Skip to content

Commit 0d34c5d

Browse files
committed
Use the node id from the Restricted variant when checking accessibility
in `typeck` and in `privacy::PrivacyVisitor`.
1 parent bb66d91 commit 0d34c5d

File tree

6 files changed

+34
-42
lines changed

6 files changed

+34
-42
lines changed

src/librustc/hir/map/mod.rs

-12
Original file line numberDiff line numberDiff line change
@@ -440,18 +440,6 @@ impl<'ast> Map<'ast> {
440440
}
441441
}
442442

443-
pub fn private_item_is_visible_from(&self, item: NodeId, block: NodeId) -> bool {
444-
// A private item is visible from everything in its nearest module parent.
445-
let visibility = self.get_module_parent(item);
446-
let mut block_ancestor = self.get_module_parent(block);
447-
loop {
448-
if block_ancestor == visibility { return true }
449-
let block_ancestor_parent = self.get_module_parent(block_ancestor);
450-
if block_ancestor_parent == block_ancestor { return false }
451-
block_ancestor = block_ancestor_parent;
452-
}
453-
}
454-
455443
/// Returns the nearest enclosing scope. A scope is an item or block.
456444
/// FIXME it is not clear to me that all items qualify as scopes - statics
457445
/// and associated types probably shouldn't, for example. Behaviour in this

src/librustc/ty/mod.rs

+20
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,26 @@ impl Visibility {
290290
hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
291291
}
292292
}
293+
294+
/// Returns true if an item with this visibility is accessible from the given block.
295+
pub fn is_accessible_from(self, block: NodeId, map: &ast_map::Map) -> bool {
296+
let restriction = match self {
297+
// Public items are visible everywhere.
298+
Visibility::Public => return true,
299+
// Private items from other crates are visible nowhere.
300+
Visibility::PrivateExternal => return false,
301+
// Restricted items are visible in an arbitrary local module.
302+
Visibility::Restricted(module) => module,
303+
};
304+
305+
let mut block_ancestor = map.get_module_parent(block);
306+
loop {
307+
if block_ancestor == restriction { return true }
308+
let block_ancestor_parent = map.get_module_parent(block_ancestor);
309+
if block_ancestor_parent == block_ancestor { return false }
310+
block_ancestor = block_ancestor_parent;
311+
}
312+
}
293313
}
294314

295315
#[derive(Clone, Debug)]

src/librustc_privacy/lib.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -382,26 +382,18 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
382382
}
383383

384384
impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
385-
fn item_is_visible(&self, did: DefId) -> bool {
386-
let is_public = match self.tcx.map.as_local_node_id(did) {
387-
Some(node_id) => self.tcx.map.expect_item(node_id).vis == hir::Public,
388-
None => self.tcx.sess.cstore.visibility(did) == ty::Visibility::Public,
389-
};
390-
is_public || self.private_accessible(did)
391-
}
392-
393-
/// True if `did` is private-accessible
394-
fn private_accessible(&self, did: DefId) -> bool {
385+
fn item_is_accessible(&self, did: DefId) -> bool {
395386
match self.tcx.map.as_local_node_id(did) {
396-
Some(node_id) => self.tcx.map.private_item_is_visible_from(node_id, self.curitem),
397-
None => false,
398-
}
387+
Some(node_id) =>
388+
ty::Visibility::from_hir(&self.tcx.map.expect_item(node_id).vis, node_id, self.tcx),
389+
None => self.tcx.sess.cstore.visibility(did),
390+
}.is_accessible_from(self.curitem, &self.tcx.map)
399391
}
400392

401393
// Checks that a field is in scope.
402394
fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) {
403395
if def.adt_kind() == ty::AdtKind::Struct &&
404-
field.vis != ty::Visibility::Public && !self.private_accessible(def.did) {
396+
!field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
405397
span_err!(self.tcx.sess, span, E0451, "field `{}` of struct `{}` is private",
406398
field.name, self.tcx.item_path_str(def.did));
407399
}
@@ -412,7 +404,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
412404
match self.tcx.impl_or_trait_item(method_def_id).container() {
413405
// Trait methods are always all public. The only controlling factor
414406
// is whether the trait itself is accessible or not.
415-
ty::TraitContainer(trait_def_id) if !self.item_is_visible(trait_def_id) => {
407+
ty::TraitContainer(trait_def_id) if !self.item_is_accessible(trait_def_id) => {
416408
let msg = format!("source trait `{}` is private",
417409
self.tcx.item_path_str(trait_def_id));
418410
self.tcx.sess.span_err(span, &msg);
@@ -464,7 +456,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
464456
_ => expr_ty
465457
}.ty_adt_def().unwrap();
466458
let any_priv = def.struct_variant().fields.iter().any(|f| {
467-
f.vis != ty::Visibility::Public && !self.private_accessible(def.did)
459+
!f.vis.is_accessible_from(self.curitem, &self.tcx.map)
468460
});
469461
if any_priv {
470462
span_err!(self.tcx.sess, expr.span, E0450,

src/librustc_typeck/check/method/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use hir::def::Def;
1616
use hir::def_id::DefId;
1717
use rustc::ty::subst;
1818
use rustc::traits;
19-
use rustc::ty::{self, TyCtxt, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable, Visibility};
19+
use rustc::ty::{self, TyCtxt, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
2020
use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
2121
use rustc::infer;
2222

@@ -343,7 +343,7 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
343343
let def = pick.item.def();
344344

345345
if let probe::InherentImplPick = pick.kind {
346-
if pick.item.vis() != Visibility::Public && !fcx.private_item_is_visible(def.def_id()) {
346+
if !pick.item.vis().is_accessible_from(fcx.body_id, &fcx.tcx().map) {
347347
let msg = format!("{} `{}` is private", def.kind_name(), &method_name.as_str());
348348
fcx.tcx().sess.span_err(span, &msg);
349349
}

src/librustc_typeck/check/method/probe.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use hir::def::Def;
2020
use rustc::ty::subst;
2121
use rustc::ty::subst::Subst;
2222
use rustc::traits;
23-
use rustc::ty::{self, NoPreference, Ty, TyCtxt, ToPolyTraitRef, TraitRef, TypeFoldable, Visibility};
23+
use rustc::ty::{self, NoPreference, Ty, TyCtxt, ToPolyTraitRef, TraitRef, TypeFoldable};
2424
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin};
2525
use syntax::ast;
2626
use syntax::codemap::{Span, DUMMY_SP};
@@ -412,7 +412,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
412412
return self.record_static_candidate(ImplSource(impl_def_id));
413413
}
414414

415-
if item.vis() != Visibility::Public && !self.fcx.private_item_is_visible(item.def_id()) {
415+
if !item.vis().is_accessible_from(self.fcx.body_id, &self.tcx().map) {
416416
self.private_candidate = Some(item.def());
417417
return
418418
}

src/librustc_typeck/check/mod.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -2054,13 +2054,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20542054
Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
20552055
}
20562056
}
2057-
2058-
fn private_item_is_visible(&self, def_id: DefId) -> bool {
2059-
match self.tcx().map.as_local_node_id(def_id) {
2060-
Some(node_id) => self.tcx().map.private_item_is_visible_from(node_id, self.body_id),
2061-
None => false, // Private items from other crates are never visible
2062-
}
2063-
}
20642057
}
20652058

20662059
impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
@@ -2966,8 +2959,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
29662959
debug!("struct named {:?}", base_t);
29672960
if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
29682961
let field_ty = fcx.field_ty(expr.span, field, substs);
2969-
if field.vis == Visibility::Public ||
2970-
fcx.private_item_is_visible(base_def.did) {
2962+
if field.vis.is_accessible_from(fcx.body_id, &fcx.tcx().map) {
29712963
return Some(field_ty);
29722964
}
29732965
private_candidate = Some((base_def.did, field_ty));
@@ -3079,7 +3071,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
30793071
debug!("tuple struct named {:?}", base_t);
30803072
if let Some(field) = base_def.struct_variant().fields.get(idx.node) {
30813073
let field_ty = fcx.field_ty(expr.span, field, substs);
3082-
if field.vis == Visibility::Public || fcx.private_item_is_visible(base_def.did) {
3074+
if field.vis.is_accessible_from(fcx.body_id, &fcx.tcx().map) {
30833075
return Some(field_ty);
30843076
}
30853077
private_candidate = Some((base_def.did, field_ty));

0 commit comments

Comments
 (0)