Skip to content

Commit a361dfe

Browse files
committed
---
yaml --- r: 106318 b: refs/heads/auto c: 3b04fba h: refs/heads/master v: v3
1 parent 5dbe2f0 commit a361dfe

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1183
-277
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1313
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1414
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1515
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
16-
refs/heads/auto: e12fda1c6e3bb8ac6e2b7408afda6db3c146d790
16+
refs/heads/auto: 3b04fba529860a30494a5acfbc8749bbb4fd414f
1717
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1818
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1919
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/libnative/io/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ fn translate_error(errno: i32, detail: bool) -> IoError {
9797
libc::WSAECONNREFUSED => (io::ConnectionRefused, "connection refused"),
9898
libc::WSAECONNRESET => (io::ConnectionReset, "connection reset"),
9999
libc::WSAEACCES => (io::PermissionDenied, "permission denied"),
100-
libc::WSAEWOULDBLOCK =>
101-
(io::ResourceUnavailable, "resource temporarily unavailable"),
100+
libc::WSAEWOULDBLOCK => {
101+
(io::ResourceUnavailable, "resource temporarily unavailable")
102+
}
102103
libc::WSAENOTCONN => (io::NotConnected, "not connected"),
103104
libc::WSAECONNABORTED => (io::ConnectionAborted, "connection aborted"),
104105
libc::WSAEADDRNOTAVAIL => (io::ConnectionRefused, "address not available"),

branches/auto/src/librustc/metadata/decoder.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1019,10 +1019,11 @@ pub fn get_struct_fields(intr: @IdentInterner, cdata: Cmd, id: ast::NodeId)
10191019
});
10201020
reader::tagged_docs(item, tag_item_unnamed_field, |an_item| {
10211021
let did = item_def_id(an_item, cdata);
1022+
let f = item_family(an_item);
10221023
result.push(ty::field_ty {
10231024
name: special_idents::unnamed_field.name,
10241025
id: did,
1025-
vis: ast::Inherited,
1026+
vis: struct_field_family_to_visibility(f),
10261027
});
10271028
true
10281029
});

branches/auto/src/librustc/metadata/encoder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,9 @@ fn encode_struct_fields(ebml_w: &mut writer::Encoder,
310310
encode_def_id(ebml_w, local_def(f.node.id));
311311
ebml_w.end_tag();
312312
}
313-
UnnamedField => {
313+
UnnamedField(vis) => {
314314
ebml_w.start_tag(tag_item_unnamed_field);
315+
encode_struct_field_family(ebml_w, vis);
315316
encode_def_id(ebml_w, local_def(f.node.id));
316317
ebml_w.end_tag();
317318
}
@@ -513,8 +514,7 @@ fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
513514
// If this is a newtype struct, return the constructor.
514515
match struct_def.ctor_id {
515516
Some(ctor_id) if struct_def.fields.len() > 0 &&
516-
struct_def.fields.get(0).node.kind ==
517-
ast::UnnamedField => {
517+
struct_def.fields.get(0).node.kind.is_unnamed() => {
518518
continue_ = callback(ctor_id);
519519
}
520520
_ => {}
@@ -690,7 +690,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
690690
for field in fields.iter() {
691691
let (nm, vis) = match field.node.kind {
692692
NamedField(nm, vis) => (nm, vis),
693-
UnnamedField => (special_idents::unnamed_field, Inherited)
693+
UnnamedField(vis) => (special_idents::unnamed_field, vis)
694694
};
695695

696696
let id = field.node.id;

branches/auto/src/librustc/middle/privacy.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,15 +1001,11 @@ impl<'a> SanePrivacyVisitor<'a> {
10011001
};
10021002
for f in def.fields.iter() {
10031003
match f.node.kind {
1004-
ast::NamedField(_, ast::Public) if public_def => {
1005-
tcx.sess.span_err(f.span, "unnecessary `pub` \
1006-
visibility");
1007-
}
10081004
ast::NamedField(_, ast::Private) if !public_def => {
10091005
tcx.sess.span_err(f.span, "unnecessary `priv` \
10101006
visibility");
10111007
}
1012-
ast::NamedField(..) | ast::UnnamedField => {}
1008+
ast::NamedField(..) | ast::UnnamedField(..) => {}
10131009
}
10141010
}
10151011
};
@@ -1106,7 +1102,7 @@ impl<'a> SanePrivacyVisitor<'a> {
11061102
for f in def.fields.iter() {
11071103
match f.node.kind {
11081104
ast::NamedField(_, p) => check_inherited(f.span, p),
1109-
ast::UnnamedField => {}
1105+
ast::UnnamedField(..) => {}
11101106
}
11111107
}
11121108
};

branches/auto/src/librustc/middle/trans/_match.rs

Lines changed: 81 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -256,43 +256,23 @@ enum Opt {
256256
vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
257257
}
258258

259+
fn lit_to_expr(tcx: &ty::ctxt, a: &Lit) -> @ast::Expr {
260+
match *a {
261+
ExprLit(existing_a_expr) => existing_a_expr,
262+
ConstLit(a_const) => const_eval::lookup_const_by_id(tcx, a_const).unwrap(),
263+
UnitLikeStructLit(_) => fail!("lit_to_expr: unexpected struct lit"),
264+
}
265+
}
266+
259267
fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
260268
match (a, b) {
269+
(&lit(UnitLikeStructLit(a)), &lit(UnitLikeStructLit(b))) => a == b,
261270
(&lit(a), &lit(b)) => {
262-
match (a, b) {
263-
(UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
264-
_ => {
265-
let a_expr;
266-
match a {
267-
ExprLit(existing_a_expr) => a_expr = existing_a_expr,
268-
ConstLit(a_const) => {
269-
let e = const_eval::lookup_const_by_id(tcx, a_const);
270-
a_expr = e.unwrap();
271-
}
272-
UnitLikeStructLit(_) => {
273-
fail!("UnitLikeStructLit should have been handled \
274-
above")
275-
}
276-
}
277-
278-
let b_expr;
279-
match b {
280-
ExprLit(existing_b_expr) => b_expr = existing_b_expr,
281-
ConstLit(b_const) => {
282-
let e = const_eval::lookup_const_by_id(tcx, b_const);
283-
b_expr = e.unwrap();
284-
}
285-
UnitLikeStructLit(_) => {
286-
fail!("UnitLikeStructLit should have been handled \
287-
above")
288-
}
289-
}
290-
291-
match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
292-
Some(val1) => val1 == 0,
293-
None => fail!("compare_list_exprs: type mismatch"),
294-
}
295-
}
271+
let a_expr = lit_to_expr(tcx, &a);
272+
let b_expr = lit_to_expr(tcx, &b);
273+
match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
274+
Some(val1) => val1 == 0,
275+
None => fail!("compare_list_exprs: type mismatch"),
296276
}
297277
}
298278
(&range(a1, a2), &range(b1, b2)) => {
@@ -310,6 +290,42 @@ fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
310290
}
311291
}
312292

293+
fn opt_overlap(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
294+
match (a, b) {
295+
(&lit(a), &lit(b)) => {
296+
let a_expr = lit_to_expr(tcx, &a);
297+
let b_expr = lit_to_expr(tcx, &b);
298+
match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
299+
Some(val1) => val1 == 0,
300+
None => fail!("opt_overlap: type mismatch"),
301+
}
302+
}
303+
304+
(&range(a1, a2), &range(b1, b2)) => {
305+
let m1 = const_eval::compare_lit_exprs(tcx, a1, b2);
306+
let m2 = const_eval::compare_lit_exprs(tcx, b1, a2);
307+
match (m1, m2) {
308+
// two ranges [a1, a2] and [b1, b2] overlap iff:
309+
// a1 <= b2 && b1 <= a2
310+
(Some(val1), Some(val2)) => (val1 <= 0 && val2 <= 0),
311+
_ => fail!("opt_overlap: type mismatch"),
312+
}
313+
}
314+
315+
(&range(a1, a2), &lit(b)) | (&lit(b), &range(a1, a2)) => {
316+
let b_expr = lit_to_expr(tcx, &b);
317+
let m1 = const_eval::compare_lit_exprs(tcx, a1, b_expr);
318+
let m2 = const_eval::compare_lit_exprs(tcx, a2, b_expr);
319+
match (m1, m2) {
320+
// b is in range [a1, a2] iff a1 <= b and b <= a2
321+
(Some(val1), Some(val2)) => (val1 <= 0 && 0 <= val2),
322+
_ => fail!("opt_overlap: type mismatch"),
323+
}
324+
}
325+
_ => fail!("opt_overlap: expect lit or range")
326+
}
327+
}
328+
313329
pub enum opt_result<'a> {
314330
single_result(Result<'a>),
315331
lower_bound(Result<'a>),
@@ -490,7 +506,7 @@ fn assert_is_binding_or_wild(bcx: &Block, p: @ast::Pat) {
490506
}
491507
}
492508

493-
type enter_pat<'a> = 'a |@ast::Pat| -> Option<Vec<@ast::Pat> >;
509+
type enter_pat<'a> = 'a |@ast::Pat| -> Option<Vec<@ast::Pat>>;
494510

495511
fn enter_match<'r,'b>(
496512
bcx: &'b Block<'b>,
@@ -632,16 +648,30 @@ fn enter_opt<'r,'b>(
632648
let tcx = bcx.tcx();
633649
let dummy = @ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
634650
let mut i = 0;
651+
// By the virtue of fact that we are in `trans` already, `enter_opt` is able
652+
// to prune sub-match tree aggressively based on exact equality. But when it
653+
// comes to literal or range, that strategy may lead to wrong result if there
654+
// are guard function or multiple patterns inside tuple; in that case, pruning
655+
// based on the overlap of patterns is required.
656+
//
657+
// Ideally, when constructing the sub-match tree for certain arm, only those
658+
// arms beneath it matter. But that isn't how algorithm works right now and
659+
// all other arms are taken into consideration when computing `guarded` below.
660+
// That is ok since each round of `compile_submatch` guarantees to trim one
661+
// "column" of arm patterns and the algorithm will converge.
662+
let guarded = m.iter().any(|x| x.data.arm.guard.is_some());
663+
let multi_pats = m.len() > 0 && m[0].pats.len() > 1;
635664
enter_match(bcx, tcx.def_map, m, col, val, |p| {
636665
let answer = match p.node {
637666
ast::PatEnum(..) |
638667
ast::PatIdent(_, _, None) if pat_is_const(tcx.def_map, p) => {
639668
let const_def = tcx.def_map.borrow().get_copy(&p.id);
640669
let const_def_id = ast_util::def_id_of_def(const_def);
641-
if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
642-
Some(Vec::new())
643-
} else {
644-
None
670+
let konst = lit(ConstLit(const_def_id));
671+
match guarded || multi_pats {
672+
false if opt_eq(tcx, &konst, opt) => Some(Vec::new()),
673+
true if opt_overlap(tcx, &konst, opt) => Some(Vec::new()),
674+
_ => None,
645675
}
646676
}
647677
ast::PatEnum(_, ref subpats) => {
@@ -666,10 +696,20 @@ fn enter_opt<'r,'b>(
666696
}
667697
}
668698
ast::PatLit(l) => {
669-
if opt_eq(tcx, &lit(ExprLit(l)), opt) {Some(Vec::new())} else {None}
699+
let lit_expr = lit(ExprLit(l));
700+
match guarded || multi_pats {
701+
false if opt_eq(tcx, &lit_expr, opt) => Some(Vec::new()),
702+
true if opt_overlap(tcx, &lit_expr, opt) => Some(Vec::new()),
703+
_ => None,
704+
}
670705
}
671706
ast::PatRange(l1, l2) => {
672-
if opt_eq(tcx, &range(l1, l2), opt) {Some(Vec::new())} else {None}
707+
let rng = range(l1, l2);
708+
match guarded || multi_pats {
709+
false if opt_eq(tcx, &rng, opt) => Some(Vec::new()),
710+
true if opt_overlap(tcx, &rng, opt) => Some(Vec::new()),
711+
_ => None,
712+
}
673713
}
674714
ast::PatStruct(_, ref field_pats, _) => {
675715
if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {

branches/auto/src/librustc/middle/trans/base.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,8 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
246246
pub fn decl_rust_fn(ccx: &CrateContext, has_env: bool,
247247
inputs: &[ty::t], output: ty::t,
248248
name: &str) -> ValueRef {
249+
use middle::ty::{BrAnon, ReLateBound};
250+
249251
let llfty = type_of_rust_fn(ccx, has_env, inputs, output);
250252
let llfn = decl_cdecl_fn(ccx.llmod, name, llfty, output);
251253

@@ -265,7 +267,16 @@ pub fn decl_rust_fn(ccx: &CrateContext, has_env: bool,
265267
unsafe {
266268
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
267269
}
268-
}
270+
},
271+
// When a reference in an argument has no named lifetime, it's
272+
// impossible for that reference to escape this function(ie, be
273+
// returned).
274+
ty::ty_rptr(ReLateBound(_, BrAnon(_)), _) => {
275+
debug!("marking argument of {} as nocapture because of anonymous lifetime", name);
276+
unsafe {
277+
llvm::LLVMAddAttribute(llarg, lib::llvm::NoCaptureAttribute as c_uint);
278+
}
279+
},
269280
_ => {
270281
// For non-immediate arguments the callee gets its own copy of
271282
// the value on the stack, so there are no aliases

branches/auto/src/librustc/middle/trans/callee.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::slice;
2020

2121
use back::abi;
2222
use driver::session;
23-
use lib::llvm::{ValueRef, NoAliasAttribute, StructRetAttribute};
23+
use lib::llvm::{ValueRef, NoAliasAttribute, StructRetAttribute, NoCaptureAttribute};
2424
use lib::llvm::llvm;
2525
use metadata::csearch;
2626
use middle::trans::base;
@@ -661,9 +661,15 @@ pub fn trans_call_inner<'a>(
661661
llargs.push(opt_llretslot.unwrap());
662662
}
663663

664+
// start at 1, because index 0 is the return value of the llvm func
665+
let mut first_arg_offset = 1;
666+
664667
// Push the environment (or a trait object's self).
665668
match (llenv, llself) {
666-
(Some(llenv), None) => llargs.push(llenv),
669+
(Some(llenv), None) => {
670+
first_arg_offset += 1;
671+
llargs.push(llenv)
672+
},
667673
(None, Some(llself)) => llargs.push(llself),
668674
_ => {}
669675
}
@@ -682,6 +688,11 @@ pub fn trans_call_inner<'a>(
682688
let mut attrs = Vec::new();
683689
if type_of::return_uses_outptr(ccx, ret_ty) {
684690
attrs.push((1, StructRetAttribute));
691+
// The outptr can be noalias and nocapture because it's entirely
692+
// invisible to the program.
693+
attrs.push((1, NoAliasAttribute));
694+
attrs.push((1, NoCaptureAttribute));
695+
first_arg_offset += 1;
685696
}
686697

687698
// The `noalias` attribute on the return value is useful to a
@@ -695,6 +706,30 @@ pub fn trans_call_inner<'a>(
695706
_ => {}
696707
}
697708

709+
debug!("trans_callee_inner: first_arg_offset={}", first_arg_offset);
710+
711+
for (idx, &t) in ty::ty_fn_args(callee_ty).iter().enumerate()
712+
.map(|(i, v)| (i+first_arg_offset, v)) {
713+
use middle::ty::{BrAnon, ReLateBound};
714+
if !type_is_immediate(ccx, t) {
715+
// if it's not immediate, we have a program-invisible pointer,
716+
// which it can't possibly capture
717+
attrs.push((idx, NoCaptureAttribute));
718+
debug!("trans_callee_inner: argument {} nocapture because it's non-immediate", idx);
719+
continue;
720+
}
721+
722+
let t_ = ty::get(t);
723+
match t_.sty {
724+
ty::ty_rptr(ReLateBound(_, BrAnon(_)), _) => {
725+
debug!("trans_callee_inner: argument {} nocapture because \
726+
of anonymous lifetime", idx);
727+
attrs.push((idx, NoCaptureAttribute));
728+
},
729+
_ => { }
730+
}
731+
}
732+
698733
// Invoke the actual rust fn and update bcx/llresult.
699734
let (llret, b) = base::invoke(bcx,
700735
llfn,

branches/auto/src/librustc/middle/ty.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3900,7 +3900,7 @@ impl VariantInfo {
39003900
let arg_names = fields.iter().map(|field| {
39013901
match field.node.kind {
39023902
NamedField(ident, _) => ident,
3903-
UnnamedField => cx.sess.bug(
3903+
UnnamedField(..) => cx.sess.bug(
39043904
"enum_variants: all fields in struct must have a name")
39053905
}
39063906
}).collect();
@@ -4264,11 +4264,11 @@ fn struct_field_tys(fields: &[StructField]) -> Vec<field_ty> {
42644264
vis: visibility,
42654265
}
42664266
}
4267-
UnnamedField => {
4267+
UnnamedField(visibility) => {
42684268
field_ty {
42694269
name: syntax::parse::token::special_idents::unnamed_field.name,
42704270
id: ast_util::local_def(field.node.id),
4271-
vis: ast::Public,
4271+
vis: visibility,
42724272
}
42734273
}
42744274
}

branches/auto/src/librustc/middle/typeck/collect.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
695695
write_ty_to_tcx(tcx, ctor_id, selfty);
696696

697697
tcx.tcache.borrow_mut().insert(local_def(ctor_id), tpt);
698-
} else if struct_def.fields.get(0).node.kind ==
699-
ast::UnnamedField {
698+
} else if struct_def.fields.get(0).node.kind.is_unnamed() {
700699
// Tuple-like.
701700
let inputs = struct_def.fields.map(
702701
|field| tcx.tcache.borrow().get(

0 commit comments

Comments
 (0)