|
1 | 1 | import driver::session;
|
2 | 2 | import driver::session::session;
|
3 | 3 | import middle::ty;
|
4 |
| -import syntax::{ast, visit}; |
| 4 | +import syntax::{ast, ast_util, visit}; |
5 | 5 | import syntax::attr;
|
6 | 6 | import syntax::codemap::span;
|
7 | 7 | import std::map::{map,hashmap,int_hash,hash_from_strs};
|
@@ -54,6 +54,10 @@ enum lint {
|
54 | 54 | deprecated_pattern,
|
55 | 55 | non_camel_case_types,
|
56 | 56 |
|
| 57 | + managed_heap_memory, |
| 58 | + owned_heap_memory, |
| 59 | + heap_memory, |
| 60 | + |
57 | 61 | // FIXME(#3266)--make liveness warnings lintable
|
58 | 62 | // unused_variable,
|
59 | 63 | // dead_assignment
|
@@ -140,6 +144,21 @@ fn get_lint_dict() -> lint_dict {
|
140 | 144 | desc: ~"types, variants and traits must have camel case names",
|
141 | 145 | default: allow}),
|
142 | 146 |
|
| 147 | + (~"managed_heap_memory", |
| 148 | + @{lint: managed_heap_memory, |
| 149 | + desc: ~"use of managed (@ type) heap memory", |
| 150 | + default: allow}), |
| 151 | + |
| 152 | + (~"owned_heap_memory", |
| 153 | + @{lint: owned_heap_memory, |
| 154 | + desc: ~"use of owned (~ type) heap memory", |
| 155 | + default: allow}), |
| 156 | + |
| 157 | + (~"heap_memory", |
| 158 | + @{lint: heap_memory, |
| 159 | + desc: ~"use of any (~ type or @ type) heap memory", |
| 160 | + default: allow}), |
| 161 | + |
143 | 162 | /* FIXME(#3266)--make liveness warnings lintable
|
144 | 163 | (~"unused_variable",
|
145 | 164 | @{lint: unused_variable,
|
@@ -348,6 +367,7 @@ fn check_item(i: @ast::item, cx: ty::ctxt) {
|
348 | 367 | check_item_while_true(cx, i);
|
349 | 368 | check_item_path_statement(cx, i);
|
350 | 369 | check_item_non_camel_case_types(cx, i);
|
| 370 | + check_item_heap(cx, i); |
351 | 371 | }
|
352 | 372 |
|
353 | 373 | // Take a visitor, and modify it so that it will not proceed past subitems.
|
@@ -428,6 +448,71 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) {
|
428 | 448 | }
|
429 | 449 | }
|
430 | 450 |
|
| 451 | +fn check_item_heap(cx: ty::ctxt, it: @ast::item) { |
| 452 | + |
| 453 | + fn check_type_for_lint(cx: ty::ctxt, lint: lint, |
| 454 | + node: ast::node_id, |
| 455 | + item: ast::node_id, |
| 456 | + span: span, ty: ty::t) { |
| 457 | + |
| 458 | + if get_lint_settings_level(cx.sess.lint_settings, |
| 459 | + lint, node, item) != allow { |
| 460 | + let mut n_box = 0; |
| 461 | + let mut n_uniq = 0; |
| 462 | + ty::fold_ty(cx, ty, |t| { |
| 463 | + match ty::get(t).struct { |
| 464 | + ty::ty_box(_) => n_box += 1, |
| 465 | + ty::ty_uniq(_) => n_uniq += 1, |
| 466 | + _ => () |
| 467 | + }; |
| 468 | + t |
| 469 | + }); |
| 470 | + |
| 471 | + if (n_uniq > 0 && lint != managed_heap_memory) { |
| 472 | + let s = ty_to_str(cx, ty); |
| 473 | + let m = ~"type uses owned (~ type) pointers: " + s; |
| 474 | + cx.sess.span_lint(lint, node, item, span, m); |
| 475 | + } |
| 476 | + |
| 477 | + if (n_box > 0 && lint != owned_heap_memory) { |
| 478 | + let s = ty_to_str(cx, ty); |
| 479 | + let m = ~"type uses managed (@ type) pointers: " + s; |
| 480 | + cx.sess.span_lint(lint, node, item, span, m); |
| 481 | + } |
| 482 | + } |
| 483 | + } |
| 484 | + |
| 485 | + fn check_type(cx: ty::ctxt, |
| 486 | + node: ast::node_id, |
| 487 | + item: ast::node_id, |
| 488 | + span: span, ty: ty::t) { |
| 489 | + for [managed_heap_memory, |
| 490 | + owned_heap_memory, |
| 491 | + heap_memory].each |lint| { |
| 492 | + check_type_for_lint(cx, lint, node, item, span, ty); |
| 493 | + } |
| 494 | + } |
| 495 | + |
| 496 | + match it.node { |
| 497 | + ast::item_fn(*) | |
| 498 | + ast::item_ty(*) | |
| 499 | + ast::item_enum(*) | |
| 500 | + ast::item_class(*) | |
| 501 | + ast::item_trait(*) => check_type(cx, it.id, it.id, it.span, |
| 502 | + ty::node_id_to_type(cx, it.id)), |
| 503 | + _ => () |
| 504 | + } |
| 505 | + |
| 506 | + let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ |
| 507 | + visit_expr: fn@(e: @ast::expr) { |
| 508 | + let ty = ty::expr_ty(cx, e); |
| 509 | + check_type(cx, e.id, it.id, e.span, ty); |
| 510 | + } |
| 511 | + with *visit::default_simple_visitor() |
| 512 | + })); |
| 513 | + visit::visit_item(it, (), visit); |
| 514 | +} |
| 515 | + |
431 | 516 | fn check_item_path_statement(cx: ty::ctxt, it: @ast::item) {
|
432 | 517 | let visit = item_stopping_visitor(visit::mk_simple_visitor(@{
|
433 | 518 | visit_stmt: fn@(s: @ast::stmt) {
|
|
0 commit comments