Auto merge of #38490 - jseyfried:def_id_vis, r=nrc
Use `DefId`s instead of `NodeId`s for `pub(restricted)` visibilities This is groundwork for hygiene 2.0, specifically privacy checking hygienic intercrate name resolutions. r? @nrc
This commit is contained in:
commit
44ad63e487
@ -219,26 +219,18 @@ pub enum Visibility {
|
|||||||
/// Visible everywhere (including in other crates).
|
/// Visible everywhere (including in other crates).
|
||||||
Public,
|
Public,
|
||||||
/// Visible only in the given crate-local module.
|
/// Visible only in the given crate-local module.
|
||||||
Restricted(NodeId),
|
Restricted(DefId),
|
||||||
/// Not visible anywhere in the local crate. This is the visibility of private external items.
|
/// Not visible anywhere in the local crate. This is the visibility of private external items.
|
||||||
PrivateExternal,
|
Invisible,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait NodeIdTree {
|
pub trait DefIdTree: Copy {
|
||||||
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool;
|
fn parent(self, id: DefId) -> Option<DefId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NodeIdTree for ast_map::Map<'a> {
|
impl<'a, 'gcx, 'tcx> DefIdTree for TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
|
fn parent(self, id: DefId) -> Option<DefId> {
|
||||||
let mut node_ancestor = node;
|
self.def_key(id).parent.map(|index| DefId { index: index, ..id })
|
||||||
while node_ancestor != ancestor {
|
|
||||||
let node_ancestor_parent = self.get_module_parent(node_ancestor);
|
|
||||||
if node_ancestor_parent == node_ancestor {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
node_ancestor = node_ancestor_parent;
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,36 +238,46 @@ impl Visibility {
|
|||||||
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
|
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
|
||||||
match *visibility {
|
match *visibility {
|
||||||
hir::Public => Visibility::Public,
|
hir::Public => Visibility::Public,
|
||||||
hir::Visibility::Crate => Visibility::Restricted(ast::CRATE_NODE_ID),
|
hir::Visibility::Crate => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
|
||||||
hir::Visibility::Restricted { ref path, .. } => match path.def {
|
hir::Visibility::Restricted { ref path, .. } => match path.def {
|
||||||
// If there is no resolution, `resolve` will have already reported an error, so
|
// If there is no resolution, `resolve` will have already reported an error, so
|
||||||
// assume that the visibility is public to avoid reporting more privacy errors.
|
// assume that the visibility is public to avoid reporting more privacy errors.
|
||||||
Def::Err => Visibility::Public,
|
Def::Err => Visibility::Public,
|
||||||
def => Visibility::Restricted(tcx.map.as_local_node_id(def.def_id()).unwrap()),
|
def => Visibility::Restricted(def.def_id()),
|
||||||
},
|
},
|
||||||
hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
|
hir::Inherited => {
|
||||||
|
Visibility::Restricted(tcx.map.local_def_id(tcx.map.get_module_parent(id)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if an item with this visibility is accessible from the given block.
|
/// Returns true if an item with this visibility is accessible from the given block.
|
||||||
pub fn is_accessible_from<T: NodeIdTree>(self, block: NodeId, tree: &T) -> bool {
|
pub fn is_accessible_from<T: DefIdTree>(self, mut module: DefId, tree: T) -> bool {
|
||||||
let restriction = match self {
|
let restriction = match self {
|
||||||
// Public items are visible everywhere.
|
// Public items are visible everywhere.
|
||||||
Visibility::Public => return true,
|
Visibility::Public => return true,
|
||||||
// Private items from other crates are visible nowhere.
|
// Private items from other crates are visible nowhere.
|
||||||
Visibility::PrivateExternal => return false,
|
Visibility::Invisible => return false,
|
||||||
// Restricted items are visible in an arbitrary local module.
|
// Restricted items are visible in an arbitrary local module.
|
||||||
|
Visibility::Restricted(other) if other.krate != module.krate => return false,
|
||||||
Visibility::Restricted(module) => module,
|
Visibility::Restricted(module) => module,
|
||||||
};
|
};
|
||||||
|
|
||||||
tree.is_descendant_of(block, restriction)
|
while module != restriction {
|
||||||
|
match tree.parent(module) {
|
||||||
|
Some(parent) => module = parent,
|
||||||
|
None => return false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this visibility is at least as accessible as the given visibility
|
/// Returns true if this visibility is at least as accessible as the given visibility
|
||||||
pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
|
pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool {
|
||||||
let vis_restriction = match vis {
|
let vis_restriction = match vis {
|
||||||
Visibility::Public => return self == Visibility::Public,
|
Visibility::Public => return self == Visibility::Public,
|
||||||
Visibility::PrivateExternal => return true,
|
Visibility::Invisible => return true,
|
||||||
Visibility::Restricted(module) => module,
|
Visibility::Restricted(module) => module,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1779,7 +1781,7 @@ pub fn is_uninhabited_recurse(&self,
|
|||||||
block: Option<NodeId>,
|
block: Option<NodeId>,
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
substs: &'tcx Substs<'tcx>) -> bool {
|
substs: &'tcx Substs<'tcx>) -> bool {
|
||||||
block.map_or(true, |b| self.vis.is_accessible_from(b, &tcx.map)) &&
|
block.map_or(true, |b| tcx.vis_is_accessible_from(self.vis, b)) &&
|
||||||
self.ty(tcx, substs).is_uninhabited_recurse(visited, block, tcx)
|
self.ty(tcx, substs).is_uninhabited_recurse(visited, block, tcx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2266,6 +2268,10 @@ pub fn def_span(self, def_id: DefId) -> Span {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool {
|
||||||
|
vis.is_accessible_from(self.map.local_def_id(self.map.get_module_parent(block)), self)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn item_name(self, id: DefId) -> ast::Name {
|
pub fn item_name(self, id: DefId) -> ast::Name {
|
||||||
if let Some(id) = self.map.as_local_node_id(id) {
|
if let Some(id) = self.map.as_local_node_id(id) {
|
||||||
self.map.name(id)
|
self.map.name(id)
|
||||||
|
@ -588,7 +588,7 @@ fn get_variant(&self,
|
|||||||
ty::FieldDef {
|
ty::FieldDef {
|
||||||
did: self.local_def_id(index),
|
did: self.local_def_id(index),
|
||||||
name: self.item_name(index),
|
name: self.item_name(index),
|
||||||
vis: f.visibility
|
vis: f.visibility.decode(self)
|
||||||
}
|
}
|
||||||
}).collect(),
|
}).collect(),
|
||||||
disr_val: ConstInt::Infer(data.disr),
|
disr_val: ConstInt::Infer(data.disr),
|
||||||
@ -678,7 +678,7 @@ pub fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
|
|||||||
pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
|
pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
|
||||||
match self.is_proc_macro(id) {
|
match self.is_proc_macro(id) {
|
||||||
true => ty::Visibility::Public,
|
true => ty::Visibility::Public,
|
||||||
false => self.entry(id).visibility,
|
false => self.entry(id).visibility.decode(self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -885,7 +885,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
|
|||||||
ty::AssociatedItem {
|
ty::AssociatedItem {
|
||||||
name: name,
|
name: name,
|
||||||
kind: ty::AssociatedKind::Const,
|
kind: ty::AssociatedKind::Const,
|
||||||
vis: item.visibility,
|
vis: item.visibility.decode(self),
|
||||||
defaultness: container.defaultness(),
|
defaultness: container.defaultness(),
|
||||||
def_id: self.local_def_id(id),
|
def_id: self.local_def_id(id),
|
||||||
container: container.with_def_id(parent),
|
container: container.with_def_id(parent),
|
||||||
@ -898,7 +898,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
|
|||||||
ty::AssociatedItem {
|
ty::AssociatedItem {
|
||||||
name: name,
|
name: name,
|
||||||
kind: ty::AssociatedKind::Method,
|
kind: ty::AssociatedKind::Method,
|
||||||
vis: item.visibility,
|
vis: item.visibility.decode(self),
|
||||||
defaultness: data.container.defaultness(),
|
defaultness: data.container.defaultness(),
|
||||||
def_id: self.local_def_id(id),
|
def_id: self.local_def_id(id),
|
||||||
container: data.container.with_def_id(parent),
|
container: data.container.with_def_id(parent),
|
||||||
@ -910,7 +910,7 @@ pub fn get_associated_item(&self, id: DefIndex) -> Option<ty::AssociatedItem> {
|
|||||||
ty::AssociatedItem {
|
ty::AssociatedItem {
|
||||||
name: name,
|
name: name,
|
||||||
kind: ty::AssociatedKind::Type,
|
kind: ty::AssociatedKind::Type,
|
||||||
vis: item.visibility,
|
vis: item.visibility.decode(self),
|
||||||
defaultness: container.defaultness(),
|
defaultness: container.defaultness(),
|
||||||
def_id: self.local_def_id(id),
|
def_id: self.local_def_id(id),
|
||||||
container: container.with_def_id(parent),
|
container: container.with_def_id(parent),
|
||||||
|
@ -268,7 +268,7 @@ fn encode_enum_variant_info(&mut self,
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: EntryKind::Variant(self.lazy(&data)),
|
kind: EntryKind::Variant(self.lazy(&data)),
|
||||||
visibility: enum_vis.simplify(),
|
visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)),
|
||||||
span: self.lazy(&tcx.def_span(def_id)),
|
span: self.lazy(&tcx.def_span(def_id)),
|
||||||
attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
|
attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
|
||||||
children: self.lazy_seq(variant.fields.iter().map(|f| {
|
children: self.lazy_seq(variant.fields.iter().map(|f| {
|
||||||
@ -306,7 +306,7 @@ fn encode_info_for_mod(&mut self,
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: EntryKind::Mod(self.lazy(&data)),
|
kind: EntryKind::Mod(self.lazy(&data)),
|
||||||
visibility: vis.simplify(),
|
visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)),
|
||||||
span: self.lazy(&md.inner),
|
span: self.lazy(&md.inner),
|
||||||
attributes: self.encode_attributes(attrs),
|
attributes: self.encode_attributes(attrs),
|
||||||
children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
|
children: self.lazy_seq(md.item_ids.iter().map(|item_id| {
|
||||||
@ -327,30 +327,6 @@ fn encode_info_for_mod(&mut self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Visibility {
|
|
||||||
fn simplify(&self) -> ty::Visibility;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Visibility for hir::Visibility {
|
|
||||||
fn simplify(&self) -> ty::Visibility {
|
|
||||||
if *self == hir::Public {
|
|
||||||
ty::Visibility::Public
|
|
||||||
} else {
|
|
||||||
ty::Visibility::PrivateExternal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Visibility for ty::Visibility {
|
|
||||||
fn simplify(&self) -> ty::Visibility {
|
|
||||||
if *self == ty::Visibility::Public {
|
|
||||||
ty::Visibility::Public
|
|
||||||
} else {
|
|
||||||
ty::Visibility::PrivateExternal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
|
||||||
fn encode_fields(&mut self, adt_def_id: DefId) {
|
fn encode_fields(&mut self, adt_def_id: DefId) {
|
||||||
let def = self.tcx.lookup_adt_def(adt_def_id);
|
let def = self.tcx.lookup_adt_def(adt_def_id);
|
||||||
@ -386,7 +362,7 @@ fn encode_field(&mut self,
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: EntryKind::Field,
|
kind: EntryKind::Field,
|
||||||
visibility: field.vis.simplify(),
|
visibility: self.lazy(&field.vis),
|
||||||
span: self.lazy(&tcx.def_span(def_id)),
|
span: self.lazy(&tcx.def_span(def_id)),
|
||||||
attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs),
|
attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs),
|
||||||
children: LazySeq::empty(),
|
children: LazySeq::empty(),
|
||||||
@ -419,7 +395,7 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: EntryKind::Struct(self.lazy(&data)),
|
kind: EntryKind::Struct(self.lazy(&data)),
|
||||||
visibility: struct_vis.simplify(),
|
visibility: self.lazy(&ty::Visibility::from_hir(struct_vis, struct_id, tcx)),
|
||||||
span: self.lazy(&tcx.def_span(def_id)),
|
span: self.lazy(&tcx.def_span(def_id)),
|
||||||
attributes: LazySeq::empty(),
|
attributes: LazySeq::empty(),
|
||||||
children: LazySeq::empty(),
|
children: LazySeq::empty(),
|
||||||
@ -485,7 +461,7 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
visibility: trait_item.vis.simplify(),
|
visibility: self.lazy(&trait_item.vis),
|
||||||
span: self.lazy(&ast_item.span),
|
span: self.lazy(&ast_item.span),
|
||||||
attributes: self.encode_attributes(&ast_item.attrs),
|
attributes: self.encode_attributes(&ast_item.attrs),
|
||||||
children: LazySeq::empty(),
|
children: LazySeq::empty(),
|
||||||
@ -574,7 +550,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
visibility: impl_item.vis.simplify(),
|
visibility: self.lazy(&impl_item.vis),
|
||||||
span: self.lazy(&ast_item.span),
|
span: self.lazy(&ast_item.span),
|
||||||
attributes: self.encode_attributes(&ast_item.attrs),
|
attributes: self.encode_attributes(&ast_item.attrs),
|
||||||
children: LazySeq::empty(),
|
children: LazySeq::empty(),
|
||||||
@ -736,7 +712,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
visibility: item.vis.simplify(),
|
visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.id, tcx)),
|
||||||
span: self.lazy(&item.span),
|
span: self.lazy(&item.span),
|
||||||
attributes: self.encode_attributes(&item.attrs),
|
attributes: self.encode_attributes(&item.attrs),
|
||||||
children: match item.node {
|
children: match item.node {
|
||||||
@ -849,7 +825,7 @@ fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx
|
|||||||
kind: EntryKind::MacroDef(self.lazy(&MacroDef {
|
kind: EntryKind::MacroDef(self.lazy(&MacroDef {
|
||||||
body: ::syntax::print::pprust::tts_to_string(¯o_def.body)
|
body: ::syntax::print::pprust::tts_to_string(¯o_def.body)
|
||||||
})),
|
})),
|
||||||
visibility: ty::Visibility::Public,
|
visibility: self.lazy(&ty::Visibility::Public),
|
||||||
span: self.lazy(¯o_def.span),
|
span: self.lazy(¯o_def.span),
|
||||||
|
|
||||||
attributes: self.encode_attributes(¯o_def.attrs),
|
attributes: self.encode_attributes(¯o_def.attrs),
|
||||||
@ -950,7 +926,7 @@ fn encode_info_for_foreign_item(&mut self,
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
visibility: nitem.vis.simplify(),
|
visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)),
|
||||||
span: self.lazy(&nitem.span),
|
span: self.lazy(&nitem.span),
|
||||||
attributes: self.encode_attributes(&nitem.attrs),
|
attributes: self.encode_attributes(&nitem.attrs),
|
||||||
children: LazySeq::empty(),
|
children: LazySeq::empty(),
|
||||||
@ -1032,7 +1008,7 @@ fn encode_info_for_anon_ty(&mut self, def_id: DefId) -> Entry<'tcx> {
|
|||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
Entry {
|
Entry {
|
||||||
kind: EntryKind::Type,
|
kind: EntryKind::Type,
|
||||||
visibility: ty::Visibility::Public,
|
visibility: self.lazy(&ty::Visibility::Public),
|
||||||
span: self.lazy(&tcx.def_span(def_id)),
|
span: self.lazy(&tcx.def_span(def_id)),
|
||||||
attributes: LazySeq::empty(),
|
attributes: LazySeq::empty(),
|
||||||
children: LazySeq::empty(),
|
children: LazySeq::empty(),
|
||||||
@ -1060,7 +1036,7 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
|
|||||||
|
|
||||||
Entry {
|
Entry {
|
||||||
kind: EntryKind::Closure(self.lazy(&data)),
|
kind: EntryKind::Closure(self.lazy(&data)),
|
||||||
visibility: ty::Visibility::Public,
|
visibility: self.lazy(&ty::Visibility::Public),
|
||||||
span: self.lazy(&tcx.def_span(def_id)),
|
span: self.lazy(&tcx.def_span(def_id)),
|
||||||
attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
|
attributes: self.encode_attributes(&tcx.get_attrs(def_id)),
|
||||||
children: LazySeq::empty(),
|
children: LazySeq::empty(),
|
||||||
|
@ -201,7 +201,7 @@ pub struct TraitImpls {
|
|||||||
#[derive(RustcEncodable, RustcDecodable)]
|
#[derive(RustcEncodable, RustcDecodable)]
|
||||||
pub struct Entry<'tcx> {
|
pub struct Entry<'tcx> {
|
||||||
pub kind: EntryKind<'tcx>,
|
pub kind: EntryKind<'tcx>,
|
||||||
pub visibility: ty::Visibility,
|
pub visibility: Lazy<ty::Visibility>,
|
||||||
pub span: Lazy<Span>,
|
pub span: Lazy<Span>,
|
||||||
pub attributes: LazySeq<ast::Attribute>,
|
pub attributes: LazySeq<ast::Attribute>,
|
||||||
pub children: LazySeq<DefIndex>,
|
pub children: LazySeq<DefIndex>,
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
use rustc::dep_graph::DepNode;
|
use rustc::dep_graph::DepNode;
|
||||||
use rustc::hir::{self, PatKind};
|
use rustc::hir::{self, PatKind};
|
||||||
use rustc::hir::def::{self, Def, CtorKind};
|
use rustc::hir::def::{self, Def, CtorKind};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
|
||||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||||
use rustc::hir::itemlikevisit::DeepVisitor;
|
use rustc::hir::itemlikevisit::DeepVisitor;
|
||||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||||
@ -391,7 +391,7 @@ fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
|
|||||||
|
|
||||||
struct PrivacyVisitor<'a, 'tcx: 'a> {
|
struct PrivacyVisitor<'a, 'tcx: 'a> {
|
||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
curitem: ast::NodeId,
|
curitem: DefId,
|
||||||
in_foreign: bool,
|
in_foreign: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -401,12 +401,12 @@ fn item_is_accessible(&self, did: DefId) -> bool {
|
|||||||
Some(node_id) =>
|
Some(node_id) =>
|
||||||
ty::Visibility::from_hir(&self.tcx.map.expect_item(node_id).vis, node_id, self.tcx),
|
ty::Visibility::from_hir(&self.tcx.map.expect_item(node_id).vis, node_id, self.tcx),
|
||||||
None => self.tcx.sess.cstore.visibility(did),
|
None => self.tcx.sess.cstore.visibility(did),
|
||||||
}.is_accessible_from(self.curitem, &self.tcx.map)
|
}.is_accessible_from(self.curitem, self.tcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks that a field is in scope.
|
// Checks that a field is in scope.
|
||||||
fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::FieldDef) {
|
fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::FieldDef) {
|
||||||
if !def.is_enum() && !field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
|
if !def.is_enum() && !field.vis.is_accessible_from(self.curitem, self.tcx) {
|
||||||
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
|
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
|
||||||
field.name, def.variant_descr(), self.tcx.item_path_str(def.did))
|
field.name, def.variant_descr(), self.tcx.item_path_str(def.did))
|
||||||
.span_label(span, &format!("field `{}` is private", field.name))
|
.span_label(span, &format!("field `{}` is private", field.name))
|
||||||
@ -437,7 +437,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||||
let orig_curitem = replace(&mut self.curitem, item.id);
|
let orig_curitem = replace(&mut self.curitem, self.tcx.map.local_def_id(item.id));
|
||||||
intravisit::walk_item(self, item);
|
intravisit::walk_item(self, item);
|
||||||
self.curitem = orig_curitem;
|
self.curitem = orig_curitem;
|
||||||
}
|
}
|
||||||
@ -474,7 +474,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
|||||||
if let Def::StructCtor(_, CtorKind::Fn) = path.def {
|
if let Def::StructCtor(_, CtorKind::Fn) = path.def {
|
||||||
let adt_def = self.tcx.expect_variant_def(path.def);
|
let adt_def = self.tcx.expect_variant_def(path.def);
|
||||||
let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
|
let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
|
||||||
!field.vis.is_accessible_from(self.curitem, &self.tcx.map)
|
!field.vis.is_accessible_from(self.curitem, self.tcx)
|
||||||
}).map(|(i, _)| i).collect::<Vec<_>>();
|
}).map(|(i, _)| i).collect::<Vec<_>>();
|
||||||
|
|
||||||
if !private_indexes.is_empty() {
|
if !private_indexes.is_empty() {
|
||||||
@ -940,7 +940,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
|||||||
ty::TyAdt(adt, _) => Some(adt.did),
|
ty::TyAdt(adt, _) => Some(adt.did),
|
||||||
ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
|
ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()),
|
||||||
ty::TyProjection(ref proj) => {
|
ty::TyProjection(ref proj) => {
|
||||||
if self.required_visibility == ty::Visibility::PrivateExternal {
|
if self.required_visibility == ty::Visibility::Invisible {
|
||||||
// Conservatively approximate the whole type alias as public without
|
// Conservatively approximate the whole type alias as public without
|
||||||
// recursing into its components when determining impl publicity.
|
// recursing into its components when determining impl publicity.
|
||||||
// For example, `impl <Type as Trait>::Alias {...}` may be a public impl
|
// For example, `impl <Type as Trait>::Alias {...}` may be a public impl
|
||||||
@ -961,10 +961,10 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
|||||||
let item = self.tcx.map.expect_item(node_id);
|
let item = self.tcx.map.expect_item(node_id);
|
||||||
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
|
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
|
||||||
|
|
||||||
if !vis.is_at_least(self.min_visibility, &self.tcx.map) {
|
if !vis.is_at_least(self.min_visibility, self.tcx) {
|
||||||
self.min_visibility = vis;
|
self.min_visibility = vis;
|
||||||
}
|
}
|
||||||
if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
|
if !vis.is_at_least(self.required_visibility, self.tcx) {
|
||||||
if self.tcx.sess.features.borrow().pub_restricted || self.has_old_errors {
|
if self.tcx.sess.features.borrow().pub_restricted || self.has_old_errors {
|
||||||
let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
|
let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
|
||||||
"private type `{}` in public interface", ty);
|
"private type `{}` in public interface", ty);
|
||||||
@ -996,10 +996,10 @@ fn visit_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool {
|
|||||||
let item = self.tcx.map.expect_item(node_id);
|
let item = self.tcx.map.expect_item(node_id);
|
||||||
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
|
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);
|
||||||
|
|
||||||
if !vis.is_at_least(self.min_visibility, &self.tcx.map) {
|
if !vis.is_at_least(self.min_visibility, self.tcx) {
|
||||||
self.min_visibility = vis;
|
self.min_visibility = vis;
|
||||||
}
|
}
|
||||||
if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
|
if !vis.is_at_least(self.required_visibility, self.tcx) {
|
||||||
if self.tcx.sess.features.borrow().pub_restricted || self.has_old_errors {
|
if self.tcx.sess.features.borrow().pub_restricted || self.has_old_errors {
|
||||||
struct_span_err!(self.tcx.sess, self.span, E0445,
|
struct_span_err!(self.tcx.sess, self.span, E0445,
|
||||||
"private trait `{}` in public interface", trait_ref)
|
"private trait `{}` in public interface", trait_ref)
|
||||||
@ -1071,7 +1071,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
|||||||
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let min = |vis1: ty::Visibility, vis2| {
|
let min = |vis1: ty::Visibility, vis2| {
|
||||||
if vis1.is_at_least(vis2, &tcx.map) { vis2 } else { vis1 }
|
if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx);
|
let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx);
|
||||||
@ -1137,8 +1137,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
|
|||||||
// An inherent impl is public when its type is public
|
// An inherent impl is public when its type is public
|
||||||
// Subitems of inherent impls have their own publicity
|
// Subitems of inherent impls have their own publicity
|
||||||
hir::ItemImpl(.., None, _, ref impl_item_refs) => {
|
hir::ItemImpl(.., None, _, ref impl_item_refs) => {
|
||||||
let ty_vis = self.check(item.id, ty::Visibility::PrivateExternal)
|
let ty_vis =
|
||||||
.item_type().min_visibility;
|
self.check(item.id, ty::Visibility::Invisible).item_type().min_visibility;
|
||||||
self.check(item.id, ty_vis).generics().predicates();
|
self.check(item.id, ty_vis).generics().predicates();
|
||||||
|
|
||||||
for impl_item_ref in impl_item_refs {
|
for impl_item_ref in impl_item_refs {
|
||||||
@ -1156,7 +1156,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
|
|||||||
// A trait impl is public when both its type and its trait are public
|
// A trait impl is public when both its type and its trait are public
|
||||||
// Subitems of trait impls have inherited publicity
|
// Subitems of trait impls have inherited publicity
|
||||||
hir::ItemImpl(.., Some(_), _, ref impl_item_refs) => {
|
hir::ItemImpl(.., Some(_), _, ref impl_item_refs) => {
|
||||||
let vis = self.check(item.id, ty::Visibility::PrivateExternal)
|
let vis = self.check(item.id, ty::Visibility::Invisible)
|
||||||
.item_type().impl_trait_ref().min_visibility;
|
.item_type().impl_trait_ref().min_visibility;
|
||||||
self.check(item.id, vis).generics().predicates();
|
self.check(item.id, vis).generics().predicates();
|
||||||
for impl_item_ref in impl_item_refs {
|
for impl_item_ref in impl_item_refs {
|
||||||
@ -1203,7 +1203,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||||||
|
|
||||||
// Use the parent map to check the privacy of everything
|
// Use the parent map to check the privacy of everything
|
||||||
let mut visitor = PrivacyVisitor {
|
let mut visitor = PrivacyVisitor {
|
||||||
curitem: ast::DUMMY_NODE_ID,
|
curitem: DefId::local(CRATE_DEF_INDEX),
|
||||||
in_foreign: false,
|
in_foreign: false,
|
||||||
tcx: tcx,
|
tcx: tcx,
|
||||||
};
|
};
|
||||||
|
@ -229,7 +229,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
|||||||
ViewPathGlob(_) => {
|
ViewPathGlob(_) => {
|
||||||
let subclass = GlobImport {
|
let subclass = GlobImport {
|
||||||
is_prelude: is_prelude,
|
is_prelude: is_prelude,
|
||||||
max_vis: Cell::new(ty::Visibility::PrivateExternal),
|
max_vis: Cell::new(ty::Visibility::Invisible),
|
||||||
};
|
};
|
||||||
self.add_import_directive(
|
self.add_import_directive(
|
||||||
module_path, subclass, view_path.span, item.id, vis, expansion,
|
module_path, subclass, view_path.span, item.id, vis, expansion,
|
||||||
@ -265,16 +265,16 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
|||||||
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
|
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
|
||||||
|
|
||||||
ItemKind::Mod(..) => {
|
ItemKind::Mod(..) => {
|
||||||
let def = Def::Mod(self.definitions.local_def_id(item.id));
|
let def_id = self.definitions.local_def_id(item.id);
|
||||||
|
let module_kind = ModuleKind::Def(Def::Mod(def_id), ident.name);
|
||||||
let module = self.arenas.alloc_module(ModuleData {
|
let module = self.arenas.alloc_module(ModuleData {
|
||||||
no_implicit_prelude: parent.no_implicit_prelude || {
|
no_implicit_prelude: parent.no_implicit_prelude || {
|
||||||
attr::contains_name(&item.attrs, "no_implicit_prelude")
|
attr::contains_name(&item.attrs, "no_implicit_prelude")
|
||||||
},
|
},
|
||||||
normal_ancestor_id: Some(item.id),
|
..ModuleData::new(Some(parent), module_kind, def_id)
|
||||||
..ModuleData::new(Some(parent), ModuleKind::Def(def, ident.name))
|
|
||||||
});
|
});
|
||||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||||
self.module_map.insert(item.id, module);
|
self.module_map.insert(def_id, module);
|
||||||
|
|
||||||
// Descend into the module.
|
// Descend into the module.
|
||||||
self.current_module = module;
|
self.current_module = module;
|
||||||
@ -305,7 +305,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
|||||||
|
|
||||||
ItemKind::Enum(ref enum_definition, _) => {
|
ItemKind::Enum(ref enum_definition, _) => {
|
||||||
let def = Def::Enum(self.definitions.local_def_id(item.id));
|
let def = Def::Enum(self.definitions.local_def_id(item.id));
|
||||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), true);
|
let module_kind = ModuleKind::Def(def, ident.name);
|
||||||
|
let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
|
||||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||||
|
|
||||||
for variant in &(*enum_definition).variants {
|
for variant in &(*enum_definition).variants {
|
||||||
@ -355,8 +356,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
|||||||
let def_id = self.definitions.local_def_id(item.id);
|
let def_id = self.definitions.local_def_id(item.id);
|
||||||
|
|
||||||
// Add all the items within to a new module.
|
// Add all the items within to a new module.
|
||||||
let module =
|
let module_kind = ModuleKind::Def(Def::Trait(def_id), ident.name);
|
||||||
self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), ident.name), true);
|
let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
|
||||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||||
self.current_module = module;
|
self.current_module = module;
|
||||||
}
|
}
|
||||||
@ -404,15 +405,10 @@ fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion
|
|||||||
fn build_reduced_graph_for_block(&mut self, block: &Block) {
|
fn build_reduced_graph_for_block(&mut self, block: &Block) {
|
||||||
let parent = self.current_module;
|
let parent = self.current_module;
|
||||||
if self.block_needs_anonymous_module(block) {
|
if self.block_needs_anonymous_module(block) {
|
||||||
let block_id = block.id;
|
let module =
|
||||||
|
self.new_module(parent, ModuleKind::Block(block.id), parent.normal_ancestor_id);
|
||||||
debug!("(building reduced graph for block) creating a new anonymous module for block \
|
self.block_map.insert(block.id, module);
|
||||||
{}",
|
self.current_module = module; // Descend into the block.
|
||||||
block_id);
|
|
||||||
|
|
||||||
let new_module = self.new_module(parent, ModuleKind::Block(block_id), true);
|
|
||||||
self.module_map.insert(block_id, new_module);
|
|
||||||
self.current_module = new_module; // Descend into the block.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +425,7 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
|
|||||||
|
|
||||||
match def {
|
match def {
|
||||||
Def::Mod(..) | Def::Enum(..) => {
|
Def::Mod(..) | Def::Enum(..) => {
|
||||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false);
|
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), def_id);
|
||||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||||
}
|
}
|
||||||
Def::Variant(..) => {
|
Def::Variant(..) => {
|
||||||
@ -446,7 +442,8 @@ fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, chi
|
|||||||
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||||
}
|
}
|
||||||
Def::Trait(..) => {
|
Def::Trait(..) => {
|
||||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false);
|
let module_kind = ModuleKind::Def(def, ident.name);
|
||||||
|
let module = self.new_module(parent, module_kind, parent.normal_ancestor_id);
|
||||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||||
|
|
||||||
// If this is a trait, add all the trait item names to the trait info.
|
// If this is a trait, add all the trait item names to the trait info.
|
||||||
@ -497,12 +494,10 @@ fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> {
|
|||||||
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
|
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
|
||||||
let name = self.session.cstore.crate_name(cnum);
|
let name = self.session.cstore.crate_name(cnum);
|
||||||
let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
|
let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
|
||||||
|
let module_kind = ModuleKind::Def(Def::Mod(def_id), name);
|
||||||
let arenas = self.arenas;
|
let arenas = self.arenas;
|
||||||
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
|
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
|
||||||
arenas.alloc_module(ModuleData {
|
arenas.alloc_module(ModuleData::new(None, module_kind, def_id))
|
||||||
populated: Cell::new(false),
|
|
||||||
..ModuleData::new(None, ModuleKind::Def(Def::Mod(def_id), name))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,14 +43,13 @@
|
|||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::lint;
|
use rustc::lint;
|
||||||
use rustc::hir::def::*;
|
use rustc::hir::def::*;
|
||||||
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
|
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
|
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
|
||||||
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet};
|
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
||||||
use syntax::ast::{self, FloatTy};
|
use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
|
||||||
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, Ident, SpannedIdent, IntTy, UintTy};
|
|
||||||
use syntax::ext::base::SyntaxExtension;
|
use syntax::ext::base::SyntaxExtension;
|
||||||
use syntax::ext::base::Determinacy::{Determined, Undetermined};
|
use syntax::ext::base::Determinacy::{Determined, Undetermined};
|
||||||
use syntax::symbol::{Symbol, keywords};
|
use syntax::symbol::{Symbol, keywords};
|
||||||
@ -771,8 +770,8 @@ pub struct ModuleData<'a> {
|
|||||||
parent: Option<Module<'a>>,
|
parent: Option<Module<'a>>,
|
||||||
kind: ModuleKind,
|
kind: ModuleKind,
|
||||||
|
|
||||||
// The node id of the closest normal module (`mod`) ancestor (including this module).
|
// The def id of the closest normal module (`mod`) ancestor (including this module).
|
||||||
normal_ancestor_id: Option<NodeId>,
|
normal_ancestor_id: DefId,
|
||||||
|
|
||||||
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
|
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
|
||||||
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span)>>,
|
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span)>>,
|
||||||
@ -798,11 +797,11 @@ pub struct ModuleData<'a> {
|
|||||||
pub type Module<'a> = &'a ModuleData<'a>;
|
pub type Module<'a> = &'a ModuleData<'a>;
|
||||||
|
|
||||||
impl<'a> ModuleData<'a> {
|
impl<'a> ModuleData<'a> {
|
||||||
fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self {
|
fn new(parent: Option<Module<'a>>, kind: ModuleKind, normal_ancestor_id: DefId) -> Self {
|
||||||
ModuleData {
|
ModuleData {
|
||||||
parent: parent,
|
parent: parent,
|
||||||
kind: kind,
|
kind: kind,
|
||||||
normal_ancestor_id: None,
|
normal_ancestor_id: normal_ancestor_id,
|
||||||
resolutions: RefCell::new(FxHashMap()),
|
resolutions: RefCell::new(FxHashMap()),
|
||||||
legacy_macro_resolutions: RefCell::new(Vec::new()),
|
legacy_macro_resolutions: RefCell::new(Vec::new()),
|
||||||
macro_resolutions: RefCell::new(Vec::new()),
|
macro_resolutions: RefCell::new(Vec::new()),
|
||||||
@ -811,7 +810,7 @@ fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self {
|
|||||||
glob_importers: RefCell::new(Vec::new()),
|
glob_importers: RefCell::new(Vec::new()),
|
||||||
globs: RefCell::new((Vec::new())),
|
globs: RefCell::new((Vec::new())),
|
||||||
traits: RefCell::new(None),
|
traits: RefCell::new(None),
|
||||||
populated: Cell::new(true),
|
populated: Cell::new(normal_ancestor_id.is_local()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -848,7 +847,7 @@ fn is_trait(&self) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_local(&self) -> bool {
|
fn is_local(&self) -> bool {
|
||||||
self.normal_ancestor_id.is_some()
|
self.normal_ancestor_id.is_local()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,7 +1062,7 @@ pub struct Resolver<'a> {
|
|||||||
pub export_map: ExportMap,
|
pub export_map: ExportMap,
|
||||||
pub trait_map: TraitMap,
|
pub trait_map: TraitMap,
|
||||||
|
|
||||||
// A map from nodes to modules, both normal (`mod`) modules and anonymous modules.
|
// A map from nodes to anonymous modules.
|
||||||
// Anonymous modules are pseudo-modules that are implicitly created around items
|
// Anonymous modules are pseudo-modules that are implicitly created around items
|
||||||
// contained within blocks.
|
// contained within blocks.
|
||||||
//
|
//
|
||||||
@ -1077,7 +1076,8 @@ pub struct Resolver<'a> {
|
|||||||
//
|
//
|
||||||
// There will be an anonymous module created around `g` with the ID of the
|
// There will be an anonymous module created around `g` with the ID of the
|
||||||
// entry block for `f`.
|
// entry block for `f`.
|
||||||
module_map: NodeMap<Module<'a>>,
|
block_map: NodeMap<Module<'a>>,
|
||||||
|
module_map: FxHashMap<DefId, Module<'a>>,
|
||||||
extern_crate_roots: FxHashMap<(CrateNum, bool /* MacrosOnly? */), Module<'a>>,
|
extern_crate_roots: FxHashMap<(CrateNum, bool /* MacrosOnly? */), Module<'a>>,
|
||||||
|
|
||||||
pub make_glob_map: bool,
|
pub make_glob_map: bool,
|
||||||
@ -1153,15 +1153,12 @@ fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBindi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ty::NodeIdTree for Resolver<'a> {
|
impl<'a, 'b: 'a> ty::DefIdTree for &'a Resolver<'b> {
|
||||||
fn is_descendant_of(&self, mut node: NodeId, ancestor: NodeId) -> bool {
|
fn parent(self, id: DefId) -> Option<DefId> {
|
||||||
while node != ancestor {
|
match id.krate {
|
||||||
node = match self.module_map[&node].parent {
|
LOCAL_CRATE => self.definitions.def_key(id.index).parent,
|
||||||
Some(parent) => parent.normal_ancestor_id.unwrap(),
|
_ => self.session.cstore.def_key(id).parent,
|
||||||
None => return false,
|
}.map(|index| DefId { index: index, ..id })
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1202,14 +1199,14 @@ pub fn new(session: &'a Session,
|
|||||||
crate_loader: &'a mut CrateLoader,
|
crate_loader: &'a mut CrateLoader,
|
||||||
arenas: &'a ResolverArenas<'a>)
|
arenas: &'a ResolverArenas<'a>)
|
||||||
-> Resolver<'a> {
|
-> Resolver<'a> {
|
||||||
let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX));
|
let root_def_id = DefId::local(CRATE_DEF_INDEX);
|
||||||
|
let root_module_kind = ModuleKind::Def(Def::Mod(root_def_id), keywords::Invalid.name());
|
||||||
let graph_root = arenas.alloc_module(ModuleData {
|
let graph_root = arenas.alloc_module(ModuleData {
|
||||||
normal_ancestor_id: Some(CRATE_NODE_ID),
|
|
||||||
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
|
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
|
||||||
..ModuleData::new(None, ModuleKind::Def(root_def, keywords::Invalid.name()))
|
..ModuleData::new(None, root_module_kind, root_def_id)
|
||||||
});
|
});
|
||||||
let mut module_map = NodeMap();
|
let mut module_map = FxHashMap();
|
||||||
module_map.insert(CRATE_NODE_ID, graph_root);
|
module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
|
||||||
|
|
||||||
let mut definitions = Definitions::new();
|
let mut definitions = Definitions::new();
|
||||||
DefCollector::new(&mut definitions).collect_root();
|
DefCollector::new(&mut definitions).collect_root();
|
||||||
@ -1254,6 +1251,7 @@ pub fn new(session: &'a Session,
|
|||||||
export_map: NodeMap(),
|
export_map: NodeMap(),
|
||||||
trait_map: NodeMap(),
|
trait_map: NodeMap(),
|
||||||
module_map: module_map,
|
module_map: module_map,
|
||||||
|
block_map: NodeMap(),
|
||||||
extern_crate_roots: FxHashMap(),
|
extern_crate_roots: FxHashMap(),
|
||||||
|
|
||||||
make_glob_map: make_glob_map == MakeGlobMap::Yes,
|
make_glob_map: make_glob_map == MakeGlobMap::Yes,
|
||||||
@ -1324,12 +1322,9 @@ pub fn resolve_crate(&mut self, krate: &Crate) {
|
|||||||
self.crate_loader.postprocess(krate);
|
self.crate_loader.postprocess(krate);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> {
|
fn new_module(&self, parent: Module<'a>, kind: ModuleKind, normal_ancestor_id: DefId)
|
||||||
self.arenas.alloc_module(ModuleData {
|
-> Module<'a> {
|
||||||
normal_ancestor_id: if local { self.current_module.normal_ancestor_id } else { None },
|
self.arenas.alloc_module(ModuleData::new(Some(parent), kind, normal_ancestor_id))
|
||||||
populated: Cell::new(local),
|
|
||||||
..ModuleData::new(Some(parent), kind)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
|
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
|
||||||
@ -1462,6 +1457,7 @@ fn resolve_crate_var(&mut self, mut crate_var_ctxt: SyntaxContext) -> Module<'a>
|
|||||||
fn with_scope<F>(&mut self, id: NodeId, f: F)
|
fn with_scope<F>(&mut self, id: NodeId, f: F)
|
||||||
where F: FnOnce(&mut Resolver)
|
where F: FnOnce(&mut Resolver)
|
||||||
{
|
{
|
||||||
|
let id = self.definitions.local_def_id(id);
|
||||||
let module = self.module_map.get(&id).cloned(); // clones a reference
|
let module = self.module_map.get(&id).cloned(); // clones a reference
|
||||||
if let Some(module) = module {
|
if let Some(module) = module {
|
||||||
// Move down in the graph.
|
// Move down in the graph.
|
||||||
@ -1958,7 +1954,7 @@ fn resolve_block(&mut self, block: &Block) {
|
|||||||
debug!("(resolving block) entering block");
|
debug!("(resolving block) entering block");
|
||||||
// Move down in the graph, if there's an anonymous module rooted here.
|
// Move down in the graph, if there's an anonymous module rooted here.
|
||||||
let orig_module = self.current_module;
|
let orig_module = self.current_module;
|
||||||
let anonymous_module = self.module_map.get(&block.id).cloned(); // clones a reference
|
let anonymous_module = self.block_map.get(&block.id).cloned(); // clones a reference
|
||||||
|
|
||||||
let mut num_macro_definition_ribs = 0;
|
let mut num_macro_definition_ribs = 0;
|
||||||
if let Some(anonymous_module) = anonymous_module {
|
if let Some(anonymous_module) = anonymous_module {
|
||||||
@ -2334,13 +2330,13 @@ fn resolve_path(&mut self,
|
|||||||
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
|
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
|
||||||
|
|
||||||
if i == 0 && ns == TypeNS && ident.name == keywords::SelfValue.name() {
|
if i == 0 && ns == TypeNS && ident.name == keywords::SelfValue.name() {
|
||||||
module = Some(self.module_map[&self.current_module.normal_ancestor_id.unwrap()]);
|
module = Some(self.module_map[&self.current_module.normal_ancestor_id]);
|
||||||
continue
|
continue
|
||||||
} else if allow_super && ns == TypeNS && ident.name == keywords::Super.name() {
|
} else if allow_super && ns == TypeNS && ident.name == keywords::Super.name() {
|
||||||
let current_module = if i == 0 { self.current_module } else { module.unwrap() };
|
let current_module = if i == 0 { self.current_module } else { module.unwrap() };
|
||||||
let self_module = self.module_map[¤t_module.normal_ancestor_id.unwrap()];
|
let self_module = self.module_map[¤t_module.normal_ancestor_id];
|
||||||
if let Some(parent) = self_module.parent {
|
if let Some(parent) = self_module.parent {
|
||||||
module = Some(self.module_map[&parent.normal_ancestor_id.unwrap()]);
|
module = Some(self.module_map[&parent.normal_ancestor_id]);
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
let msg = "There are too many initial `super`s.".to_string();
|
let msg = "There are too many initial `super`s.".to_string();
|
||||||
@ -3001,10 +2997,12 @@ fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
|
|||||||
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
||||||
let (segments, span, id) = match *vis {
|
let (segments, span, id) = match *vis {
|
||||||
ast::Visibility::Public => return ty::Visibility::Public,
|
ast::Visibility::Public => return ty::Visibility::Public,
|
||||||
ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID),
|
ast::Visibility::Crate(_) => {
|
||||||
|
return ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
|
||||||
|
}
|
||||||
ast::Visibility::Restricted { ref path, id } => (&path.segments, path.span, id),
|
ast::Visibility::Restricted { ref path, id } => (&path.segments, path.span, id),
|
||||||
ast::Visibility::Inherited => {
|
ast::Visibility::Inherited => {
|
||||||
return ty::Visibility::Restricted(self.current_module.normal_ancestor_id.unwrap());
|
return ty::Visibility::Restricted(self.current_module.normal_ancestor_id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -3013,7 +3011,7 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
|||||||
let vis = match self.resolve_path(&path, None, Some(span)) {
|
let vis = match self.resolve_path(&path, None, Some(span)) {
|
||||||
PathResult::Module(module) => {
|
PathResult::Module(module) => {
|
||||||
path_resolution = PathResolution::new(module.def().unwrap());
|
path_resolution = PathResolution::new(module.def().unwrap());
|
||||||
ty::Visibility::Restricted(module.normal_ancestor_id.unwrap())
|
ty::Visibility::Restricted(module.normal_ancestor_id)
|
||||||
}
|
}
|
||||||
PathResult::Failed(msg, _) => {
|
PathResult::Failed(msg, _) => {
|
||||||
self.session.span_err(span, &format!("failed to resolve module path. {}", msg));
|
self.session.span_err(span, &format!("failed to resolve module path. {}", msg));
|
||||||
@ -3030,11 +3028,11 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_accessible(&self, vis: ty::Visibility) -> bool {
|
fn is_accessible(&self, vis: ty::Visibility) -> bool {
|
||||||
vis.is_accessible_from(self.current_module.normal_ancestor_id.unwrap(), self)
|
vis.is_accessible_from(self.current_module.normal_ancestor_id, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
|
fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
|
||||||
vis.is_accessible_from(module.normal_ancestor_id.unwrap(), self)
|
vis.is_accessible_from(module.normal_ancestor_id, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_errors(&mut self) {
|
fn report_errors(&mut self) {
|
||||||
|
@ -88,7 +88,7 @@ fn next_node_id(&mut self) -> ast::NodeId {
|
|||||||
|
|
||||||
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
|
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
|
||||||
let mark = Mark::fresh();
|
let mark = Mark::fresh();
|
||||||
let module = self.module_map[&id];
|
let module = self.module_map[&self.definitions.local_def_id(id)];
|
||||||
self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
|
self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
|
||||||
module: Cell::new(module),
|
module: Cell::new(module),
|
||||||
def_index: module.def_id().unwrap().index,
|
def_index: module.def_id().unwrap().index,
|
||||||
@ -154,7 +154,7 @@ fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
|
|||||||
let binding = self.arenas.alloc_name_binding(NameBinding {
|
let binding = self.arenas.alloc_name_binding(NameBinding {
|
||||||
kind: NameBindingKind::Def(Def::Macro(def_id)),
|
kind: NameBindingKind::Def(Def::Macro(def_id)),
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
vis: ty::Visibility::PrivateExternal,
|
vis: ty::Visibility::Invisible,
|
||||||
expansion: Mark::root(),
|
expansion: Mark::root(),
|
||||||
});
|
});
|
||||||
self.builtin_macros.insert(ident.name, binding);
|
self.builtin_macros.insert(ident.name, binding);
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
|
use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
|
||||||
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::def::*;
|
use rustc::hir::def::*;
|
||||||
|
|
||||||
use syntax::ast::{Ident, NodeId};
|
use syntax::ast::{Ident, NodeId};
|
||||||
@ -274,7 +275,7 @@ pub fn add_import_directive(&mut self,
|
|||||||
|
|
||||||
// Given a binding and an import directive that resolves to it,
|
// Given a binding and an import directive that resolves to it,
|
||||||
// return the corresponding binding defined by the import directive.
|
// return the corresponding binding defined by the import directive.
|
||||||
pub fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
|
pub fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
|
||||||
-> &'a NameBinding<'a> {
|
-> &'a NameBinding<'a> {
|
||||||
let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
|
let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
|
||||||
!directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
|
!directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
|
||||||
@ -316,7 +317,7 @@ pub fn try_define(&mut self,
|
|||||||
resolution.shadows_glob = Some(binding);
|
resolution.shadows_glob = Some(binding);
|
||||||
} else if binding.def() != old_binding.def() {
|
} else if binding.def() != old_binding.def() {
|
||||||
resolution.binding = Some(this.ambiguity(old_binding, binding));
|
resolution.binding = Some(this.ambiguity(old_binding, binding));
|
||||||
} else if !old_binding.vis.is_at_least(binding.vis, this) {
|
} else if !old_binding.vis.is_at_least(binding.vis, &*this) {
|
||||||
// We are glob-importing the same item but with greater visibility.
|
// We are glob-importing the same item but with greater visibility.
|
||||||
resolution.binding = Some(binding);
|
resolution.binding = Some(binding);
|
||||||
}
|
}
|
||||||
@ -339,7 +340,7 @@ pub fn try_define(&mut self,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ambiguity(&mut self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>)
|
pub fn ambiguity(&self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>)
|
||||||
-> &'a NameBinding<'a> {
|
-> &'a NameBinding<'a> {
|
||||||
self.arenas.alloc_name_binding(NameBinding {
|
self.arenas.alloc_name_binding(NameBinding {
|
||||||
kind: NameBindingKind::Ambiguity { b1: b1, b2: b2, legacy: false },
|
kind: NameBindingKind::Ambiguity { b1: b1, b2: b2, legacy: false },
|
||||||
@ -414,9 +415,9 @@ fn deref_mut(&mut self) -> &mut Resolver<'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b: 'a> ty::NodeIdTree for ImportResolver<'a, 'b> {
|
impl<'a, 'b: 'a> ty::DefIdTree for &'a ImportResolver<'a, 'b> {
|
||||||
fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
|
fn parent(self, id: DefId) -> Option<DefId> {
|
||||||
self.resolver.is_descendant_of(node, ancestor)
|
self.resolver.parent(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +490,7 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
|
|||||||
let vis = directive.vis.get();
|
let vis = directive.vis.get();
|
||||||
// For better failure detection, pretend that the import will not define any names
|
// For better failure detection, pretend that the import will not define any names
|
||||||
// while resolving its module path.
|
// while resolving its module path.
|
||||||
directive.vis.set(ty::Visibility::PrivateExternal);
|
directive.vis.set(ty::Visibility::Invisible);
|
||||||
let result = self.resolve_path(&directive.module_path, None, None);
|
let result = self.resolve_path(&directive.module_path, None, None);
|
||||||
directive.vis.set(vis);
|
directive.vis.set(vis);
|
||||||
|
|
||||||
@ -579,8 +580,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
|
|||||||
}
|
}
|
||||||
GlobImport { is_prelude, ref max_vis } => {
|
GlobImport { is_prelude, ref max_vis } => {
|
||||||
if !is_prelude &&
|
if !is_prelude &&
|
||||||
max_vis.get() != ty::Visibility::PrivateExternal && // Allow empty globs.
|
max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
|
||||||
!max_vis.get().is_at_least(directive.vis.get(), self) {
|
!max_vis.get().is_at_least(directive.vis.get(), &*self) {
|
||||||
let msg = "A non-empty glob must import something with the glob's visibility";
|
let msg = "A non-empty glob must import something with the glob's visibility";
|
||||||
self.session.span_err(directive.span, msg);
|
self.session.span_err(directive.span, msg);
|
||||||
}
|
}
|
||||||
@ -643,7 +644,7 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<Stri
|
|||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if let Ok(binding) = result[ns].get() {
|
if let Ok(binding) = result[ns].get() {
|
||||||
let vis = directive.vis.get();
|
let vis = directive.vis.get();
|
||||||
if !binding.pseudo_vis().is_at_least(vis, this) {
|
if !binding.pseudo_vis().is_at_least(vis, &*this) {
|
||||||
reexport_error = Some((ns, binding));
|
reexport_error = Some((ns, binding));
|
||||||
} else {
|
} else {
|
||||||
any_successful_reexport = true;
|
any_successful_reexport = true;
|
||||||
@ -751,7 +752,7 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
|
|||||||
match binding.kind {
|
match binding.kind {
|
||||||
NameBindingKind::Import { binding: orig_binding, directive, .. } => {
|
NameBindingKind::Import { binding: orig_binding, directive, .. } => {
|
||||||
if ns == TypeNS && orig_binding.is_variant() &&
|
if ns == TypeNS && orig_binding.is_variant() &&
|
||||||
!orig_binding.vis.is_at_least(binding.vis, self) {
|
!orig_binding.vis.is_at_least(binding.vis, &*self) {
|
||||||
let msg = format!("variant `{}` is private, and cannot be reexported \
|
let msg = format!("variant `{}` is private, and cannot be reexported \
|
||||||
(error E0364), consider declaring its enum as `pub`",
|
(error E0364), consider declaring its enum as `pub`",
|
||||||
ident);
|
ident);
|
||||||
|
@ -344,7 +344,7 @@ pub fn resolve_ufcs(&self,
|
|||||||
self.tcx.check_stability(def.def_id(), expr_id, span);
|
self.tcx.check_stability(def.def_id(), expr_id, span);
|
||||||
|
|
||||||
if let probe::InherentImplPick = pick.kind {
|
if let probe::InherentImplPick = pick.kind {
|
||||||
if !pick.item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
|
if !self.tcx.vis_is_accessible_from(pick.item.vis, self.body_id) {
|
||||||
let msg = format!("{} `{}` is private", def.kind_name(), method_name);
|
let msg = format!("{} `{}` is private", def.kind_name(), method_name);
|
||||||
self.tcx.sess.span_err(span, &msg);
|
self.tcx.sess.span_err(span, &msg);
|
||||||
}
|
}
|
||||||
|
@ -503,7 +503,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
|
if !self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
|
||||||
self.private_candidate = Some(item.def());
|
self.private_candidate = Some(item.def());
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -3009,7 +3009,7 @@ fn check_field(&self,
|
|||||||
debug!("struct named {:?}", base_t);
|
debug!("struct named {:?}", base_t);
|
||||||
if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
|
if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
|
||||||
let field_ty = self.field_ty(expr.span, field, substs);
|
let field_ty = self.field_ty(expr.span, field, substs);
|
||||||
if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
|
if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
|
||||||
autoderef.finalize(lvalue_pref, Some(base));
|
autoderef.finalize(lvalue_pref, Some(base));
|
||||||
self.write_autoderef_adjustment(base.id, autoderefs, base_t);
|
self.write_autoderef_adjustment(base.id, autoderefs, base_t);
|
||||||
|
|
||||||
@ -3116,7 +3116,7 @@ fn check_tup_field(&self,
|
|||||||
base_def.struct_variant().fields.get(idx.node).and_then(|field| {
|
base_def.struct_variant().fields.get(idx.node).and_then(|field| {
|
||||||
let field_ty = self.field_ty(expr.span, field, substs);
|
let field_ty = self.field_ty(expr.span, field, substs);
|
||||||
private_candidate = Some((base_def.did, field_ty));
|
private_candidate = Some((base_def.did, field_ty));
|
||||||
if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
|
if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
|
||||||
self.tcx.check_stability(field.did, expr.id, expr.span);
|
self.tcx.check_stability(field.did, expr.id, expr.span);
|
||||||
Some(field_ty)
|
Some(field_ty)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user