Skip to content

Commit 781b806

Browse files
committed
---
yaml --- r: 31389 b: refs/heads/dist-snap c: cc8086a h: refs/heads/master i: 31387: d830bda v: v3
1 parent 38745e6 commit 781b806

File tree

3 files changed

+162
-22
lines changed

3 files changed

+162
-22
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: d0c6ce338884ee21843f4b40bf6bf18d222ce5df
99
refs/heads/incoming: d9317a174e434d4c99fc1a37fd7dc0d2f5328d37
10-
refs/heads/dist-snap: 99674dc52b45a22b49f13242be9d931009b4f276
10+
refs/heads/dist-snap: cc8086a045abf1aaac29c3d33b1a18a9ae67a58d
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1212
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/dist-snap/src/rustc/middle/lint.rs

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import syntax::codemap::span;
77
import std::map::{map,hashmap,int_hash,hash_from_strs};
88
import std::smallintmap::{map,smallintmap};
99
import io::writer_util;
10-
import syntax::print::pprust::expr_to_str;
10+
import util::ppaux::{ty_to_str};
11+
import syntax::print::pprust::{expr_to_str, mode_to_str};
1112
export lint, ctypes, unused_imports, while_true, path_statement, old_vecs;
1213
export unrecognized_warning, non_implicitly_copyable_typarams;
1314
export vecs_not_implicitly_copyable, implicit_copies;
@@ -47,6 +48,7 @@ enum lint {
4748
unrecognized_warning,
4849
non_implicitly_copyable_typarams,
4950
vecs_not_implicitly_copyable,
51+
deprecated_mode,
5052
}
5153

5254
// This is pretty unfortunate. We really want some sort of "deriving Enum"
@@ -61,6 +63,7 @@ fn int_to_lint(i: int) -> lint {
6163
5 { unrecognized_warning }
6264
6 { non_implicitly_copyable_typarams }
6365
7 { vecs_not_implicitly_copyable }
66+
8 { deprecated_mode }
6467
}
6568
}
6669

@@ -119,8 +122,12 @@ fn get_lint_dict() -> lint_dict {
119122
(~"implicit_copies",
120123
@{lint: implicit_copies,
121124
desc: ~"implicit copies of non implicitly copyable data",
122-
default: warn})
125+
default: warn}),
123126

127+
(~"deprecated_mode",
128+
@{lint: deprecated_mode,
129+
desc: ~"warn about deprecated uses of modes",
130+
default: ignore})
124131
];
125132
hash_from_strs(v)
126133
}
@@ -411,10 +418,56 @@ fn check_item_path_statement(cx: ty::ctxt, it: @ast::item) {
411418
visit::visit_item(it, (), visit);
412419
}
413420

421+
fn check_fn(tcx: ty::ctxt, fk: visit::fn_kind, decl: ast::fn_decl,
422+
_body: ast::blk, span: span, id: ast::node_id) {
423+
#debug["lint check_fn fk=%? id=%?", fk, id];
424+
let fn_ty = ty::node_id_to_type(tcx, id);
425+
alt check ty::get(fn_ty).struct {
426+
ty::ty_fn(fn_ty) {
427+
let mut counter = 0;
428+
do vec::iter2(fn_ty.inputs, decl.inputs) |arg_ty, arg_ast| {
429+
counter += 1;
430+
#debug["arg %d, ty=%s, mode=%s",
431+
counter,
432+
ty_to_str(tcx, arg_ty.ty),
433+
mode_to_str(arg_ast.mode)];
434+
alt arg_ast.mode {
435+
ast::expl(ast::by_copy) => {
436+
/* always allow by-copy */
437+
}
438+
439+
ast::expl(_) => {
440+
tcx.sess.span_lint(
441+
deprecated_mode, id, id,
442+
span,
443+
#fmt["argument %d uses an explicit mode", counter]);
444+
}
445+
446+
ast::infer(_) {
447+
let kind = ty::type_kind(tcx, arg_ty.ty);
448+
if !ty::kind_is_safe_for_default_mode(kind) {
449+
tcx.sess.span_lint(
450+
deprecated_mode, id, id,
451+
span,
452+
#fmt["argument %d uses the default mode \
453+
but shouldn't",
454+
counter]);
455+
}
456+
}
457+
}
458+
}
459+
}
460+
}
461+
}
462+
414463
fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
415464

416465
let v = visit::mk_simple_visitor(@{
417-
visit_item: fn@(it: @ast::item) { check_item(it, tcx); }
466+
visit_item:
467+
|it| check_item(it, tcx),
468+
visit_fn:
469+
|fk, decl, body, span, id| check_fn(tcx, fk, decl, body,
470+
span, id),
418471
with *visit::default_simple_visitor()
419472
});
420473
visit::visit_crate(*crate, (), v);

branches/dist-snap/src/rustc/middle/ty.rs

Lines changed: 105 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export ty_fn_args;
110110
export kind, kind_implicitly_copyable, kind_send_copy, kind_copyable;
111111
export kind_noncopyable, kind_const;
112112
export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied;
113+
export kind_is_safe_for_default_mode;
113114
export kind_is_owned;
114115
export proto_kind, kind_lteq, type_kind;
115116
export operators;
@@ -1371,19 +1372,22 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
13711372
enum kind { kind_(u32) }
13721373

13731374
/// can be copied (implicitly or explicitly)
1374-
const KIND_MASK_COPY : u32 = 0b00000000000000000000000000000001_u32;
1375+
const KIND_MASK_COPY : u32 = 0b000000000000000000000000001_u32;
13751376

13761377
/// can be sent: no shared box, borrowed ptr (must imply OWNED)
1377-
const KIND_MASK_SEND : u32 = 0b00000000000000000000000000000010_u32;
1378+
const KIND_MASK_SEND : u32 = 0b000000000000000000000000010_u32;
13781379

13791380
/// is owned (no borrowed ptrs)
1380-
const KIND_MASK_OWNED : u32 = 0b00000000000000000000000000000100_u32;
1381+
const KIND_MASK_OWNED : u32 = 0b000000000000000000000000100_u32;
13811382

13821383
/// is deeply immutable
1383-
const KIND_MASK_CONST : u32 = 0b00000000000000000000000000001000_u32;
1384+
const KIND_MASK_CONST : u32 = 0b000000000000000000000001000_u32;
13841385

13851386
/// can be implicitly copied (must imply COPY)
1386-
const KIND_MASK_IMPLICIT : u32 = 0b00000000000000000000000000010000_u32;
1387+
const KIND_MASK_IMPLICIT : u32 = 0b000000000000000000000010000_u32;
1388+
1389+
/// safe for default mode (subset of KIND_MASK_IMPLICIT)
1390+
const KIND_MASK_DEFAULT_MODE : u32 = 0b000000000000000000000100000_u32;
13871391

13881392
fn kind_noncopyable() -> kind {
13891393
kind_(0u32)
@@ -1397,10 +1401,22 @@ fn kind_implicitly_copyable() -> kind {
13971401
kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY)
13981402
}
13991403

1404+
fn kind_safe_for_default_mode() -> kind {
1405+
// similar to implicit copy, but always includes vectors and strings
1406+
kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY)
1407+
}
1408+
14001409
fn kind_implicitly_sendable() -> kind {
14011410
kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_SEND)
14021411
}
14031412

1413+
fn kind_safe_for_default_mode_send() -> kind {
1414+
// similar to implicit copy, but always includes vectors and strings
1415+
kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT |
1416+
KIND_MASK_COPY | KIND_MASK_SEND)
1417+
}
1418+
1419+
14041420
fn kind_send_copy() -> kind {
14051421
kind_(KIND_MASK_COPY | KIND_MASK_SEND)
14061422
}
@@ -1426,7 +1442,7 @@ fn remove_const(k: kind) -> kind {
14261442
}
14271443

14281444
fn remove_implicit(k: kind) -> kind {
1429-
k - kind_(KIND_MASK_IMPLICIT)
1445+
k - kind_(KIND_MASK_IMPLICIT | KIND_MASK_DEFAULT_MODE)
14301446
}
14311447

14321448
fn remove_send(k: kind) -> kind {
@@ -1462,6 +1478,10 @@ pure fn kind_can_be_implicitly_copied(k: kind) -> bool {
14621478
*k & KIND_MASK_IMPLICIT == KIND_MASK_IMPLICIT
14631479
}
14641480

1481+
pure fn kind_is_safe_for_default_mode(k: kind) -> bool {
1482+
*k & KIND_MASK_DEFAULT_MODE == KIND_MASK_DEFAULT_MODE
1483+
}
1484+
14651485
pure fn kind_can_be_copied(k: kind) -> bool {
14661486
*k & KIND_MASK_COPY == KIND_MASK_COPY
14671487
}
@@ -1478,9 +1498,9 @@ fn proto_kind(p: proto) -> kind {
14781498
alt p {
14791499
ast::proto_any { kind_noncopyable() }
14801500
ast::proto_block { kind_noncopyable() }
1481-
ast::proto_box { kind_implicitly_copyable() | kind_owned() }
1501+
ast::proto_box { kind_safe_for_default_mode() | kind_owned() }
14821502
ast::proto_uniq { kind_send_copy() | kind_owned() }
1483-
ast::proto_bare { kind_implicitly_sendable() | kind_const() |
1503+
ast::proto_bare { kind_safe_for_default_mode_send() | kind_const() |
14841504
kind_owned() }
14851505
}
14861506
}
@@ -1539,11 +1559,11 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
15391559
// Insert a default in case we loop back on self recursively.
15401560
cx.kind_cache.insert(ty, kind_top());
15411561

1542-
let result = alt get(ty).struct {
1562+
let mut result = alt get(ty).struct {
15431563
// Scalar and unique types are sendable, constant, and owned
15441564
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
15451565
ty_ptr(_) {
1546-
kind_implicitly_sendable() | kind_const() | kind_owned()
1566+
kind_safe_for_default_mode_send() | kind_const() | kind_owned()
15471567
}
15481568

15491569
// Implicit copyability of strs is configurable
@@ -1561,14 +1581,14 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
15611581
// Those with refcounts raise noncopyable to copyable,
15621582
// lower sendable to copyable. Therefore just set result to copyable.
15631583
ty_box(tm) {
1564-
remove_send(mutable_type_kind(cx, tm) | kind_implicitly_copyable())
1584+
remove_send(mutable_type_kind(cx, tm) | kind_safe_for_default_mode())
15651585
}
15661586

15671587
// Iface instances are (for now) like shared boxes, basically
1568-
ty_trait(_, _) { kind_implicitly_copyable() | kind_owned() }
1588+
ty_trait(_, _) { kind_safe_for_default_mode() | kind_owned() }
15691589

15701590
// Region pointers are copyable but NOT owned nor sendable
1571-
ty_rptr(_, _) { kind_implicitly_copyable() }
1591+
ty_rptr(_, _) { kind_safe_for_default_mode() }
15721592

15731593
// Unique boxes and vecs have the kind of their contained type,
15741594
// but unique boxes can't be implicitly copyable.
@@ -1587,10 +1607,10 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
15871607
// contained type, but aren't implicitly copyable. Fixed vectors have
15881608
// the kind of the element they contain, taking mutability into account.
15891609
ty_evec(tm, vstore_box) {
1590-
remove_send(kind_implicitly_copyable() | mutable_type_kind(cx, tm))
1610+
remove_send(kind_safe_for_default_mode() | mutable_type_kind(cx, tm))
15911611
}
15921612
ty_evec(tm, vstore_slice(_)) {
1593-
remove_owned_send(kind_implicitly_copyable() |
1613+
remove_owned_send(kind_safe_for_default_mode() |
15941614
mutable_type_kind(cx, tm))
15951615
}
15961616
ty_evec(tm, vstore_fixed(_)) {
@@ -1599,13 +1619,13 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
15991619

16001620
// All estrs are copyable; uniques and interiors are sendable.
16011621
ty_estr(vstore_box) {
1602-
kind_implicitly_copyable() | kind_const() | kind_owned()
1622+
kind_safe_for_default_mode() | kind_const() | kind_owned()
16031623
}
16041624
ty_estr(vstore_slice(_)) {
1605-
kind_implicitly_copyable() | kind_const()
1625+
kind_safe_for_default_mode() | kind_const()
16061626
}
16071627
ty_estr(vstore_fixed(_)) {
1608-
kind_implicitly_sendable() | kind_const() | kind_owned()
1628+
kind_safe_for_default_mode_send() | kind_const() | kind_owned()
16091629
}
16101630

16111631
// Records lower to the lowest of their members.
@@ -1676,10 +1696,77 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
16761696
}
16771697
};
16781698

1699+
// arbitrary threshold to prevent by-value copying of big records
1700+
if kind_is_safe_for_default_mode(result) {
1701+
if type_size(cx, ty) > 4 {
1702+
result -= kind_(KIND_MASK_DEFAULT_MODE);
1703+
}
1704+
}
1705+
16791706
cx.kind_cache.insert(ty, result);
16801707
ret result;
16811708
}
16821709

1710+
/// gives a rough estimate of how much space it takes to represent
1711+
/// an instance of `ty`. Used for the mode transition.
1712+
fn type_size(cx: ctxt, ty: t) -> uint {
1713+
alt get(ty).struct {
1714+
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1715+
ty_ptr(_) | ty_box(_) | ty_uniq(_) | ty_estr(vstore_uniq) |
1716+
ty_trait(*) | ty_rptr(*) | ty_evec(_, vstore_uniq) |
1717+
ty_evec(_, vstore_box) | ty_estr(vstore_box) => {
1718+
1
1719+
}
1720+
1721+
ty_evec(_, vstore_slice(_)) |
1722+
ty_estr(vstore_slice(_)) |
1723+
ty_fn(_) => {
1724+
2
1725+
}
1726+
1727+
ty_evec(t, vstore_fixed(n)) => {
1728+
type_size(cx, t.ty) * n
1729+
}
1730+
1731+
ty_estr(vstore_fixed(n)) => {
1732+
n
1733+
}
1734+
1735+
ty_rec(flds) => {
1736+
flds.foldl(0, |s, f| s + type_size(cx, f.mt.ty))
1737+
}
1738+
1739+
ty_class(did, substs) {
1740+
let flds = class_items_as_fields(cx, did, substs);
1741+
flds.foldl(0, |s, f| s + type_size(cx, f.mt.ty))
1742+
}
1743+
1744+
ty_tup(tys) {
1745+
tys.foldl(0, |s, t| s + type_size(cx, t))
1746+
}
1747+
1748+
ty_enum(did, substs) {
1749+
let variants = substd_enum_variants(cx, did, substs);
1750+
variants.foldl( // find max size of any variant
1751+
0,
1752+
|m, v| uint::max(m,
1753+
// find size of this variant:
1754+
v.args.foldl(0, |s, a| s + type_size(cx, a))))
1755+
}
1756+
1757+
ty_param(_) | ty_self {
1758+
1
1759+
}
1760+
1761+
ty_var(_) | ty_var_integral(_) {
1762+
cx.sess.bug(~"Asked to compute kind of a type variable");
1763+
}
1764+
ty_type | ty_opaque_closure_ptr(_) | ty_opaque_box | ty_unboxed_vec(_) {
1765+
cx.sess.bug(~"Asked to compute kind of fictitious type");
1766+
}
1767+
}
1768+
}
1769+
16831770
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
16841771
fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
16851772

0 commit comments

Comments
 (0)