Port privacy.rs from oldvisit to <V:Visitor> trait.
This commit is contained in:
parent
b97cc955c2
commit
18be88f64a
1 changed files with 146 additions and 133 deletions
|
|
@ -34,54 +34,57 @@ use syntax::ast_util::{variant_visibility_to_privacy, visibility_to_privacy};
|
|||
use syntax::attr;
|
||||
use syntax::codemap::span;
|
||||
use syntax::parse::token;
|
||||
use syntax::oldvisit;
|
||||
use syntax::visit;
|
||||
use syntax::visit::Visitor;
|
||||
use syntax::ast::{_mod,expr,item,Block,pat};
|
||||
|
||||
pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||
method_map: &'mm method_map,
|
||||
crate: &ast::Crate) {
|
||||
let privileged_items = @mut ~[];
|
||||
struct PrivacyVisitor {
|
||||
tcx: ty::ctxt,
|
||||
privileged_items: @mut ~[NodeId],
|
||||
}
|
||||
|
||||
impl PrivacyVisitor {
|
||||
// Adds an item to its scope.
|
||||
let add_privileged_item: @fn(@ast::item, &mut uint) = |item, count| {
|
||||
fn add_privileged_item(&mut self, item: @ast::item, count: &mut uint) {
|
||||
match item.node {
|
||||
item_struct(*) | item_trait(*) | item_enum(*) |
|
||||
item_fn(*) => {
|
||||
privileged_items.push(item.id);
|
||||
self.privileged_items.push(item.id);
|
||||
*count += 1;
|
||||
}
|
||||
item_impl(_, _, _, ref methods) => {
|
||||
for method in methods.iter() {
|
||||
privileged_items.push(method.id);
|
||||
self.privileged_items.push(method.id);
|
||||
*count += 1;
|
||||
}
|
||||
privileged_items.push(item.id);
|
||||
self.privileged_items.push(item.id);
|
||||
*count += 1;
|
||||
}
|
||||
item_foreign_mod(ref foreign_mod) => {
|
||||
for foreign_item in foreign_mod.items.iter() {
|
||||
privileged_items.push(foreign_item.id);
|
||||
self.privileged_items.push(foreign_item.id);
|
||||
*count += 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Adds items that are privileged to this scope.
|
||||
let add_privileged_items: @fn(&[@ast::item]) -> uint = |items| {
|
||||
fn add_privileged_items(&mut self, items: &[@ast::item]) -> uint {
|
||||
let mut count = 0;
|
||||
for &item in items.iter() {
|
||||
add_privileged_item(item, &mut count);
|
||||
self.add_privileged_item(item, &mut count);
|
||||
}
|
||||
count
|
||||
};
|
||||
}
|
||||
|
||||
// Checks that an enum variant is in scope
|
||||
let check_variant: @fn(span: span, enum_id: ast::def_id) =
|
||||
|span, enum_id| {
|
||||
let variant_info = ty::enum_variants(tcx, enum_id)[0];
|
||||
fn check_variant(&mut self, span: span, enum_id: ast::def_id) {
|
||||
let variant_info = ty::enum_variants(self.tcx, enum_id)[0];
|
||||
let parental_privacy = if is_local(enum_id) {
|
||||
let parent_vis = ast_map::node_item_query(tcx.items, enum_id.node,
|
||||
let parent_vis = ast_map::node_item_query(self.tcx.items,
|
||||
enum_id.node,
|
||||
|it| { it.vis },
|
||||
~"unbound enum parent when checking \
|
||||
dereference of enum type");
|
||||
|
|
@ -99,15 +102,14 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
if variant_visibility_to_privacy(variant_info.vis,
|
||||
parental_privacy == Public)
|
||||
== Private {
|
||||
tcx.sess.span_err(span,
|
||||
self.tcx.sess.span_err(span,
|
||||
"can only dereference enums \
|
||||
with a single, public variant");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Returns true if a crate-local method is private and false otherwise.
|
||||
let method_is_private: @fn(span: span, method_id: NodeId) -> bool =
|
||||
|span, method_id| {
|
||||
fn method_is_private(&mut self, span: span, method_id: NodeId) -> bool {
|
||||
let check = |vis: visibility, container_id: def_id| {
|
||||
let mut is_private = false;
|
||||
if vis == private {
|
||||
|
|
@ -117,12 +119,12 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
} else {
|
||||
// Look up the enclosing impl.
|
||||
if container_id.crate != LOCAL_CRATE {
|
||||
tcx.sess.span_bug(span,
|
||||
self.tcx.sess.span_bug(span,
|
||||
"local method isn't in local \
|
||||
impl?!");
|
||||
}
|
||||
|
||||
match tcx.items.find(&container_id.node) {
|
||||
match self.tcx.items.find(&container_id.node) {
|
||||
Some(&node_item(item, _)) => {
|
||||
match item.node {
|
||||
item_impl(_, None, _, _)
|
||||
|
|
@ -133,10 +135,10 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.sess.span_bug(span, "impl wasn't an item?!");
|
||||
self.tcx.sess.span_bug(span, "impl wasn't an item?!");
|
||||
}
|
||||
None => {
|
||||
tcx.sess.span_bug(span, "impl wasn't in AST map?!");
|
||||
self.tcx.sess.span_bug(span, "impl wasn't in AST map?!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -144,7 +146,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
is_private
|
||||
};
|
||||
|
||||
match tcx.items.find(&method_id) {
|
||||
match self.tcx.items.find(&method_id) {
|
||||
Some(&node_method(method, impl_id, _)) => {
|
||||
check(method.vis, impl_id)
|
||||
}
|
||||
|
|
@ -155,26 +157,25 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.sess.span_bug(span,
|
||||
self.tcx.sess.span_bug(span,
|
||||
fmt!("method_is_private: method was a %s?!",
|
||||
ast_map::node_id_to_str(
|
||||
tcx.items,
|
||||
self.tcx.items,
|
||||
method_id,
|
||||
token::get_ident_interner())));
|
||||
}
|
||||
None => {
|
||||
tcx.sess.span_bug(span, "method not found in \
|
||||
self.tcx.sess.span_bug(span, "method not found in \
|
||||
AST map?!");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Returns true if the given local item is private and false otherwise.
|
||||
let local_item_is_private: @fn(span: span, item_id: NodeId) -> bool =
|
||||
|span, item_id| {
|
||||
fn local_item_is_private(&mut self, span: span, item_id: NodeId) -> bool {
|
||||
let mut f: &fn(NodeId) -> bool = |_| false;
|
||||
f = |item_id| {
|
||||
match tcx.items.find(&item_id) {
|
||||
match self.tcx.items.find(&item_id) {
|
||||
Some(&node_item(item, _)) => item.vis != public,
|
||||
Some(&node_foreign_item(*)) => false,
|
||||
Some(&node_method(method, impl_did, _)) => {
|
||||
|
|
@ -186,104 +187,96 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
Some(&node_trait_method(_, trait_did, _)) => f(trait_did.node),
|
||||
Some(_) => {
|
||||
tcx.sess.span_bug(span,
|
||||
self.tcx.sess.span_bug(span,
|
||||
fmt!("local_item_is_private: item was \
|
||||
a %s?!",
|
||||
ast_map::node_id_to_str(
|
||||
tcx.items,
|
||||
self.tcx.items,
|
||||
item_id,
|
||||
token::get_ident_interner())));
|
||||
}
|
||||
None => {
|
||||
tcx.sess.span_bug(span, "item not found in AST map?!");
|
||||
self.tcx.sess.span_bug(span, "item not found in AST map?!");
|
||||
}
|
||||
}
|
||||
};
|
||||
f(item_id)
|
||||
};
|
||||
}
|
||||
|
||||
// Checks that a private field is in scope.
|
||||
let check_field: @fn(span: span, id: ast::def_id, ident: ast::ident) =
|
||||
|span, id, ident| {
|
||||
let fields = ty::lookup_struct_fields(tcx, id);
|
||||
fn check_field(&mut self, span: span, id: ast::def_id, ident: ast::ident) {
|
||||
let fields = ty::lookup_struct_fields(self.tcx, id);
|
||||
for field in fields.iter() {
|
||||
if field.ident != ident { loop; }
|
||||
if field.vis == private {
|
||||
tcx.sess.span_err(span, fmt!("field `%s` is private",
|
||||
self.tcx.sess.span_err(span, fmt!("field `%s` is private",
|
||||
token::ident_to_str(&ident)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Given the ID of a method, checks to ensure it's in scope.
|
||||
let check_method_common: @fn(span: span,
|
||||
method_id: def_id,
|
||||
name: &ident) =
|
||||
|span, method_id, name| {
|
||||
fn check_method_common(&mut self, span: span, method_id: def_id, name: &ident) {
|
||||
// If the method is a default method, we need to use the def_id of
|
||||
// the default implementation.
|
||||
// Having to do this this is really unfortunate.
|
||||
let method_id = ty::method(tcx, method_id).provided_source
|
||||
let method_id = ty::method(self.tcx, method_id).provided_source
|
||||
.unwrap_or_default(method_id);
|
||||
|
||||
if method_id.crate == LOCAL_CRATE {
|
||||
let is_private = method_is_private(span, method_id.node);
|
||||
let container_id = ty::method(tcx, method_id).container_id;
|
||||
let is_private = self.method_is_private(span, method_id.node);
|
||||
let container_id = ty::method(self.tcx, method_id).container_id;
|
||||
if is_private &&
|
||||
(container_id.crate != LOCAL_CRATE ||
|
||||
!privileged_items.iter().any(|x| x == &(container_id.node))) {
|
||||
tcx.sess.span_err(span,
|
||||
!self.privileged_items.iter().any(|x| x == &(container_id.node))) {
|
||||
self.tcx.sess.span_err(span,
|
||||
fmt!("method `%s` is private",
|
||||
token::ident_to_str(name)));
|
||||
}
|
||||
} else {
|
||||
let visibility =
|
||||
csearch::get_item_visibility(tcx.sess.cstore, method_id);
|
||||
csearch::get_item_visibility(self.tcx.sess.cstore, method_id);
|
||||
if visibility != public {
|
||||
tcx.sess.span_err(span,
|
||||
self.tcx.sess.span_err(span,
|
||||
fmt!("method `%s` is private",
|
||||
token::ident_to_str(name)));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Checks that a private path is in scope.
|
||||
let check_path: @fn(span: span, def: def, path: &Path) =
|
||||
|span, def, path| {
|
||||
fn check_path(&mut self, span: span, def: def, path: &Path) {
|
||||
debug!("checking path");
|
||||
match def {
|
||||
def_static_method(method_id, _, _) => {
|
||||
debug!("found static method def, checking it");
|
||||
check_method_common(span, method_id, path.idents.last())
|
||||
self.check_method_common(span, method_id, path.idents.last())
|
||||
}
|
||||
def_fn(def_id, _) => {
|
||||
if def_id.crate == LOCAL_CRATE {
|
||||
if local_item_is_private(span, def_id.node) &&
|
||||
!privileged_items.iter().any(|x| x == &def_id.node) {
|
||||
tcx.sess.span_err(span,
|
||||
if self.local_item_is_private(span, def_id.node) &&
|
||||
!self.privileged_items.iter().any(|x| x == &def_id.node) {
|
||||
self.tcx.sess.span_err(span,
|
||||
fmt!("function `%s` is private",
|
||||
token::ident_to_str(path.idents.last())));
|
||||
}
|
||||
} else if csearch::get_item_visibility(tcx.sess.cstore,
|
||||
} else if csearch::get_item_visibility(self.tcx.sess.cstore,
|
||||
def_id) != public {
|
||||
tcx.sess.span_err(span,
|
||||
self.tcx.sess.span_err(span,
|
||||
fmt!("function `%s` is private",
|
||||
token::ident_to_str(path.idents.last())));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Checks that a private method is in scope.
|
||||
let check_method: @fn(span: span,
|
||||
origin: &method_origin,
|
||||
ident: ast::ident) =
|
||||
|span, origin, ident| {
|
||||
fn check_method(&mut self, span: span, origin: &method_origin, ident: ast::ident) {
|
||||
match *origin {
|
||||
method_static(method_id) => {
|
||||
check_method_common(span, method_id, &ident)
|
||||
self.check_method_common(span, method_id, &ident)
|
||||
}
|
||||
method_param(method_param {
|
||||
trait_id: trait_id,
|
||||
|
|
@ -292,19 +285,20 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}) |
|
||||
method_trait(trait_id, method_num) => {
|
||||
if trait_id.crate == LOCAL_CRATE {
|
||||
match tcx.items.find(&trait_id.node) {
|
||||
match self.tcx.items.find(&trait_id.node) {
|
||||
Some(&node_item(item, _)) => {
|
||||
match item.node {
|
||||
item_trait(_, _, ref methods) => {
|
||||
if method_num >= (*methods).len() {
|
||||
tcx.sess.span_bug(span, "method number out of range?!");
|
||||
self.tcx.sess.span_bug(span,
|
||||
"method number out of range?!");
|
||||
}
|
||||
match (*methods)[method_num] {
|
||||
provided(method)
|
||||
if method.vis == private &&
|
||||
!privileged_items.iter()
|
||||
!self.privileged_items.iter()
|
||||
.any(|x| x == &(trait_id.node)) => {
|
||||
tcx.sess.span_err(span,
|
||||
self.tcx.sess.span_err(span,
|
||||
fmt!("method `%s` is private",
|
||||
token::ident_to_str(&method
|
||||
.ident)));
|
||||
|
|
@ -316,15 +310,16 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_bug(span, "trait wasn't actually a trait?!");
|
||||
self.tcx.sess.span_bug(span, "trait wasn't actually a trait?!");
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(_) => {
|
||||
tcx.sess.span_bug(span, "trait wasn't an item?!");
|
||||
self.tcx.sess.span_bug(span, "trait wasn't an item?!");
|
||||
}
|
||||
None => {
|
||||
tcx.sess.span_bug(span, "trait item wasn't found in the AST map?!");
|
||||
self.tcx.sess.span_bug(span,
|
||||
"trait item wasn't found in the AST map?!");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -332,30 +327,35 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let visitor = oldvisit::mk_vt(@oldvisit::Visitor {
|
||||
visit_mod: |the_module, span, node_id, (method_map, visitor)| {
|
||||
let n_added = add_privileged_items(the_module.items);
|
||||
impl<'self> Visitor<&'self method_map> for PrivacyVisitor {
|
||||
|
||||
oldvisit::visit_mod(the_module,
|
||||
span,
|
||||
node_id,
|
||||
(method_map, visitor));
|
||||
fn visit_mod<'mm>(&mut self, the_module:&_mod, _:span, _:NodeId,
|
||||
method_map:&'mm method_map) {
|
||||
|
||||
let n_added = self.add_privileged_items(the_module.items);
|
||||
|
||||
visit::walk_mod(self, the_module, method_map);
|
||||
|
||||
do n_added.times {
|
||||
ignore(privileged_items.pop());
|
||||
ignore(self.privileged_items.pop());
|
||||
}
|
||||
},
|
||||
visit_item: |item, (method_map, visitor)| {
|
||||
}
|
||||
|
||||
fn visit_item<'mm>(&mut self, item:@item, method_map:&'mm method_map) {
|
||||
|
||||
// Do not check privacy inside items with the resolve_unexported
|
||||
// attribute. This is used for the test runner.
|
||||
if !attr::contains_name(item.attrs, "!resolve_unexported") {
|
||||
check_sane_privacy(tcx, item);
|
||||
oldvisit::visit_item(item, (method_map, visitor));
|
||||
check_sane_privacy(self.tcx, item);
|
||||
visit::walk_item(self, item, method_map);
|
||||
}
|
||||
},
|
||||
visit_block: |block, (method_map, visitor)| {
|
||||
}
|
||||
|
||||
fn visit_block<'mm>(&mut self, block:&Block, method_map:&'mm method_map) {
|
||||
|
||||
// Gather up all the privileged items.
|
||||
let mut n_added = 0;
|
||||
for stmt in block.stmts.iter() {
|
||||
|
|
@ -363,7 +363,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
stmt_decl(decl, _) => {
|
||||
match decl.node {
|
||||
decl_item(item) => {
|
||||
add_privileged_item(item, &mut n_added);
|
||||
self.add_privileged_item(item, &mut n_added);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -372,15 +372,16 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
|
||||
oldvisit::visit_block(block, (method_map, visitor));
|
||||
visit::walk_block(self, block, method_map);
|
||||
|
||||
do n_added.times {
|
||||
ignore(privileged_items.pop());
|
||||
ignore(self.privileged_items.pop());
|
||||
}
|
||||
},
|
||||
visit_expr: |expr,
|
||||
(method_map, visitor):
|
||||
(&'mm method_map, oldvisit::vt<&'mm method_map>)| {
|
||||
|
||||
}
|
||||
|
||||
fn visit_expr<'mm>(&mut self, expr:@expr, method_map:&'mm method_map) {
|
||||
|
||||
match expr.node {
|
||||
expr_field(base, ident, _) => {
|
||||
// Method calls are now a special syntactic form,
|
||||
|
|
@ -389,35 +390,35 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
|
||||
// With type_autoderef, make sure we don't
|
||||
// allow pointers to violate privacy
|
||||
match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
|
||||
match ty::get(ty::type_autoderef(self.tcx, ty::expr_ty(self.tcx,
|
||||
base))).sty {
|
||||
ty_struct(id, _)
|
||||
if id.crate != LOCAL_CRATE || !privileged_items.iter()
|
||||
if id.crate != LOCAL_CRATE || !self.privileged_items.iter()
|
||||
.any(|x| x == &(id.node)) => {
|
||||
debug!("(privacy checking) checking field access");
|
||||
check_field(expr.span, id, ident);
|
||||
self.check_field(expr.span, id, ident);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
expr_method_call(_, base, ident, _, _, _) => {
|
||||
// Ditto
|
||||
match ty::get(ty::type_autoderef(tcx, ty::expr_ty(tcx,
|
||||
match ty::get(ty::type_autoderef(self.tcx, ty::expr_ty(self.tcx,
|
||||
base))).sty {
|
||||
ty_enum(id, _) |
|
||||
ty_struct(id, _)
|
||||
if id.crate != LOCAL_CRATE ||
|
||||
!privileged_items.iter().any(|x| x == &(id.node)) => {
|
||||
!self.privileged_items.iter().any(|x| x == &(id.node)) => {
|
||||
match method_map.find(&expr.id) {
|
||||
None => {
|
||||
tcx.sess.span_bug(expr.span,
|
||||
self.tcx.sess.span_bug(expr.span,
|
||||
"method call not in \
|
||||
method map");
|
||||
}
|
||||
Some(ref entry) => {
|
||||
debug!("(privacy checking) checking \
|
||||
impl method");
|
||||
check_method(expr.span, &entry.origin, ident);
|
||||
self.check_method(expr.span, &entry.origin, ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -425,35 +426,35 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
expr_path(ref path) => {
|
||||
check_path(expr.span, tcx.def_map.get_copy(&expr.id), path);
|
||||
self.check_path(expr.span, self.tcx.def_map.get_copy(&expr.id), path);
|
||||
}
|
||||
expr_struct(_, ref fields, _) => {
|
||||
match ty::get(ty::expr_ty(tcx, expr)).sty {
|
||||
match ty::get(ty::expr_ty(self.tcx, expr)).sty {
|
||||
ty_struct(id, _) => {
|
||||
if id.crate != LOCAL_CRATE ||
|
||||
!privileged_items.iter().any(|x| x == &(id.node)) {
|
||||
!self.privileged_items.iter().any(|x| x == &(id.node)) {
|
||||
for field in (*fields).iter() {
|
||||
debug!("(privacy checking) checking \
|
||||
field in struct literal");
|
||||
check_field(expr.span, id, field.ident);
|
||||
self.check_field(expr.span, id, field.ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
ty_enum(id, _) => {
|
||||
if id.crate != LOCAL_CRATE ||
|
||||
!privileged_items.iter().any(|x| x == &(id.node)) {
|
||||
match tcx.def_map.get_copy(&expr.id) {
|
||||
!self.privileged_items.iter().any(|x| x == &(id.node)) {
|
||||
match self.tcx.def_map.get_copy(&expr.id) {
|
||||
def_variant(_, variant_id) => {
|
||||
for field in (*fields).iter() {
|
||||
debug!("(privacy checking) \
|
||||
checking field in \
|
||||
struct variant \
|
||||
literal");
|
||||
check_field(expr.span, variant_id, field.ident);
|
||||
self.check_field(expr.span, variant_id, field.ident);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_bug(expr.span,
|
||||
self.tcx.sess.span_bug(expr.span,
|
||||
"resolve didn't \
|
||||
map enum struct \
|
||||
constructor to a \
|
||||
|
|
@ -463,7 +464,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_bug(expr.span, "struct expr \
|
||||
self.tcx.sess.span_bug(expr.span, "struct expr \
|
||||
didn't have \
|
||||
struct type?!");
|
||||
}
|
||||
|
|
@ -474,11 +475,11 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
// enum type t, then t's first variant is public or
|
||||
// privileged. (We can assume it has only one variant
|
||||
// since typeck already happened.)
|
||||
match ty::get(ty::expr_ty(tcx, operand)).sty {
|
||||
match ty::get(ty::expr_ty(self.tcx, operand)).sty {
|
||||
ty_enum(id, _) => {
|
||||
if id.crate != LOCAL_CRATE ||
|
||||
!privileged_items.iter().any(|x| x == &(id.node)) {
|
||||
check_variant(expr.span, id);
|
||||
!self.privileged_items.iter().any(|x| x == &(id.node)) {
|
||||
self.check_variant(expr.span, id);
|
||||
}
|
||||
}
|
||||
_ => { /* No check needed */ }
|
||||
|
|
@ -487,36 +488,39 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
_ => {}
|
||||
}
|
||||
|
||||
oldvisit::visit_expr(expr, (method_map, visitor));
|
||||
},
|
||||
visit_pat: |pattern, (method_map, visitor)| {
|
||||
visit::walk_expr(self, expr, method_map);
|
||||
|
||||
}
|
||||
|
||||
fn visit_pat<'mm>(&mut self, pattern:@pat, method_map:&'mm method_map) {
|
||||
|
||||
match pattern.node {
|
||||
pat_struct(_, ref fields, _) => {
|
||||
match ty::get(ty::pat_ty(tcx, pattern)).sty {
|
||||
match ty::get(ty::pat_ty(self.tcx, pattern)).sty {
|
||||
ty_struct(id, _) => {
|
||||
if id.crate != LOCAL_CRATE ||
|
||||
!privileged_items.iter().any(|x| x == &(id.node)) {
|
||||
!self.privileged_items.iter().any(|x| x == &(id.node)) {
|
||||
for field in fields.iter() {
|
||||
debug!("(privacy checking) checking \
|
||||
struct pattern");
|
||||
check_field(pattern.span, id, field.ident);
|
||||
self.check_field(pattern.span, id, field.ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
ty_enum(enum_id, _) => {
|
||||
if enum_id.crate != LOCAL_CRATE ||
|
||||
!privileged_items.iter().any(|x| x == &enum_id.node) {
|
||||
match tcx.def_map.find(&pattern.id) {
|
||||
!self.privileged_items.iter().any(|x| x == &enum_id.node) {
|
||||
match self.tcx.def_map.find(&pattern.id) {
|
||||
Some(&def_variant(_, variant_id)) => {
|
||||
for field in fields.iter() {
|
||||
debug!("(privacy checking) \
|
||||
checking field in \
|
||||
struct variant pattern");
|
||||
check_field(pattern.span, variant_id, field.ident);
|
||||
self.check_field(pattern.span, variant_id, field.ident);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_bug(pattern.span,
|
||||
self.tcx.sess.span_bug(pattern.span,
|
||||
"resolve didn't \
|
||||
map enum struct \
|
||||
pattern to a \
|
||||
|
|
@ -526,7 +530,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.span_bug(pattern.span,
|
||||
self.tcx.sess.span_bug(pattern.span,
|
||||
"struct pattern didn't have \
|
||||
struct type?!");
|
||||
}
|
||||
|
|
@ -535,11 +539,20 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
|
|||
_ => {}
|
||||
}
|
||||
|
||||
oldvisit::visit_pat(pattern, (method_map, visitor));
|
||||
},
|
||||
.. *oldvisit::default_visitor()
|
||||
});
|
||||
oldvisit::visit_crate(crate, (method_map, visitor));
|
||||
visit::walk_pat(self, pattern, method_map);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate<'mm>(tcx: ty::ctxt,
|
||||
method_map: &'mm method_map,
|
||||
crate: &ast::Crate) {
|
||||
let privileged_items = @mut ~[];
|
||||
|
||||
let mut visitor = PrivacyVisitor {
|
||||
tcx: tcx,
|
||||
privileged_items: privileged_items,
|
||||
};
|
||||
visit::walk_crate(&mut visitor, crate, method_map);
|
||||
}
|
||||
|
||||
/// Validates all of the visibility qualifers placed on the item given. This
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue