2014-01-25 01:37:51 -06:00
|
|
|
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2014-03-21 20:05:05 -05:00
|
|
|
#![allow(non_camel_case_types)]
|
2014-02-10 08:36:31 -06:00
|
|
|
|
2012-10-15 16:56:42 -05:00
|
|
|
use driver::session::Session;
|
2014-05-06 18:37:32 -05:00
|
|
|
use lint;
|
2013-08-21 19:26:33 -05:00
|
|
|
use metadata::csearch;
|
2013-08-31 11:13:04 -05:00
|
|
|
use metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
|
2014-05-14 14:31:30 -05:00
|
|
|
use middle::def::*;
|
2012-09-04 13:54:36 -05:00
|
|
|
use middle::lang_items::LanguageItems;
|
2013-03-26 15:38:07 -05:00
|
|
|
use middle::pat_util::pat_bindings;
|
2014-05-31 17:53:13 -05:00
|
|
|
use middle::subst::{ParamSpace, FnSpace, TypeSpace};
|
2014-05-06 18:37:32 -05:00
|
|
|
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
|
2014-09-17 21:45:21 -05:00
|
|
|
use middle::ty::{CaptureModeMap, Freevar, FreevarMap};
|
|
|
|
use util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2014-09-11 12:14:43 -05:00
|
|
|
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
|
2014-08-12 22:31:30 -05:00
|
|
|
use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField};
|
2014-08-25 05:35:03 -05:00
|
|
|
use syntax::ast::{ExprFnBlock, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
|
2014-08-12 22:31:30 -05:00
|
|
|
use syntax::ast::{ExprPath, ExprProc, ExprStruct, ExprUnboxedFn, FnDecl};
|
|
|
|
use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics};
|
|
|
|
use syntax::ast::{Ident, ImplItem, Item, ItemEnum, ItemFn, ItemForeignMod};
|
|
|
|
use syntax::ast::{ItemImpl, ItemMac, ItemMod, ItemStatic, ItemStruct};
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 10:17:01 -05:00
|
|
|
use syntax::ast::{ItemTrait, ItemTy, LOCAL_CRATE, Local, ItemConst};
|
2014-08-12 22:31:30 -05:00
|
|
|
use syntax::ast::{MethodImplItem, Mod, Name, NamedField, NodeId};
|
2014-09-07 12:09:06 -05:00
|
|
|
use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
|
2014-08-12 22:31:30 -05:00
|
|
|
use syntax::ast::{PatRange, PatStruct, Path, PathListIdent, PathListMod};
|
|
|
|
use syntax::ast::{PrimTy, Public, SelfExplicit, SelfStatic};
|
2014-08-27 20:46:52 -05:00
|
|
|
use syntax::ast::{RegionTyParamBound, StmtDecl, StructField};
|
2014-08-12 22:31:30 -05:00
|
|
|
use syntax::ast::{StructVariantKind, TraitRef, TraitTyParamBound};
|
|
|
|
use syntax::ast::{TupleVariantKind, Ty, TyBool, TyChar, TyClosure, TyF32};
|
|
|
|
use syntax::ast::{TyF64, TyFloat, TyI, TyI8, TyI16, TyI32, TyI64, TyInt};
|
2014-08-05 21:44:21 -05:00
|
|
|
use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyProc, TyQPath};
|
|
|
|
use syntax::ast::{TyRptr, TyStr, TyU, TyU8, TyU16, TyU32, TyU64, TyUint};
|
|
|
|
use syntax::ast::{TypeImplItem, UnboxedFnTyParamBound, UnnamedField};
|
2014-10-15 23:44:24 -05:00
|
|
|
use syntax::ast::{Variant, ViewItem, ViewItemExternCrate};
|
2014-08-05 21:44:21 -05:00
|
|
|
use syntax::ast::{ViewItemUse, ViewPathGlob, ViewPathList, ViewPathSimple};
|
|
|
|
use syntax::ast::{Visibility};
|
2013-05-21 20:24:42 -05:00
|
|
|
use syntax::ast;
|
2014-09-07 12:09:06 -05:00
|
|
|
use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat};
|
2014-08-05 21:44:21 -05:00
|
|
|
use syntax::ast_util;
|
2014-08-12 22:31:30 -05:00
|
|
|
use syntax::attr::AttrMetaMethods;
|
2014-02-24 14:47:19 -06:00
|
|
|
use syntax::ext::mtwt;
|
2014-07-06 18:02:48 -05:00
|
|
|
use syntax::parse::token::special_names;
|
2014-02-13 23:07:09 -06:00
|
|
|
use syntax::parse::token::special_idents;
|
2013-05-14 19:27:27 -05:00
|
|
|
use syntax::parse::token;
|
2014-01-01 00:53:22 -06:00
|
|
|
use syntax::codemap::{Span, DUMMY_SP, Pos};
|
2014-03-19 09:52:37 -05:00
|
|
|
use syntax::owned_slice::OwnedSlice;
|
2013-08-13 11:52:41 -05:00
|
|
|
use syntax::visit;
|
|
|
|
use syntax::visit::Visitor;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-05-29 21:03:06 -05:00
|
|
|
use std::collections::{HashMap, HashSet};
|
2014-09-18 16:05:52 -05:00
|
|
|
use std::collections::hashmap::{Occupied, Vacant};
|
2013-12-20 23:14:25 -06:00
|
|
|
use std::cell::{Cell, RefCell};
|
2014-01-31 14:35:36 -06:00
|
|
|
use std::mem::replace;
|
2014-04-14 03:30:59 -05:00
|
|
|
use std::rc::{Rc, Weak};
|
2014-04-02 18:54:22 -05:00
|
|
|
use std::uint;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Definition mapping
|
2014-04-22 11:06:43 -05:00
|
|
|
pub type DefMap = RefCell<NodeMap<Def>>;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
struct binding_info {
|
2013-08-31 11:13:04 -05:00
|
|
|
span: Span,
|
2013-09-01 20:45:37 -05:00
|
|
|
binding_mode: BindingMode,
|
2012-08-06 09:20:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Map from the name in a pattern to its binding mode.
|
2013-10-02 07:33:01 -05:00
|
|
|
type BindingMap = HashMap<Name,binding_info>;
|
2012-08-06 09:20:23 -05:00
|
|
|
|
2012-07-11 17:00:40 -05:00
|
|
|
// Trait method resolution
|
2014-03-04 12:02:49 -06:00
|
|
|
pub type TraitMap = NodeMap<Vec<DefId> >;
|
2012-07-11 17:00:40 -05:00
|
|
|
|
2012-08-17 14:41:34 -05:00
|
|
|
// This is the replacement export map. It maps a module to all of the exports
|
|
|
|
// within.
|
2014-09-29 18:06:13 -05:00
|
|
|
pub type ExportMap2 = NodeMap<Vec<Export2>>;
|
2012-08-17 14:41:34 -05:00
|
|
|
|
2013-01-30 15:44:24 -06:00
|
|
|
pub struct Export2 {
|
2014-05-22 18:57:53 -05:00
|
|
|
pub name: String, // The name of the target.
|
2014-03-28 12:05:27 -05:00
|
|
|
pub def_id: DefId, // The definition of the target.
|
2012-08-17 14:41:34 -05:00
|
|
|
}
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
// This set contains all exported definitions from external crates. The set does
|
|
|
|
// not contain any entries from local crates.
|
2014-02-28 16:34:26 -06:00
|
|
|
pub type ExternalExports = DefIdSet;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
|
2014-01-26 02:43:42 -06:00
|
|
|
// FIXME: dox
|
2014-02-28 16:34:26 -06:00
|
|
|
pub type LastPrivateMap = NodeMap<LastPrivate>;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
|
2014-10-15 01:25:34 -05:00
|
|
|
#[deriving(Show)]
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
pub enum LastPrivate {
|
2014-02-11 13:19:18 -06:00
|
|
|
LastMod(PrivateDep),
|
|
|
|
// `use` directives (imports) can refer to two separate definitions in the
|
|
|
|
// type and value namespaces. We record here the last private node for each
|
|
|
|
// and whether the import is in fact used for each.
|
2014-04-20 23:49:39 -05:00
|
|
|
// If the Option<PrivateDep> fields are None, it means there is no definition
|
2014-02-11 13:19:18 -06:00
|
|
|
// in that namespace.
|
2014-03-28 12:05:27 -05:00
|
|
|
LastImport{pub value_priv: Option<PrivateDep>,
|
|
|
|
pub value_used: ImportUse,
|
|
|
|
pub type_priv: Option<PrivateDep>,
|
|
|
|
pub type_used: ImportUse},
|
2014-02-11 13:19:18 -06:00
|
|
|
}
|
|
|
|
|
2014-10-15 01:25:34 -05:00
|
|
|
#[deriving(Show)]
|
2014-02-11 13:19:18 -06:00
|
|
|
pub enum PrivateDep {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
AllPublic,
|
|
|
|
DependsOn(DefId),
|
|
|
|
}
|
|
|
|
|
2014-02-11 13:19:18 -06:00
|
|
|
// How an import is used.
|
2014-10-15 01:25:34 -05:00
|
|
|
#[deriving(PartialEq, Show)]
|
2014-02-11 13:19:18 -06:00
|
|
|
pub enum ImportUse {
|
|
|
|
Unused, // The import is not used.
|
|
|
|
Used, // The import is used.
|
|
|
|
}
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
impl LastPrivate {
|
|
|
|
fn or(self, other: LastPrivate) -> LastPrivate {
|
|
|
|
match (self, other) {
|
2014-02-11 13:19:18 -06:00
|
|
|
(me, LastMod(AllPublic)) => me,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
(_, other) => other,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(PartialEq)]
|
2013-10-02 07:33:01 -05:00
|
|
|
enum PatternBindingMode {
|
2012-05-22 12:54:12 -05:00
|
|
|
RefutableMode,
|
2012-11-06 20:41:06 -06:00
|
|
|
LocalIrrefutableMode,
|
2013-04-24 03:29:46 -05:00
|
|
|
ArgumentIrrefutableMode,
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-10-15 01:25:34 -05:00
|
|
|
#[deriving(PartialEq, Eq, Hash, Show)]
|
2013-10-02 07:33:01 -05:00
|
|
|
enum Namespace {
|
2012-05-22 12:54:12 -05:00
|
|
|
TypeNS,
|
2012-08-17 19:09:53 -05:00
|
|
|
ValueNS
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(PartialEq)]
|
2013-10-02 07:33:01 -05:00
|
|
|
enum NamespaceError {
|
2013-06-23 11:48:43 -05:00
|
|
|
NoError,
|
|
|
|
ModuleError,
|
|
|
|
TypeError,
|
|
|
|
ValueError
|
|
|
|
}
|
|
|
|
|
2012-11-29 16:43:33 -06:00
|
|
|
/// A NamespaceResult represents the result of resolving an import in
|
|
|
|
/// a particular namespace. The result is either definitely-resolved,
|
|
|
|
/// definitely- unresolved, or unknown.
|
2014-04-14 03:30:59 -05:00
|
|
|
#[deriving(Clone)]
|
2013-10-02 07:33:01 -05:00
|
|
|
enum NamespaceResult {
|
2012-11-29 14:08:40 -06:00
|
|
|
/// Means that resolve hasn't gathered enough information yet to determine
|
|
|
|
/// whether the name is bound in this namespace. (That is, it hasn't
|
|
|
|
/// resolved all `use` directives yet.)
|
2012-05-22 12:54:12 -05:00
|
|
|
UnknownResult,
|
2012-11-29 16:43:33 -06:00
|
|
|
/// Means that resolve has determined that the name is definitely
|
|
|
|
/// not bound in the namespace.
|
2012-05-22 12:54:12 -05:00
|
|
|
UnboundResult,
|
2012-11-29 14:08:40 -06:00
|
|
|
/// Means that resolve has determined that the name is bound in the Module
|
|
|
|
/// argument, and specified by the NameBindings argument.
|
2014-04-14 03:30:59 -05:00
|
|
|
BoundResult(Rc<Module>, Rc<NameBindings>)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl NamespaceResult {
|
2013-10-02 07:33:01 -05:00
|
|
|
fn is_unknown(&self) -> bool {
|
2013-02-22 00:41:37 -06:00
|
|
|
match *self {
|
2012-08-27 18:26:35 -05:00
|
|
|
UnknownResult => true,
|
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
2014-04-08 17:03:29 -05:00
|
|
|
fn is_unbound(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
UnboundResult => true,
|
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
2012-08-27 18:26:35 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
enum NameDefinition {
|
2012-05-22 12:54:12 -05:00
|
|
|
NoNameDefinition, //< The name was unbound.
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
ChildNameDefinition(Def, LastPrivate), //< The name identifies an immediate child.
|
|
|
|
ImportNameDefinition(Def, LastPrivate) //< The name identifies an import.
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-09-09 17:54:36 -05:00
|
|
|
impl<'a, 'v> Visitor<'v> for Resolver<'a> {
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_item(&mut self, item: &Item) {
|
2013-09-26 21:10:16 -05:00
|
|
|
self.resolve_item(item);
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_arm(&mut self, arm: &Arm) {
|
2013-09-26 21:10:16 -05:00
|
|
|
self.resolve_arm(arm);
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_block(&mut self, block: &Block) {
|
2013-09-26 21:10:16 -05:00
|
|
|
self.resolve_block(block);
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_expr(&mut self, expr: &Expr) {
|
2013-09-26 21:10:16 -05:00
|
|
|
self.resolve_expr(expr);
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_local(&mut self, local: &Local) {
|
2013-09-26 21:10:16 -05:00
|
|
|
self.resolve_local(local);
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_ty(&mut self, ty: &Ty) {
|
2013-09-26 21:10:16 -05:00
|
|
|
self.resolve_type(ty);
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Contains data for specific types of import directives.
|
2013-10-02 07:33:01 -05:00
|
|
|
enum ImportDirectiveSubclass {
|
2014-09-30 19:11:34 -05:00
|
|
|
SingleImport(Name /* target */, Name /* source */),
|
2012-05-22 12:54:12 -05:00
|
|
|
GlobImport
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The context that we thread through while building the reduced graph.
|
2013-07-02 14:47:32 -05:00
|
|
|
#[deriving(Clone)]
|
2013-10-02 07:33:01 -05:00
|
|
|
enum ReducedGraphParent {
|
2014-04-14 03:30:59 -05:00
|
|
|
ModuleReducedGraphParent(Rc<Module>)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-11-01 20:06:31 -05:00
|
|
|
impl ReducedGraphParent {
|
2014-04-14 03:30:59 -05:00
|
|
|
fn module(&self) -> Rc<Module> {
|
2013-11-01 20:06:31 -05:00
|
|
|
match *self {
|
2014-04-14 03:30:59 -05:00
|
|
|
ModuleReducedGraphParent(ref m) => {
|
|
|
|
m.clone()
|
2013-11-01 20:06:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-05 16:37:52 -05:00
|
|
|
type ErrorMessage = Option<(Span, String)>;
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
enum ResolveResult<T> {
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(ErrorMessage), // Failed to resolve the name, optional helpful error message.
|
|
|
|
Indeterminate, // Couldn't determine due to unresolved globs.
|
|
|
|
Success(T) // Successfully resolved the import.
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl<T> ResolveResult<T> {
|
2013-10-02 07:33:01 -05:00
|
|
|
fn indeterminate(&self) -> bool {
|
2013-02-22 00:41:37 -06:00
|
|
|
match *self { Indeterminate => true, _ => false }
|
2012-09-07 20:53:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-08 16:35:09 -05:00
|
|
|
enum FallbackSuggestion {
|
|
|
|
NoSuggestion,
|
|
|
|
Field,
|
|
|
|
Method,
|
2014-08-04 15:56:56 -05:00
|
|
|
TraitItem,
|
2014-05-22 18:57:53 -05:00
|
|
|
StaticMethod(String),
|
2014-10-14 19:33:20 -05:00
|
|
|
TraitMethod(String),
|
2014-05-08 16:35:09 -05:00
|
|
|
}
|
|
|
|
|
2013-12-10 01:16:18 -06:00
|
|
|
enum TypeParameters<'a> {
|
2014-05-31 17:53:13 -05:00
|
|
|
NoTypeParameters,
|
|
|
|
HasTypeParameters(
|
|
|
|
// Type parameters.
|
|
|
|
&'a Generics,
|
|
|
|
|
|
|
|
// Identifies the things that these parameters
|
|
|
|
// were declared on (type, fn, etc)
|
|
|
|
ParamSpace,
|
|
|
|
|
|
|
|
// ID of the enclosing item.
|
|
|
|
NodeId,
|
|
|
|
|
|
|
|
// The kind of the rib used for type parameters.
|
|
|
|
RibKind)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-09-17 09:28:19 -05:00
|
|
|
// The rib kind controls the translation of local
|
|
|
|
// definitions (`DefLocal`) to upvars (`DefUpvar`).
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
enum RibKind {
|
2012-05-22 12:54:12 -05:00
|
|
|
// No translation needs to be applied.
|
|
|
|
NormalRibKind,
|
2012-07-06 21:06:58 -05:00
|
|
|
|
2014-09-14 16:40:45 -05:00
|
|
|
// We passed through a closure scope at the given node ID.
|
|
|
|
// Translate upvars as appropriate.
|
2014-09-17 21:45:21 -05:00
|
|
|
ClosureRibKind(NodeId /* func id */, NodeId /* body id if proc or unboxed */),
|
2012-07-06 21:06:58 -05:00
|
|
|
|
2012-12-10 15:47:54 -06:00
|
|
|
// We passed through an impl or trait and are now in one of its
|
2013-06-06 02:38:41 -05:00
|
|
|
// methods. Allow references to ty params that impl or trait
|
2012-07-26 16:04:03 -05:00
|
|
|
// binds. Disallow any other upvars (including other ty params that are
|
|
|
|
// upvars).
|
|
|
|
// parent; method itself
|
2013-07-27 03:25:59 -05:00
|
|
|
MethodRibKind(NodeId, MethodSort),
|
2012-07-26 16:04:03 -05:00
|
|
|
|
2014-05-31 00:54:04 -05:00
|
|
|
// We passed through an item scope. Disallow upvars.
|
|
|
|
ItemRibKind,
|
2012-10-15 14:27:09 -05:00
|
|
|
|
|
|
|
// We're in a constant item. Can't refer to dynamic stuff.
|
|
|
|
ConstantItemRibKind
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-08-04 15:56:56 -05:00
|
|
|
// Methods can be required or provided. RequiredMethod methods only occur in traits.
|
2013-10-02 07:33:01 -05:00
|
|
|
enum MethodSort {
|
2014-08-04 15:56:56 -05:00
|
|
|
RequiredMethod,
|
|
|
|
ProvidedMethod(NodeId)
|
2012-07-26 16:04:03 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
enum UseLexicalScopeFlag {
|
2012-12-13 15:05:22 -06:00
|
|
|
DontUseLexicalScope,
|
|
|
|
UseLexicalScope
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
enum ModulePrefixResult {
|
2012-12-23 16:41:37 -06:00
|
|
|
NoPrefixFound,
|
2014-04-14 03:30:59 -05:00
|
|
|
PrefixFound(Rc<Module>, uint)
|
2012-12-13 15:05:22 -06:00
|
|
|
}
|
|
|
|
|
2014-05-06 18:37:32 -05:00
|
|
|
#[deriving(Clone, Eq, PartialEq)]
|
2014-08-04 15:56:56 -05:00
|
|
|
pub enum TraitItemKind {
|
|
|
|
NonstaticMethodTraitItemKind,
|
|
|
|
StaticMethodTraitItemKind,
|
2014-08-05 21:44:21 -05:00
|
|
|
TypeTraitItemKind,
|
2014-05-06 18:37:32 -05:00
|
|
|
}
|
|
|
|
|
2014-08-04 15:56:56 -05:00
|
|
|
impl TraitItemKind {
|
|
|
|
pub fn from_explicit_self_category(explicit_self_category:
|
|
|
|
ExplicitSelfCategory)
|
|
|
|
-> TraitItemKind {
|
2014-05-06 18:37:32 -05:00
|
|
|
if explicit_self_category == StaticExplicitSelfCategory {
|
2014-08-04 15:56:56 -05:00
|
|
|
StaticMethodTraitItemKind
|
2014-05-06 18:37:32 -05:00
|
|
|
} else {
|
2014-08-04 15:56:56 -05:00
|
|
|
NonstaticMethodTraitItemKind
|
2014-05-06 18:37:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(PartialEq)]
|
2013-03-01 12:44:43 -06:00
|
|
|
enum NameSearchType {
|
2013-05-13 18:13:20 -05:00
|
|
|
/// We're doing a name search in order to resolve a `use` directive.
|
|
|
|
ImportSearch,
|
|
|
|
|
|
|
|
/// We're doing a name search in order to resolve a path type, a path
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
/// expression, or a path pattern.
|
|
|
|
PathSearch,
|
2013-03-01 12:44:43 -06:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
enum BareIdentifierPatternResolution {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
FoundStructOrEnumVariant(Def, LastPrivate),
|
|
|
|
FoundConst(Def, LastPrivate),
|
2012-10-30 17:53:06 -05:00
|
|
|
BareIdentifierPatternUnresolved
|
2012-07-06 21:06:58 -05:00
|
|
|
}
|
|
|
|
|
2012-10-15 20:04:15 -05:00
|
|
|
// Specifies how duplicates should be handled when adding a child item if
|
|
|
|
// another item exists with the same name in some namespace.
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(PartialEq)]
|
2013-10-02 07:33:01 -05:00
|
|
|
enum DuplicateCheckingMode {
|
2012-10-15 20:04:15 -05:00
|
|
|
ForbidDuplicateModules,
|
2014-07-04 19:59:55 -05:00
|
|
|
ForbidDuplicateTypesAndModules,
|
2012-10-15 20:04:15 -05:00
|
|
|
ForbidDuplicateValues,
|
|
|
|
ForbidDuplicateTypesAndValues,
|
|
|
|
OverwriteDuplicates
|
|
|
|
}
|
|
|
|
|
2012-08-14 21:20:56 -05:00
|
|
|
/// One local scope.
|
2013-10-02 07:33:01 -05:00
|
|
|
struct Rib {
|
2014-09-29 18:06:13 -05:00
|
|
|
bindings: HashMap<Name, DefLike>,
|
2012-09-06 21:40:15 -05:00
|
|
|
kind: RibKind,
|
2012-09-05 17:58:43 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-08-31 11:13:04 -05:00
|
|
|
impl Rib {
|
2013-10-02 07:33:01 -05:00
|
|
|
fn new(kind: RibKind) -> Rib {
|
2013-08-31 11:13:04 -05:00
|
|
|
Rib {
|
2014-09-29 18:06:13 -05:00
|
|
|
bindings: HashMap::new(),
|
2013-08-31 11:13:04 -05:00
|
|
|
kind: kind
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// One import directive.
|
2013-10-02 07:33:01 -05:00
|
|
|
struct ImportDirective {
|
2014-09-30 19:11:34 -05:00
|
|
|
module_path: Vec<Name>,
|
2014-04-14 03:30:59 -05:00
|
|
|
subclass: ImportDirectiveSubclass,
|
2013-08-31 11:13:04 -05:00
|
|
|
span: Span,
|
2013-07-27 03:25:59 -05:00
|
|
|
id: NodeId,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
is_public: bool, // see note in ImportResolution about how to use this
|
2014-08-12 22:31:30 -05:00
|
|
|
shadowable: bool,
|
2012-09-05 17:58:43 -05:00
|
|
|
}
|
2012-07-06 21:06:58 -05:00
|
|
|
|
2013-08-31 11:13:04 -05:00
|
|
|
impl ImportDirective {
|
2014-09-30 19:11:34 -05:00
|
|
|
fn new(module_path: Vec<Name> ,
|
2014-04-14 03:30:59 -05:00
|
|
|
subclass: ImportDirectiveSubclass,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
span: Span,
|
|
|
|
id: NodeId,
|
2014-08-12 22:31:30 -05:00
|
|
|
is_public: bool,
|
|
|
|
shadowable: bool)
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
-> ImportDirective {
|
2013-08-31 11:13:04 -05:00
|
|
|
ImportDirective {
|
|
|
|
module_path: module_path,
|
|
|
|
subclass: subclass,
|
|
|
|
span: span,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
id: id,
|
|
|
|
is_public: is_public,
|
2014-08-12 22:31:30 -05:00
|
|
|
shadowable: shadowable,
|
2013-08-31 11:13:04 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The item that an import resolves to.
|
2013-12-21 19:40:36 -06:00
|
|
|
#[deriving(Clone)]
|
2013-10-02 07:33:01 -05:00
|
|
|
struct Target {
|
2014-04-14 03:30:59 -05:00
|
|
|
target_module: Rc<Module>,
|
|
|
|
bindings: Rc<NameBindings>,
|
2014-08-12 22:31:30 -05:00
|
|
|
shadowable: bool,
|
2012-09-05 17:58:43 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-08-31 11:13:04 -05:00
|
|
|
impl Target {
|
2014-08-12 22:31:30 -05:00
|
|
|
fn new(target_module: Rc<Module>,
|
|
|
|
bindings: Rc<NameBindings>,
|
|
|
|
shadowable: bool)
|
|
|
|
-> Target {
|
2013-08-31 11:13:04 -05:00
|
|
|
Target {
|
|
|
|
target_module: target_module,
|
2014-08-12 22:31:30 -05:00
|
|
|
bindings: bindings,
|
|
|
|
shadowable: shadowable,
|
2013-08-31 11:13:04 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-29 14:08:40 -06:00
|
|
|
/// An ImportResolution represents a particular `use` directive.
|
2013-10-02 07:33:01 -05:00
|
|
|
struct ImportResolution {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
/// Whether this resolution came from a `use` or a `pub use`. Note that this
|
|
|
|
/// should *not* be used whenever resolution is being performed, this is
|
|
|
|
/// only looked at for glob imports statements currently. Privacy testing
|
|
|
|
/// occurs during a later phase of compilation.
|
2014-04-14 03:30:59 -05:00
|
|
|
is_public: bool,
|
2012-07-06 21:06:58 -05:00
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// The number of outstanding references to this name. When this reaches
|
|
|
|
// zero, outside modules can count on the targets being correct. Before
|
|
|
|
// then, all bets are off; future imports could override this name.
|
2014-04-14 03:30:59 -05:00
|
|
|
outstanding_references: uint,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-11-29 14:08:40 -06:00
|
|
|
/// The value that this `use` directive names, if there is one.
|
2014-04-14 03:30:59 -05:00
|
|
|
value_target: Option<Target>,
|
2013-06-09 23:39:15 -05:00
|
|
|
/// The source node of the `use` directive leading to the value target
|
|
|
|
/// being non-none
|
2014-04-14 03:30:59 -05:00
|
|
|
value_id: NodeId,
|
2013-06-09 23:39:15 -05:00
|
|
|
|
2012-11-29 14:08:40 -06:00
|
|
|
/// The type that this `use` directive names, if there is one.
|
2014-04-14 03:30:59 -05:00
|
|
|
type_target: Option<Target>,
|
2013-06-09 23:39:15 -05:00
|
|
|
/// The source node of the `use` directive leading to the type target
|
|
|
|
/// being non-none
|
2014-04-14 03:30:59 -05:00
|
|
|
type_id: NodeId,
|
2014-03-28 12:29:55 -05:00
|
|
|
}
|
|
|
|
|
2013-08-31 11:13:04 -05:00
|
|
|
impl ImportResolution {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
fn new(id: NodeId, is_public: bool) -> ImportResolution {
|
2013-08-31 11:13:04 -05:00
|
|
|
ImportResolution {
|
2014-04-14 03:30:59 -05:00
|
|
|
type_id: id,
|
|
|
|
value_id: id,
|
|
|
|
outstanding_references: 0,
|
|
|
|
value_target: None,
|
|
|
|
type_target: None,
|
|
|
|
is_public: is_public,
|
2013-08-31 11:13:04 -05:00
|
|
|
}
|
2012-09-05 17:58:43 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn target_for_namespace(&self, namespace: Namespace)
|
2013-05-31 17:17:22 -05:00
|
|
|
-> Option<Target> {
|
2012-09-07 21:04:40 -05:00
|
|
|
match namespace {
|
2014-04-14 03:30:59 -05:00
|
|
|
TypeNS => self.type_target.clone(),
|
|
|
|
ValueNS => self.value_target.clone(),
|
2012-09-07 21:04:40 -05:00
|
|
|
}
|
|
|
|
}
|
2013-06-09 23:39:15 -05:00
|
|
|
|
2013-07-27 03:25:59 -05:00
|
|
|
fn id(&self, namespace: Namespace) -> NodeId {
|
2013-06-09 23:39:15 -05:00
|
|
|
match namespace {
|
2014-04-14 03:30:59 -05:00
|
|
|
TypeNS => self.type_id,
|
|
|
|
ValueNS => self.value_id,
|
2013-06-09 23:39:15 -05:00
|
|
|
}
|
|
|
|
}
|
2012-09-07 21:04:40 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The link from a module up to its nearest parent node.
|
2014-04-14 03:30:59 -05:00
|
|
|
#[deriving(Clone)]
|
2013-10-02 07:33:01 -05:00
|
|
|
enum ParentLink {
|
2012-05-22 12:54:12 -05:00
|
|
|
NoParentLink,
|
2014-09-30 19:11:34 -05:00
|
|
|
ModuleParentLink(Weak<Module>, Name),
|
2014-04-14 03:30:59 -05:00
|
|
|
BlockParentLink(Weak<Module>, NodeId)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
/// The type of module this is.
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(PartialEq)]
|
2013-10-02 07:33:01 -05:00
|
|
|
enum ModuleKind {
|
2012-12-23 16:41:37 -06:00
|
|
|
NormalModuleKind,
|
|
|
|
TraitModuleKind,
|
2013-05-13 18:13:20 -05:00
|
|
|
ImplModuleKind,
|
2014-10-19 01:46:08 -05:00
|
|
|
EnumModuleKind,
|
2012-12-23 16:41:37 -06:00
|
|
|
AnonymousModuleKind,
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// One node in the tree of modules.
|
2013-10-02 07:33:01 -05:00
|
|
|
struct Module {
|
2012-09-06 21:40:15 -05:00
|
|
|
parent_link: ParentLink,
|
2013-12-19 20:56:20 -06:00
|
|
|
def_id: Cell<Option<DefId>>,
|
2013-12-19 20:52:35 -06:00
|
|
|
kind: Cell<ModuleKind>,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
is_public: bool,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
children: RefCell<HashMap<Name, Rc<NameBindings>>>,
|
|
|
|
imports: RefCell<Vec<ImportDirective>>,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-03-26 21:53:33 -05:00
|
|
|
// The external module children of this node that were declared with
|
2014-02-14 12:10:06 -06:00
|
|
|
// `extern crate`.
|
2014-04-14 03:30:59 -05:00
|
|
|
external_module_children: RefCell<HashMap<Name, Rc<Module>>>,
|
2013-03-26 21:53:33 -05:00
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// The anonymous children of this node. Anonymous children are pseudo-
|
|
|
|
// modules that are implicitly created around items contained within
|
|
|
|
// blocks.
|
|
|
|
//
|
|
|
|
// For example, if we have this:
|
|
|
|
//
|
|
|
|
// fn f() {
|
|
|
|
// fn g() {
|
|
|
|
// ...
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// There will be an anonymous module created around `g` with the ID of the
|
|
|
|
// entry block for `f`.
|
2014-04-14 03:30:59 -05:00
|
|
|
anonymous_children: RefCell<NodeMap<Rc<Module>>>,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// The status of resolving each import in this module.
|
2014-04-14 03:30:59 -05:00
|
|
|
import_resolutions: RefCell<HashMap<Name, ImportResolution>>,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// The number of unresolved globs that this module exports.
|
2013-12-19 20:59:03 -06:00
|
|
|
glob_count: Cell<uint>,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// The index of the import we're resolving.
|
2013-12-19 21:01:02 -06:00
|
|
|
resolved_import_count: Cell<uint>,
|
2013-08-21 20:39:30 -05:00
|
|
|
|
|
|
|
// Whether this module is populated. If not populated, any attempt to
|
|
|
|
// access the children must be preceded with a
|
|
|
|
// `populate_module_if_necessary` call.
|
2013-12-19 20:53:59 -06:00
|
|
|
populated: Cell<bool>,
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-08-31 11:13:04 -05:00
|
|
|
impl Module {
|
2013-10-02 07:33:01 -05:00
|
|
|
fn new(parent_link: ParentLink,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
def_id: Option<DefId>,
|
|
|
|
kind: ModuleKind,
|
|
|
|
external: bool,
|
|
|
|
is_public: bool)
|
2013-12-19 20:52:35 -06:00
|
|
|
-> Module {
|
2013-08-31 11:13:04 -05:00
|
|
|
Module {
|
|
|
|
parent_link: parent_link,
|
2013-12-19 20:56:20 -06:00
|
|
|
def_id: Cell::new(def_id),
|
2013-12-19 20:52:35 -06:00
|
|
|
kind: Cell::new(kind),
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
is_public: is_public,
|
2013-12-21 17:32:44 -06:00
|
|
|
children: RefCell::new(HashMap::new()),
|
2014-03-04 12:02:49 -06:00
|
|
|
imports: RefCell::new(Vec::new()),
|
2013-12-21 16:05:26 -06:00
|
|
|
external_module_children: RefCell::new(HashMap::new()),
|
2014-02-28 16:34:26 -06:00
|
|
|
anonymous_children: RefCell::new(NodeMap::new()),
|
2013-12-21 17:15:54 -06:00
|
|
|
import_resolutions: RefCell::new(HashMap::new()),
|
2013-12-19 20:59:03 -06:00
|
|
|
glob_count: Cell::new(0),
|
2013-12-19 21:01:02 -06:00
|
|
|
resolved_import_count: Cell::new(0),
|
2013-12-19 20:53:59 -06:00
|
|
|
populated: Cell::new(!external),
|
2013-08-31 11:13:04 -05:00
|
|
|
}
|
2012-09-05 17:58:43 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn all_imports_resolved(&self) -> bool {
|
2014-03-20 21:49:20 -05:00
|
|
|
self.imports.borrow().len() == self.resolved_import_count.get()
|
2012-09-07 21:04:40 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
bitflags! {
|
|
|
|
#[deriving(Show)]
|
|
|
|
flags DefModifiers: u8 {
|
|
|
|
const PUBLIC = 0b0000_0001,
|
|
|
|
const IMPORTABLE = 0b0000_0010,
|
|
|
|
const ENUM_STAGING_HACK = 0b0000_0100,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-15 16:56:42 -05:00
|
|
|
// Records a possibly-private type definition.
|
2013-12-21 16:13:06 -06:00
|
|
|
#[deriving(Clone)]
|
2013-10-02 07:33:01 -05:00
|
|
|
struct TypeNsDef {
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: DefModifiers, // see note in ImportResolution about how to use this
|
2014-04-14 03:30:59 -05:00
|
|
|
module_def: Option<Rc<Module>>,
|
2013-09-01 20:45:37 -05:00
|
|
|
type_def: Option<Def>,
|
2013-08-31 11:13:04 -05:00
|
|
|
type_span: Option<Span>
|
2012-10-15 16:56:42 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Records a possibly-private value definition.
|
2014-10-15 01:25:34 -05:00
|
|
|
#[deriving(Clone, Show)]
|
2013-10-02 07:33:01 -05:00
|
|
|
struct ValueNsDef {
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: DefModifiers, // see note in ImportResolution about how to use this
|
2013-09-01 20:45:37 -05:00
|
|
|
def: Def,
|
2013-08-31 11:13:04 -05:00
|
|
|
value_span: Option<Span>,
|
2012-08-17 19:55:34 -05:00
|
|
|
}
|
|
|
|
|
2012-07-06 21:06:58 -05:00
|
|
|
// Records the definitions (at most one for each namespace) that a name is
|
|
|
|
// bound to.
|
2013-10-02 07:33:01 -05:00
|
|
|
struct NameBindings {
|
2013-12-21 16:13:06 -06:00
|
|
|
type_def: RefCell<Option<TypeNsDef>>, //< Meaning in type namespace.
|
2013-12-21 16:15:07 -06:00
|
|
|
value_def: RefCell<Option<ValueNsDef>>, //< Meaning in value namespace.
|
2012-09-07 21:04:40 -05:00
|
|
|
}
|
|
|
|
|
2013-07-03 16:16:08 -05:00
|
|
|
/// Ways in which a trait can be referenced
|
|
|
|
enum TraitReferenceType {
|
|
|
|
TraitImplementation, // impl SomeTrait for T { ... }
|
|
|
|
TraitDerivation, // trait T : SomeTrait { ... }
|
|
|
|
TraitBoundingTypeParameter, // fn f<T:SomeTrait>() { ... }
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl NameBindings {
|
2014-05-28 14:36:05 -05:00
|
|
|
fn new() -> NameBindings {
|
|
|
|
NameBindings {
|
|
|
|
type_def: RefCell::new(None),
|
|
|
|
value_def: RefCell::new(None),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Creates a new module in this set of name bindings.
|
2013-12-21 16:20:57 -06:00
|
|
|
fn define_module(&self,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
parent_link: ParentLink,
|
|
|
|
def_id: Option<DefId>,
|
|
|
|
kind: ModuleKind,
|
|
|
|
external: bool,
|
|
|
|
is_public: bool,
|
|
|
|
sp: Span) {
|
2012-10-15 20:04:15 -05:00
|
|
|
// Merges the module with the existing type def or creates a new one.
|
2014-10-19 01:46:08 -05:00
|
|
|
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
|
2014-04-14 03:30:59 -05:00
|
|
|
let module_ = Rc::new(Module::new(parent_link, def_id, kind, external,
|
|
|
|
is_public));
|
2014-03-28 12:29:55 -05:00
|
|
|
let type_def = self.type_def.borrow().clone();
|
|
|
|
match type_def {
|
2012-10-15 20:04:15 -05:00
|
|
|
None => {
|
2014-04-02 08:55:33 -05:00
|
|
|
*self.type_def.borrow_mut() = Some(TypeNsDef {
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: modifiers,
|
2012-10-15 20:04:15 -05:00
|
|
|
module_def: Some(module_),
|
2013-05-14 23:49:30 -05:00
|
|
|
type_def: None,
|
|
|
|
type_span: Some(sp)
|
2014-04-02 08:55:33 -05:00
|
|
|
});
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2013-05-29 18:59:33 -05:00
|
|
|
Some(type_def) => {
|
2014-04-02 08:55:33 -05:00
|
|
|
*self.type_def.borrow_mut() = Some(TypeNsDef {
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: modifiers,
|
2012-10-15 20:04:15 -05:00
|
|
|
module_def: Some(module_),
|
2013-05-14 23:49:30 -05:00
|
|
|
type_span: Some(sp),
|
2013-05-29 18:59:33 -05:00
|
|
|
type_def: type_def.type_def
|
2014-04-02 08:55:33 -05:00
|
|
|
});
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-13 18:13:20 -05:00
|
|
|
/// Sets the kind of the module, creating a new one if necessary.
|
2013-12-21 16:20:57 -06:00
|
|
|
fn set_module_kind(&self,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
parent_link: ParentLink,
|
|
|
|
def_id: Option<DefId>,
|
|
|
|
kind: ModuleKind,
|
|
|
|
external: bool,
|
|
|
|
is_public: bool,
|
|
|
|
_sp: Span) {
|
2014-10-19 01:46:08 -05:00
|
|
|
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
|
2014-03-28 12:29:55 -05:00
|
|
|
let type_def = self.type_def.borrow().clone();
|
|
|
|
match type_def {
|
2013-05-13 18:13:20 -05:00
|
|
|
None => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let module = Module::new(parent_link, def_id, kind,
|
|
|
|
external, is_public);
|
2014-04-02 08:55:33 -05:00
|
|
|
*self.type_def.borrow_mut() = Some(TypeNsDef {
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: modifiers,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_def: Some(Rc::new(module)),
|
2013-05-16 17:37:52 -05:00
|
|
|
type_def: None,
|
|
|
|
type_span: None,
|
2014-04-02 08:55:33 -05:00
|
|
|
});
|
2013-05-13 18:13:20 -05:00
|
|
|
}
|
|
|
|
Some(type_def) => {
|
|
|
|
match type_def.module_def {
|
|
|
|
None => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let module = Module::new(parent_link,
|
|
|
|
def_id,
|
|
|
|
kind,
|
|
|
|
external,
|
|
|
|
is_public);
|
2014-04-02 08:55:33 -05:00
|
|
|
*self.type_def.borrow_mut() = Some(TypeNsDef {
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: modifiers,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_def: Some(Rc::new(module)),
|
2013-05-16 17:37:52 -05:00
|
|
|
type_def: type_def.type_def,
|
|
|
|
type_span: None,
|
2014-04-02 08:55:33 -05:00
|
|
|
});
|
2013-05-13 18:13:20 -05:00
|
|
|
}
|
2013-12-19 20:52:35 -06:00
|
|
|
Some(module_def) => module_def.kind.set(kind),
|
2013-05-13 18:13:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Records a type definition.
|
2014-10-19 01:46:08 -05:00
|
|
|
fn define_type(&self, def: Def, sp: Span, modifiers: DefModifiers) {
|
|
|
|
debug!("defining type for def {} with modifiers {}", def, modifiers);
|
2012-10-15 20:04:15 -05:00
|
|
|
// Merges the type with the existing type def or creates a new one.
|
2014-03-28 12:29:55 -05:00
|
|
|
let type_def = self.type_def.borrow().clone();
|
|
|
|
match type_def {
|
2012-10-15 20:04:15 -05:00
|
|
|
None => {
|
2014-04-02 08:55:33 -05:00
|
|
|
*self.type_def.borrow_mut() = Some(TypeNsDef {
|
2012-10-15 20:04:15 -05:00
|
|
|
module_def: None,
|
2013-05-14 23:49:30 -05:00
|
|
|
type_def: Some(def),
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
type_span: Some(sp),
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: modifiers,
|
2014-04-02 08:55:33 -05:00
|
|
|
});
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2013-05-29 18:59:33 -05:00
|
|
|
Some(type_def) => {
|
2014-04-02 08:55:33 -05:00
|
|
|
*self.type_def.borrow_mut() = Some(TypeNsDef {
|
2012-10-15 20:04:15 -05:00
|
|
|
type_def: Some(def),
|
2013-05-14 23:49:30 -05:00
|
|
|
type_span: Some(sp),
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
module_def: type_def.module_def,
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: modifiers,
|
2014-04-02 08:55:33 -05:00
|
|
|
});
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Records a value definition.
|
2014-10-19 01:46:08 -05:00
|
|
|
fn define_value(&self, def: Def, sp: Span, modifiers: DefModifiers) {
|
|
|
|
debug!("defining value for def {} with modifiers {}", def, modifiers);
|
2014-04-02 08:55:33 -05:00
|
|
|
*self.value_def.borrow_mut() = Some(ValueNsDef {
|
2013-12-21 16:15:07 -06:00
|
|
|
def: def,
|
|
|
|
value_span: Some(sp),
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: modifiers,
|
2014-04-02 08:55:33 -05:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Returns the module node if applicable.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn get_module_if_available(&self) -> Option<Rc<Module>> {
|
2014-03-20 21:49:20 -05:00
|
|
|
match *self.type_def.borrow() {
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref type_def) => type_def.module_def.clone(),
|
2012-10-15 20:04:15 -05:00
|
|
|
None => None
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Returns the module node. Fails if this node does not have a module
|
|
|
|
* definition.
|
|
|
|
*/
|
2014-04-14 03:30:59 -05:00
|
|
|
fn get_module(&self) -> Rc<Module> {
|
2012-10-15 20:04:15 -05:00
|
|
|
match self.get_module_if_available() {
|
|
|
|
None => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("get_module called on a node with no module \
|
2013-01-31 19:51:01 -06:00
|
|
|
definition!")
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-10-15 20:04:15 -05:00
|
|
|
Some(module_def) => module_def
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn defined_in_namespace(&self, namespace: Namespace) -> bool {
|
2012-08-06 14:34:08 -05:00
|
|
|
match namespace {
|
2014-03-28 12:29:55 -05:00
|
|
|
TypeNS => return self.type_def.borrow().is_some(),
|
|
|
|
ValueNS => return self.value_def.borrow().is_some()
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn defined_in_public_namespace(&self, namespace: Namespace) -> bool {
|
2014-10-19 01:46:08 -05:00
|
|
|
self.defined_in_namespace_with(namespace, PUBLIC)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn defined_in_namespace_with(&self, namespace: Namespace, modifiers: DefModifiers) -> bool {
|
2013-02-25 23:34:45 -06:00
|
|
|
match namespace {
|
2014-03-28 12:29:55 -05:00
|
|
|
TypeNS => match *self.type_def.borrow() {
|
2014-10-19 01:46:08 -05:00
|
|
|
Some(ref def) => def.modifiers.contains(modifiers), None => false
|
2013-02-25 23:34:45 -06:00
|
|
|
},
|
2014-03-28 12:29:55 -05:00
|
|
|
ValueNS => match *self.value_def.borrow() {
|
2014-10-19 01:46:08 -05:00
|
|
|
Some(ref def) => def.modifiers.contains(modifiers), None => false
|
2013-02-25 23:34:45 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn def_for_namespace(&self, namespace: Namespace) -> Option<Def> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match namespace {
|
2012-10-15 16:56:42 -05:00
|
|
|
TypeNS => {
|
2014-03-28 12:29:55 -05:00
|
|
|
match *self.type_def.borrow() {
|
2012-10-15 16:56:42 -05:00
|
|
|
None => None,
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref type_def) => {
|
2013-12-21 16:13:06 -06:00
|
|
|
match type_def.type_def {
|
2012-10-15 20:04:15 -05:00
|
|
|
Some(type_def) => Some(type_def),
|
2013-06-18 11:39:16 -05:00
|
|
|
None => {
|
|
|
|
match type_def.module_def {
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref module) => {
|
2013-12-19 20:56:20 -06:00
|
|
|
match module.def_id.get() {
|
2013-09-01 20:45:37 -05:00
|
|
|
Some(did) => Some(DefMod(did)),
|
2013-06-18 11:39:16 -05:00
|
|
|
None => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => None,
|
|
|
|
}
|
|
|
|
}
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2012-08-17 19:55:34 -05:00
|
|
|
}
|
|
|
|
}
|
2012-10-15 16:56:42 -05:00
|
|
|
}
|
|
|
|
ValueNS => {
|
2014-03-28 12:29:55 -05:00
|
|
|
match *self.value_def.borrow() {
|
2012-10-15 16:56:42 -05:00
|
|
|
None => None,
|
|
|
|
Some(value_def) => Some(value_def.def)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn span_for_namespace(&self, namespace: Namespace) -> Option<Span> {
|
2012-10-15 16:56:42 -05:00
|
|
|
if self.defined_in_namespace(namespace) {
|
2012-08-06 18:10:56 -05:00
|
|
|
match namespace {
|
2013-05-14 23:49:30 -05:00
|
|
|
TypeNS => {
|
2014-03-28 12:29:55 -05:00
|
|
|
match *self.type_def.borrow() {
|
2013-05-14 23:49:30 -05:00
|
|
|
None => None,
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref type_def) => type_def.type_span
|
2013-05-14 23:49:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ValueNS => {
|
2014-03-28 12:29:55 -05:00
|
|
|
match *self.value_def.borrow() {
|
2013-05-14 23:49:30 -05:00
|
|
|
None => None,
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref value_def) => value_def.value_span
|
2013-05-14 23:49:30 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-06 18:10:56 -05:00
|
|
|
}
|
2012-10-15 16:56:42 -05:00
|
|
|
} else {
|
|
|
|
None
|
2012-08-06 18:10:56 -05:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Interns the names of the primitive types.
|
2013-10-02 07:33:01 -05:00
|
|
|
struct PrimitiveTypeTable {
|
2014-01-09 07:05:33 -06:00
|
|
|
primitive_types: HashMap<Name, PrimTy>,
|
2012-09-07 21:04:40 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl PrimitiveTypeTable {
|
2014-05-28 14:36:05 -05:00
|
|
|
fn new() -> PrimitiveTypeTable {
|
|
|
|
let mut table = PrimitiveTypeTable {
|
|
|
|
primitive_types: HashMap::new()
|
|
|
|
};
|
|
|
|
|
|
|
|
table.intern("bool", TyBool);
|
|
|
|
table.intern("char", TyChar);
|
|
|
|
table.intern("f32", TyFloat(TyF32));
|
|
|
|
table.intern("f64", TyFloat(TyF64));
|
|
|
|
table.intern("int", TyInt(TyI));
|
|
|
|
table.intern("i8", TyInt(TyI8));
|
|
|
|
table.intern("i16", TyInt(TyI16));
|
|
|
|
table.intern("i32", TyInt(TyI32));
|
|
|
|
table.intern("i64", TyInt(TyI64));
|
|
|
|
table.intern("str", TyStr);
|
|
|
|
table.intern("uint", TyUint(TyU));
|
|
|
|
table.intern("u8", TyUint(TyU8));
|
|
|
|
table.intern("u16", TyUint(TyU16));
|
|
|
|
table.intern("u32", TyUint(TyU32));
|
|
|
|
table.intern("u64", TyUint(TyU64));
|
|
|
|
|
|
|
|
table
|
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
fn intern(&mut self, string: &str, primitive_type: PrimTy) {
|
2013-06-26 17:56:13 -05:00
|
|
|
self.primitive_types.insert(token::intern(string), primitive_type);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-05 17:58:43 -05:00
|
|
|
|
2014-06-21 05:39:03 -05:00
|
|
|
fn namespace_error_to_string(ns: NamespaceError) -> &'static str {
|
2012-08-06 18:10:56 -05:00
|
|
|
match ns {
|
2014-07-04 19:59:55 -05:00
|
|
|
NoError => "",
|
|
|
|
ModuleError | TypeError => "type or module",
|
|
|
|
ValueError => "value",
|
2012-08-06 18:10:56 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The main resolver class.
|
2014-03-05 08:36:01 -06:00
|
|
|
struct Resolver<'a> {
|
|
|
|
session: &'a Session,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
graph_root: NameBindings,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
trait_item_map: FnvHashMap<(Name, DefId), TraitItemKind>,
|
2014-05-06 18:37:32 -05:00
|
|
|
|
2014-05-08 16:35:09 -05:00
|
|
|
structs: FnvHashMap<DefId, Vec<Name>>,
|
2012-07-11 17:00:40 -05:00
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// The number of imports that are currently unresolved.
|
2013-02-21 13:08:50 -06:00
|
|
|
unresolved_imports: uint,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// The module that represents the current item scope.
|
2014-04-14 03:30:59 -05:00
|
|
|
current_module: Rc<Module>,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// The current set of local scopes, for values.
|
2013-02-14 20:37:25 -06:00
|
|
|
// FIXME #4948: Reuse ribs to avoid allocation.
|
2014-09-29 18:06:13 -05:00
|
|
|
value_ribs: Vec<Rib>,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// The current set of local scopes, for types.
|
2014-09-29 18:06:13 -05:00
|
|
|
type_ribs: Vec<Rib>,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-08-14 21:20:56 -05:00
|
|
|
// The current set of local scopes, for labels.
|
2014-09-29 18:06:13 -05:00
|
|
|
label_ribs: Vec<Rib>,
|
2012-08-14 21:20:56 -05:00
|
|
|
|
2012-07-11 17:00:40 -05:00
|
|
|
// The trait that the current context can refer to.
|
2014-05-08 16:35:09 -05:00
|
|
|
current_trait_ref: Option<(DefId, TraitRef)>,
|
|
|
|
|
|
|
|
// The current self type if inside an impl (used for better errors).
|
|
|
|
current_self_type: Option<Ty>,
|
2012-07-11 17:00:40 -05:00
|
|
|
|
2012-09-19 20:52:49 -05:00
|
|
|
// The ident for the keyword "self".
|
2014-07-06 18:02:48 -05:00
|
|
|
self_name: Name,
|
2013-01-09 16:12:28 -06:00
|
|
|
// The ident for the non-keyword "Self".
|
2014-07-06 18:02:48 -05:00
|
|
|
type_self_name: Name,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-09-19 20:52:49 -05:00
|
|
|
// The idents for the primitive types.
|
2014-04-14 03:30:59 -05:00
|
|
|
primitive_type_table: PrimitiveTypeTable,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-03-22 21:26:41 -05:00
|
|
|
def_map: DefMap,
|
2014-09-17 21:45:21 -05:00
|
|
|
freevars: RefCell<FreevarMap>,
|
|
|
|
freevars_seen: RefCell<NodeMap<NodeSet>>,
|
2014-09-29 18:06:13 -05:00
|
|
|
capture_mode_map: CaptureModeMap,
|
2013-03-22 21:26:41 -05:00
|
|
|
export_map2: ExportMap2,
|
2012-09-06 21:40:15 -05:00
|
|
|
trait_map: TraitMap,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
external_exports: ExternalExports,
|
|
|
|
last_private: LastPrivateMap,
|
2013-04-30 00:15:17 -05:00
|
|
|
|
2013-08-13 19:54:14 -05:00
|
|
|
// Whether or not to print error messages. Can be set to true
|
|
|
|
// when getting additional info for error message suggestions,
|
|
|
|
// so as to avoid printing duplicate errors
|
|
|
|
emit_errors: bool,
|
|
|
|
|
2014-02-11 13:19:18 -06:00
|
|
|
used_imports: HashSet<(NodeId, Namespace)>,
|
2014-09-11 12:14:43 -05:00
|
|
|
used_crates: HashSet<CrateNum>,
|
2012-09-07 21:04:40 -05:00
|
|
|
}
|
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
struct BuildReducedGraphVisitor<'a, 'b:'a> {
|
2014-03-05 08:36:01 -06:00
|
|
|
resolver: &'a mut Resolver<'b>,
|
2014-09-12 05:10:30 -05:00
|
|
|
parent: ReducedGraphParent
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
|
|
|
|
2014-09-09 17:54:36 -05:00
|
|
|
impl<'a, 'b, 'v> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b> {
|
2013-08-13 11:52:41 -05:00
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_item(&mut self, item: &Item) {
|
|
|
|
let p = self.resolver.build_reduced_graph_for_item(item, self.parent.clone());
|
|
|
|
let old_parent = replace(&mut self.parent, p);
|
|
|
|
visit::walk_item(self, item);
|
|
|
|
self.parent = old_parent;
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
|
|
|
|
let parent = self.parent.clone();
|
2013-11-21 17:42:55 -06:00
|
|
|
self.resolver.build_reduced_graph_for_foreign_item(foreign_item,
|
2014-09-12 05:10:30 -05:00
|
|
|
parent.clone(),
|
2014-04-14 03:30:59 -05:00
|
|
|
|r| {
|
2014-09-12 05:10:30 -05:00
|
|
|
let mut v = BuildReducedGraphVisitor {
|
|
|
|
resolver: r,
|
|
|
|
parent: parent.clone()
|
|
|
|
};
|
|
|
|
visit::walk_foreign_item(&mut v, foreign_item);
|
2013-11-21 17:42:55 -06:00
|
|
|
})
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_view_item(&mut self, view_item: &ViewItem) {
|
|
|
|
self.resolver.build_reduced_graph_for_view_item(view_item, self.parent.clone());
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_block(&mut self, block: &Block) {
|
|
|
|
let np = self.resolver.build_reduced_graph_for_block(block, self.parent.clone());
|
|
|
|
let old_parent = replace(&mut self.parent, np);
|
|
|
|
visit::walk_block(self, block);
|
|
|
|
self.parent = old_parent;
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
struct UnusedImportCheckVisitor<'a, 'b:'a> {
|
|
|
|
resolver: &'a mut Resolver<'b>
|
|
|
|
}
|
2013-08-13 11:52:41 -05:00
|
|
|
|
2014-09-09 17:54:36 -05:00
|
|
|
impl<'a, 'b, 'v> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b> {
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_view_item(&mut self, vi: &ViewItem) {
|
2013-08-13 11:52:41 -05:00
|
|
|
self.resolver.check_for_item_unused_imports(vi);
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_view_item(self, vi);
|
2013-08-13 11:52:41 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-05 08:36:01 -06:00
|
|
|
impl<'a> Resolver<'a> {
|
2014-06-06 08:51:42 -05:00
|
|
|
fn new(session: &'a Session, crate_span: Span) -> Resolver<'a> {
|
2014-05-28 14:36:05 -05:00
|
|
|
let graph_root = NameBindings::new();
|
|
|
|
|
|
|
|
graph_root.define_module(NoParentLink,
|
|
|
|
Some(DefId { krate: 0, node: 0 }),
|
|
|
|
NormalModuleKind,
|
|
|
|
false,
|
|
|
|
true,
|
|
|
|
crate_span);
|
|
|
|
|
|
|
|
let current_module = graph_root.get_module();
|
|
|
|
|
|
|
|
Resolver {
|
|
|
|
session: session,
|
|
|
|
|
|
|
|
// The outermost module has def ID 0; this is not reflected in the
|
|
|
|
// AST.
|
|
|
|
|
|
|
|
graph_root: graph_root,
|
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
trait_item_map: FnvHashMap::new(),
|
2014-05-28 14:36:05 -05:00
|
|
|
structs: FnvHashMap::new(),
|
|
|
|
|
|
|
|
unresolved_imports: 0,
|
|
|
|
|
|
|
|
current_module: current_module,
|
2014-09-29 18:06:13 -05:00
|
|
|
value_ribs: Vec::new(),
|
|
|
|
type_ribs: Vec::new(),
|
|
|
|
label_ribs: Vec::new(),
|
2014-05-28 14:36:05 -05:00
|
|
|
|
|
|
|
current_trait_ref: None,
|
|
|
|
current_self_type: None,
|
|
|
|
|
2014-07-06 18:02:48 -05:00
|
|
|
self_name: special_names::self_,
|
|
|
|
type_self_name: special_names::type_self,
|
2014-05-28 14:36:05 -05:00
|
|
|
|
|
|
|
primitive_type_table: PrimitiveTypeTable::new(),
|
|
|
|
|
|
|
|
def_map: RefCell::new(NodeMap::new()),
|
2014-09-17 21:45:21 -05:00
|
|
|
freevars: RefCell::new(NodeMap::new()),
|
|
|
|
freevars_seen: RefCell::new(NodeMap::new()),
|
2014-09-29 18:06:13 -05:00
|
|
|
capture_mode_map: NodeMap::new(),
|
|
|
|
export_map2: NodeMap::new(),
|
2014-05-28 14:36:05 -05:00
|
|
|
trait_map: NodeMap::new(),
|
|
|
|
used_imports: HashSet::new(),
|
2014-09-11 12:14:43 -05:00
|
|
|
used_crates: HashSet::new(),
|
2014-05-28 14:36:05 -05:00
|
|
|
external_exports: DefIdSet::new(),
|
|
|
|
last_private: NodeMap::new(),
|
|
|
|
|
|
|
|
emit_errors: true,
|
|
|
|
}
|
|
|
|
}
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The main name resolution procedure.
|
2014-02-05 15:15:24 -06:00
|
|
|
fn resolve(&mut self, krate: &ast::Crate) {
|
|
|
|
self.build_reduced_graph(krate);
|
2012-07-06 21:06:58 -05:00
|
|
|
self.session.abort_if_errors();
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
self.resolve_imports();
|
2012-07-06 21:06:58 -05:00
|
|
|
self.session.abort_if_errors();
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
self.record_exports();
|
2012-07-06 21:06:58 -05:00
|
|
|
self.session.abort_if_errors();
|
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
self.resolve_crate(krate);
|
2012-07-06 21:06:58 -05:00
|
|
|
self.session.abort_if_errors();
|
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
self.check_for_unused_imports(krate);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Reduced graph building
|
|
|
|
//
|
|
|
|
// Here we build the "reduced graph": the graph of the module tree without
|
|
|
|
// any imports resolved.
|
|
|
|
//
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Constructs the reduced graph for the entire crate.
|
2014-02-05 15:15:24 -06:00
|
|
|
fn build_reduced_graph(&mut self, krate: &ast::Crate) {
|
2014-09-12 05:10:30 -05:00
|
|
|
let parent = ModuleReducedGraphParent(self.graph_root.get_module());
|
|
|
|
let mut visitor = BuildReducedGraphVisitor {
|
|
|
|
resolver: self,
|
|
|
|
parent: parent
|
|
|
|
};
|
|
|
|
visit::walk_crate(&mut visitor, krate);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Adds a new child item to the module definition of the parent node and
|
|
|
|
* returns its corresponding name bindings as well as the current parent.
|
|
|
|
* Or, if we're inside a block, creates (or reuses) an anonymous module
|
|
|
|
* corresponding to the innermost block ID and returns the name bindings
|
|
|
|
* as well as the newly-created parent.
|
|
|
|
*
|
|
|
|
* If this node does not have a module definition and we are not inside
|
|
|
|
* a block, fails.
|
|
|
|
*/
|
2014-04-22 11:06:43 -05:00
|
|
|
fn add_child(&self,
|
2014-09-30 19:11:34 -05:00
|
|
|
name: Name,
|
2014-04-22 11:06:43 -05:00
|
|
|
reduced_graph_parent: ReducedGraphParent,
|
|
|
|
duplicate_checking_mode: DuplicateCheckingMode,
|
|
|
|
// For printing errors
|
|
|
|
sp: Span)
|
2014-04-14 03:30:59 -05:00
|
|
|
-> Rc<NameBindings> {
|
2012-05-22 12:54:12 -05:00
|
|
|
// If this is the immediate descendant of a module, then we add the
|
|
|
|
// child name directly. Otherwise, we create or reuse an anonymous
|
|
|
|
// module and add the child to that.
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
let module_ = reduced_graph_parent.module();
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-08-12 22:31:30 -05:00
|
|
|
self.check_for_conflicts_between_external_crates_and_items(&*module_,
|
2014-09-30 19:11:34 -05:00
|
|
|
name,
|
2014-08-12 22:31:30 -05:00
|
|
|
sp);
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// Add or reuse the child.
|
2014-09-30 19:11:34 -05:00
|
|
|
let child = module_.children.borrow().find_copy(&name);
|
2014-04-14 03:30:59 -05:00
|
|
|
match child {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2014-05-28 14:36:05 -05:00
|
|
|
let child = Rc::new(NameBindings::new());
|
2014-09-30 19:11:34 -05:00
|
|
|
module_.children.borrow_mut().insert(name, child.clone());
|
2014-04-14 03:30:59 -05:00
|
|
|
child
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-12-21 17:32:44 -06:00
|
|
|
Some(child) => {
|
2013-03-26 21:53:33 -05:00
|
|
|
// Enforce the duplicate checking mode:
|
|
|
|
//
|
|
|
|
// * If we're requesting duplicate module checking, check that
|
|
|
|
// there isn't a module in the module with the same name.
|
|
|
|
//
|
|
|
|
// * If we're requesting duplicate type checking, check that
|
|
|
|
// there isn't a type in the module with the same name.
|
|
|
|
//
|
|
|
|
// * If we're requesting duplicate value checking, check that
|
|
|
|
// there isn't a value in the module with the same name.
|
|
|
|
//
|
|
|
|
// * If we're requesting duplicate type checking and duplicate
|
|
|
|
// value checking, check that there isn't a duplicate type
|
|
|
|
// and a duplicate value with the same name.
|
|
|
|
//
|
|
|
|
// * If no duplicate checking was requested at all, do
|
|
|
|
// nothing.
|
2012-10-15 20:04:15 -05:00
|
|
|
|
2013-06-23 11:48:43 -05:00
|
|
|
let mut duplicate_type = NoError;
|
2013-06-10 17:00:57 -05:00
|
|
|
let ns = match duplicate_checking_mode {
|
2012-10-15 20:04:15 -05:00
|
|
|
ForbidDuplicateModules => {
|
2014-01-19 02:21:14 -06:00
|
|
|
if child.get_module_if_available().is_some() {
|
2013-06-23 11:48:43 -05:00
|
|
|
duplicate_type = ModuleError;
|
|
|
|
}
|
2013-06-10 17:00:57 -05:00
|
|
|
Some(TypeNS)
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2014-07-04 19:59:55 -05:00
|
|
|
ForbidDuplicateTypesAndModules => {
|
2012-10-15 20:04:15 -05:00
|
|
|
match child.def_for_namespace(TypeNS) {
|
2014-07-04 19:59:55 -05:00
|
|
|
None => {}
|
|
|
|
Some(_) if child.get_module_if_available()
|
|
|
|
.map(|m| m.kind.get()) ==
|
|
|
|
Some(ImplModuleKind) => {}
|
2013-06-23 11:48:43 -05:00
|
|
|
Some(_) => duplicate_type = TypeError
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2013-06-10 17:00:57 -05:00
|
|
|
Some(TypeNS)
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
|
|
|
ForbidDuplicateValues => {
|
2013-06-23 11:48:43 -05:00
|
|
|
if child.defined_in_namespace(ValueNS) {
|
|
|
|
duplicate_type = ValueError;
|
|
|
|
}
|
2013-06-10 17:00:57 -05:00
|
|
|
Some(ValueNS)
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
|
|
|
ForbidDuplicateTypesAndValues => {
|
2013-06-10 17:00:57 -05:00
|
|
|
let mut n = None;
|
2012-10-15 20:04:15 -05:00
|
|
|
match child.def_for_namespace(TypeNS) {
|
2013-09-01 20:45:37 -05:00
|
|
|
Some(DefMod(_)) | None => {}
|
2013-06-10 17:00:57 -05:00
|
|
|
Some(_) => {
|
|
|
|
n = Some(TypeNS);
|
2013-06-23 11:48:43 -05:00
|
|
|
duplicate_type = TypeError;
|
2013-06-10 17:00:57 -05:00
|
|
|
}
|
2012-10-15 20:04:15 -05:00
|
|
|
};
|
|
|
|
if child.defined_in_namespace(ValueNS) {
|
2013-06-23 11:48:43 -05:00
|
|
|
duplicate_type = ValueError;
|
2013-06-10 17:00:57 -05:00
|
|
|
n = Some(ValueNS);
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2013-06-10 17:00:57 -05:00
|
|
|
n
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2013-06-10 17:00:57 -05:00
|
|
|
OverwriteDuplicates => None
|
|
|
|
};
|
2014-01-19 02:21:14 -06:00
|
|
|
if duplicate_type != NoError {
|
2012-10-15 20:04:15 -05:00
|
|
|
// Return an error here by looking up the namespace that
|
|
|
|
// had the duplicate.
|
2013-06-10 17:00:57 -05:00
|
|
|
let ns = ns.unwrap();
|
2013-08-13 19:54:14 -05:00
|
|
|
self.resolve_error(sp,
|
2013-09-28 00:38:08 -05:00
|
|
|
format!("duplicate definition of {} `{}`",
|
2014-06-21 05:39:03 -05:00
|
|
|
namespace_error_to_string(duplicate_type),
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name)).as_slice());
|
2013-06-10 16:50:12 -05:00
|
|
|
{
|
|
|
|
let r = child.span_for_namespace(ns);
|
2013-08-03 11:45:23 -05:00
|
|
|
for sp in r.iter() {
|
2013-06-10 16:50:12 -05:00
|
|
|
self.session.span_note(*sp,
|
2013-09-28 00:38:08 -05:00
|
|
|
format!("first definition of {} `{}` here",
|
2014-06-21 05:39:03 -05:00
|
|
|
namespace_error_to_string(duplicate_type),
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name)).as_slice());
|
2013-06-10 16:50:12 -05:00
|
|
|
}
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2012-08-06 18:10:56 -05:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
child
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
|
2012-05-22 12:54:12 -05:00
|
|
|
// If the block has view items, we need an anonymous module.
|
2013-07-16 13:08:35 -05:00
|
|
|
if block.view_items.len() > 0 {
|
2012-08-01 19:30:05 -05:00
|
|
|
return true;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check each statement.
|
2013-08-03 11:45:23 -05:00
|
|
|
for statement in block.stmts.iter() {
|
2012-08-06 14:34:08 -05:00
|
|
|
match statement.node {
|
2014-09-07 12:09:06 -05:00
|
|
|
StmtDecl(ref declaration, _) => {
|
2012-08-06 14:34:08 -05:00
|
|
|
match declaration.node {
|
2013-09-01 20:45:37 -05:00
|
|
|
DeclItem(_) => {
|
2012-08-01 19:30:05 -05:00
|
|
|
return true;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Keep searching.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Keep searching.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we found neither view items nor items, we don't need to create
|
|
|
|
// an anonymous module.
|
|
|
|
|
2012-08-01 19:30:05 -05:00
|
|
|
return false;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn get_parent_link(&mut self, parent: ReducedGraphParent, name: Name)
|
2013-05-31 17:17:22 -05:00
|
|
|
-> ParentLink {
|
2012-08-06 14:34:08 -05:00
|
|
|
match parent {
|
2012-08-03 21:59:04 -05:00
|
|
|
ModuleReducedGraphParent(module_) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
return ModuleParentLink(module_.downgrade(), name);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Constructs the reduced graph for one item.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn build_reduced_graph_for_item(&mut self,
|
2014-01-09 07:05:33 -06:00
|
|
|
item: &Item,
|
|
|
|
parent: ReducedGraphParent)
|
|
|
|
-> ReducedGraphParent
|
2013-09-26 21:10:16 -05:00
|
|
|
{
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = item.ident.name;
|
2012-08-06 18:10:56 -05:00
|
|
|
let sp = item.span;
|
2014-01-09 07:05:33 -06:00
|
|
|
let is_public = item.vis == ast::Public;
|
2014-10-19 01:46:08 -05:00
|
|
|
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-03-20 00:17:42 -05:00
|
|
|
match item.node {
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemMod(..) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name, parent.clone(), ForbidDuplicateModules, sp);
|
2012-08-06 18:10:56 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
let parent_link = self.get_parent_link(parent, name);
|
2014-02-05 15:15:24 -06:00
|
|
|
let def_id = DefId { krate: 0, node: item.id };
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
name_bindings.define_module(parent_link,
|
2013-02-04 16:02:01 -06:00
|
|
|
Some(def_id),
|
|
|
|
NormalModuleKind,
|
2013-08-21 20:39:30 -05:00
|
|
|
false,
|
2014-01-09 07:05:33 -06:00
|
|
|
item.vis == ast::Public,
|
2013-02-04 16:02:01 -06:00
|
|
|
sp);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-09-26 21:10:16 -05:00
|
|
|
ModuleReducedGraphParent(name_bindings.get_module())
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-10-15 20:04:15 -05:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemForeignMod(..) => parent,
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// These items live in the value namespace.
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemStatic(_, m, _) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name, parent.clone(), ForbidDuplicateValues, sp);
|
2013-09-01 20:45:37 -05:00
|
|
|
let mutbl = m == ast::MutMutable;
|
2012-08-06 18:10:56 -05:00
|
|
|
|
2013-02-04 16:02:01 -06:00
|
|
|
name_bindings.define_value
|
2014-10-19 01:46:08 -05:00
|
|
|
(DefStatic(local_def(item.id), mutbl), sp, modifiers);
|
2013-09-26 21:10:16 -05:00
|
|
|
parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 10:17:01 -05:00
|
|
|
ItemConst(_, _) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name, parent.clone(), ForbidDuplicateValues, sp)
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 10:17:01 -05:00
|
|
|
.define_value(DefConst(local_def(item.id)),
|
2014-10-19 01:46:08 -05:00
|
|
|
sp, modifiers);
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 10:17:01 -05:00
|
|
|
parent
|
|
|
|
}
|
2014-10-15 23:44:24 -05:00
|
|
|
ItemFn(_, _, _, _, _) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name, parent.clone(), ForbidDuplicateValues, sp);
|
2012-08-06 18:10:56 -05:00
|
|
|
|
2014-10-15 23:44:24 -05:00
|
|
|
let def = DefFn(local_def(item.id), false);
|
2014-10-19 01:46:08 -05:00
|
|
|
name_bindings.define_value(def, sp, modifiers);
|
2014-04-14 03:30:59 -05:00
|
|
|
parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// These items live in the type namespace.
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemTy(..) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name,
|
2014-07-04 19:59:55 -05:00
|
|
|
parent.clone(),
|
|
|
|
ForbidDuplicateTypesAndModules,
|
|
|
|
sp);
|
2012-08-06 18:10:56 -05:00
|
|
|
|
2013-02-04 16:02:01 -06:00
|
|
|
name_bindings.define_type
|
2014-10-19 01:46:08 -05:00
|
|
|
(DefTy(local_def(item.id), false), sp, modifiers);
|
2013-09-26 21:10:16 -05:00
|
|
|
parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemEnum(ref enum_definition, _) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name,
|
2014-07-04 19:59:55 -05:00
|
|
|
parent.clone(),
|
|
|
|
ForbidDuplicateTypesAndModules,
|
|
|
|
sp);
|
2012-08-06 18:10:56 -05:00
|
|
|
|
2013-02-04 16:02:01 -06:00
|
|
|
name_bindings.define_type
|
2014-10-19 01:46:08 -05:00
|
|
|
(DefTy(local_def(item.id), true), sp, modifiers);
|
|
|
|
|
|
|
|
let parent_link = self.get_parent_link(parent.clone(), name);
|
|
|
|
// We want to make sure the module type is EnumModuleKind
|
|
|
|
// even if there's already an ImplModuleKind module defined,
|
|
|
|
// since that's how we prevent duplicate enum definitions
|
|
|
|
name_bindings.set_module_kind(parent_link,
|
|
|
|
Some(local_def(item.id)),
|
|
|
|
EnumModuleKind,
|
|
|
|
false,
|
|
|
|
is_public,
|
|
|
|
sp);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-05-16 12:15:33 -05:00
|
|
|
for variant in (*enum_definition).variants.iter() {
|
2014-10-19 01:46:08 -05:00
|
|
|
self.build_reduced_graph_for_variant(
|
|
|
|
&**variant,
|
|
|
|
local_def(item.id),
|
|
|
|
ModuleReducedGraphParent(name_bindings.get_module()),
|
|
|
|
modifiers);
|
|
|
|
|
|
|
|
// Temporary staging hack
|
2013-06-11 21:55:16 -05:00
|
|
|
self.build_reduced_graph_for_variant(
|
2014-05-16 12:15:33 -05:00
|
|
|
&**variant,
|
2012-11-29 14:08:40 -06:00
|
|
|
local_def(item.id),
|
2014-04-14 03:30:59 -05:00
|
|
|
parent.clone(),
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers | ENUM_STAGING_HACK);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-09-26 21:10:16 -05:00
|
|
|
parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-13 17:17:35 -05:00
|
|
|
|
|
|
|
// These items live in both the type and value namespaces.
|
2014-09-07 12:09:06 -05:00
|
|
|
ItemStruct(ref struct_def, _) => {
|
2013-06-10 16:29:48 -05:00
|
|
|
// Adding to both Type and Value namespaces or just Type?
|
|
|
|
let (forbid, ctor_id) = match struct_def.ctor_id {
|
|
|
|
Some(ctor_id) => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
|
2014-07-04 19:59:55 -05:00
|
|
|
None => (ForbidDuplicateTypesAndModules, None)
|
2013-06-10 16:29:48 -05:00
|
|
|
};
|
2012-08-08 13:52:23 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
let name_bindings = self.add_child(name, parent.clone(), forbid, sp);
|
2013-06-10 16:29:48 -05:00
|
|
|
|
|
|
|
// Define a name in the type namespace.
|
2014-10-19 01:46:08 -05:00
|
|
|
name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
|
2013-06-10 16:29:48 -05:00
|
|
|
|
|
|
|
// If this is a newtype or unit-like struct, define a name
|
|
|
|
// in the value namespace as well
|
2014-10-15 01:05:01 -05:00
|
|
|
match ctor_id {
|
|
|
|
Some(cid) => {
|
|
|
|
name_bindings.define_value(DefStruct(local_def(cid)),
|
2014-10-19 01:46:08 -05:00
|
|
|
sp, modifiers);
|
2014-10-15 01:05:01 -05:00
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-05-08 16:35:09 -05:00
|
|
|
// Record the def ID and fields of this struct.
|
|
|
|
let named_fields = struct_def.fields.iter().filter_map(|f| {
|
|
|
|
match f.node.kind {
|
|
|
|
NamedField(ident, _) => Some(ident.name),
|
|
|
|
UnnamedField(_) => None
|
|
|
|
}
|
|
|
|
}).collect();
|
|
|
|
self.structs.insert(local_def(item.id), named_fields);
|
2012-07-23 20:44:59 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-09-07 12:09:06 -05:00
|
|
|
ItemImpl(_, None, ref ty, ref impl_items) => {
|
2013-06-14 20:21:47 -05:00
|
|
|
// If this implements an anonymous trait, then add all the
|
|
|
|
// methods within to a new module, if the type was defined
|
|
|
|
// within this module.
|
2012-10-15 20:04:15 -05:00
|
|
|
|
2013-06-14 20:21:47 -05:00
|
|
|
// Create the module and add all methods.
|
2013-11-30 16:00:39 -06:00
|
|
|
match ty.node {
|
2014-01-09 07:05:33 -06:00
|
|
|
TyPath(ref path, _, _) if path.segments.len() == 1 => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let mod_name = path.segments.last().unwrap().identifier.name;
|
2012-10-15 20:04:15 -05:00
|
|
|
|
2014-03-20 21:49:20 -05:00
|
|
|
let parent_opt = parent.module().children.borrow()
|
2014-09-30 19:11:34 -05:00
|
|
|
.find_copy(&mod_name);
|
2014-03-20 21:49:20 -05:00
|
|
|
let new_parent = match parent_opt {
|
2013-06-09 06:35:24 -05:00
|
|
|
// It already exists
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref child) if child.get_module_if_available()
|
2013-12-21 17:32:44 -06:00
|
|
|
.is_some() &&
|
|
|
|
child.get_module().kind.get() ==
|
2013-06-14 20:21:47 -05:00
|
|
|
ImplModuleKind => {
|
2013-06-09 06:35:24 -05:00
|
|
|
ModuleReducedGraphParent(child.get_module())
|
|
|
|
}
|
2014-10-19 01:46:08 -05:00
|
|
|
Some(ref child) if child.get_module_if_available()
|
|
|
|
.is_some() &&
|
|
|
|
child.get_module().kind.get() ==
|
|
|
|
EnumModuleKind => {
|
|
|
|
ModuleReducedGraphParent(child.get_module())
|
|
|
|
}
|
2013-06-09 06:35:24 -05:00
|
|
|
// Create the module
|
|
|
|
_ => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(mod_name,
|
2014-04-14 03:30:59 -05:00
|
|
|
parent.clone(),
|
2013-06-09 06:35:24 -05:00
|
|
|
ForbidDuplicateModules,
|
|
|
|
sp);
|
|
|
|
|
2013-06-14 20:21:47 -05:00
|
|
|
let parent_link =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.get_parent_link(parent.clone(), name);
|
2013-06-09 06:35:24 -05:00
|
|
|
let def_id = local_def(item.id);
|
2013-12-17 01:32:37 -06:00
|
|
|
let ns = TypeNS;
|
|
|
|
let is_public =
|
|
|
|
!name_bindings.defined_in_namespace(ns) ||
|
|
|
|
name_bindings.defined_in_public_namespace(ns);
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
name_bindings.define_module(parent_link,
|
2013-06-09 06:35:24 -05:00
|
|
|
Some(def_id),
|
|
|
|
ImplModuleKind,
|
2013-08-21 20:39:30 -05:00
|
|
|
false,
|
2013-12-17 01:32:37 -06:00
|
|
|
is_public,
|
2013-06-09 06:35:24 -05:00
|
|
|
sp);
|
|
|
|
|
2013-06-14 20:21:47 -05:00
|
|
|
ModuleReducedGraphParent(
|
|
|
|
name_bindings.get_module())
|
2013-06-09 06:35:24 -05:00
|
|
|
}
|
|
|
|
};
|
2012-10-15 20:04:15 -05:00
|
|
|
|
2014-08-04 15:56:56 -05:00
|
|
|
// For each implementation item...
|
|
|
|
for impl_item in impl_items.iter() {
|
|
|
|
match *impl_item {
|
2014-09-07 12:09:06 -05:00
|
|
|
MethodImplItem(ref method) => {
|
2014-08-04 15:56:56 -05:00
|
|
|
// Add the method to the module.
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = method.pe_ident().name;
|
2014-08-04 15:56:56 -05:00
|
|
|
let method_name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name,
|
2014-08-04 15:56:56 -05:00
|
|
|
new_parent.clone(),
|
|
|
|
ForbidDuplicateValues,
|
|
|
|
method.span);
|
|
|
|
let def = match method.pe_explicit_self()
|
|
|
|
.node {
|
|
|
|
SelfStatic => {
|
|
|
|
// Static methods become
|
2014-10-14 19:33:20 -05:00
|
|
|
// `DefStaticMethod`s.
|
|
|
|
DefStaticMethod(local_def(method.id),
|
2014-10-15 23:44:24 -05:00
|
|
|
FromImpl(local_def(item.id)))
|
2014-08-04 15:56:56 -05:00
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
// Non-static methods become
|
2014-10-14 19:33:20 -05:00
|
|
|
// `DefMethod`s.
|
2014-08-04 15:56:56 -05:00
|
|
|
DefMethod(local_def(method.id),
|
2014-10-14 19:33:20 -05:00
|
|
|
None,
|
|
|
|
FromImpl(local_def(item.id)))
|
2014-08-04 15:56:56 -05:00
|
|
|
}
|
|
|
|
};
|
2013-06-14 20:21:47 -05:00
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
// NB: not IMPORTABLE
|
|
|
|
let modifiers = if method.pe_vis() == ast::Public {
|
|
|
|
PUBLIC
|
|
|
|
} else {
|
|
|
|
DefModifiers::empty()
|
|
|
|
};
|
2014-08-04 15:56:56 -05:00
|
|
|
method_name_bindings.define_value(
|
|
|
|
def,
|
|
|
|
method.span,
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers);
|
2014-08-04 15:56:56 -05:00
|
|
|
}
|
2014-08-05 21:44:21 -05:00
|
|
|
TypeImplItem(ref typedef) => {
|
|
|
|
// Add the typedef to the module.
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = typedef.ident.name;
|
2014-08-05 21:44:21 -05:00
|
|
|
let typedef_name_bindings =
|
|
|
|
self.add_child(
|
2014-09-30 19:11:34 -05:00
|
|
|
name,
|
2014-08-05 21:44:21 -05:00
|
|
|
new_parent.clone(),
|
|
|
|
ForbidDuplicateTypesAndModules,
|
|
|
|
typedef.span);
|
|
|
|
let def = DefAssociatedTy(local_def(
|
|
|
|
typedef.id));
|
2014-10-19 01:46:08 -05:00
|
|
|
// NB: not IMPORTABLE
|
|
|
|
let modifiers = if typedef.vis == ast::Public {
|
|
|
|
PUBLIC
|
|
|
|
} else {
|
|
|
|
DefModifiers::empty()
|
|
|
|
};
|
2014-08-05 21:44:21 -05:00
|
|
|
typedef_name_bindings.define_type(
|
|
|
|
def,
|
|
|
|
typedef.span,
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers);
|
2014-08-05 21:44:21 -05:00
|
|
|
}
|
2014-08-04 15:56:56 -05:00
|
|
|
}
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
|
|
|
}
|
2014-09-11 00:26:41 -05:00
|
|
|
_ => {
|
|
|
|
self.resolve_error(ty.span,
|
|
|
|
"inherent implementations may \
|
|
|
|
only be implemented in the same \
|
|
|
|
module as the type they are \
|
|
|
|
implemented for")
|
|
|
|
}
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
|
|
|
|
2013-09-26 21:10:16 -05:00
|
|
|
parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemImpl(_, Some(_), _, _) => parent,
|
2013-06-14 20:21:47 -05:00
|
|
|
|
2014-04-02 19:38:45 -05:00
|
|
|
ItemTrait(_, _, _, ref methods) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name,
|
2014-07-04 19:59:55 -05:00
|
|
|
parent.clone(),
|
|
|
|
ForbidDuplicateTypesAndModules,
|
|
|
|
sp);
|
2012-08-06 18:10:56 -05:00
|
|
|
|
2013-06-14 20:21:47 -05:00
|
|
|
// Add all the methods within to a new module.
|
2014-09-30 19:11:34 -05:00
|
|
|
let parent_link = self.get_parent_link(parent.clone(), name);
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
name_bindings.define_module(parent_link,
|
2013-06-14 20:21:47 -05:00
|
|
|
Some(local_def(item.id)),
|
|
|
|
TraitModuleKind,
|
2013-08-21 20:39:30 -05:00
|
|
|
false,
|
2014-01-09 07:05:33 -06:00
|
|
|
item.vis == ast::Public,
|
2013-06-14 20:21:47 -05:00
|
|
|
sp);
|
|
|
|
let module_parent = ModuleReducedGraphParent(name_bindings.
|
|
|
|
get_module());
|
2012-11-12 14:15:08 -06:00
|
|
|
|
2014-04-22 11:06:43 -05:00
|
|
|
let def_id = local_def(item.id);
|
|
|
|
|
2012-07-11 17:00:40 -05:00
|
|
|
// Add the names of all the methods to the trait info.
|
2013-08-03 11:45:23 -05:00
|
|
|
for method in methods.iter() {
|
2014-09-30 19:11:34 -05:00
|
|
|
let (name, kind) = match *method {
|
2014-08-05 21:44:21 -05:00
|
|
|
ast::RequiredMethod(_) |
|
|
|
|
ast::ProvidedMethod(_) => {
|
|
|
|
let ty_m =
|
|
|
|
ast_util::trait_item_to_ty_method(method);
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = ty_m.ident.name;
|
2014-08-05 21:44:21 -05:00
|
|
|
|
|
|
|
// Add it as a name in the trait module.
|
|
|
|
let (def, static_flag) = match ty_m.explicit_self
|
|
|
|
.node {
|
|
|
|
SelfStatic => {
|
2014-10-14 19:33:20 -05:00
|
|
|
// Static methods become `DefStaticMethod`s.
|
2014-08-05 21:44:21 -05:00
|
|
|
(DefStaticMethod(
|
|
|
|
local_def(ty_m.id),
|
2014-10-15 23:44:24 -05:00
|
|
|
FromTrait(local_def(item.id))),
|
2014-08-05 21:44:21 -05:00
|
|
|
StaticMethodTraitItemKind)
|
|
|
|
}
|
|
|
|
_ => {
|
2014-10-14 19:33:20 -05:00
|
|
|
// Non-static methods become `DefMethod`s.
|
2014-08-05 21:44:21 -05:00
|
|
|
(DefMethod(local_def(ty_m.id),
|
2014-10-14 19:33:20 -05:00
|
|
|
Some(local_def(item.id)),
|
|
|
|
FromTrait(local_def(item.id))),
|
2014-08-05 21:44:21 -05:00
|
|
|
NonstaticMethodTraitItemKind)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let method_name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name,
|
2014-08-05 21:44:21 -05:00
|
|
|
module_parent.clone(),
|
|
|
|
ForbidDuplicateTypesAndValues,
|
|
|
|
ty_m.span);
|
2014-10-19 01:46:08 -05:00
|
|
|
// NB: not IMPORTABLE
|
2014-08-05 21:44:21 -05:00
|
|
|
method_name_bindings.define_value(def,
|
|
|
|
ty_m.span,
|
2014-10-19 01:46:08 -05:00
|
|
|
PUBLIC);
|
2012-11-12 14:15:08 -06:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
(name, static_flag)
|
2012-11-12 14:15:08 -06:00
|
|
|
}
|
2014-08-05 21:44:21 -05:00
|
|
|
ast::TypeTraitItem(ref associated_type) => {
|
|
|
|
let def = DefAssociatedTy(local_def(
|
|
|
|
associated_type.id));
|
|
|
|
|
|
|
|
let name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(associated_type.ident.name,
|
2014-08-05 21:44:21 -05:00
|
|
|
module_parent.clone(),
|
|
|
|
ForbidDuplicateTypesAndValues,
|
|
|
|
associated_type.span);
|
2014-10-19 01:46:08 -05:00
|
|
|
// NB: not IMPORTABLE
|
2014-08-05 21:44:21 -05:00
|
|
|
name_bindings.define_type(def,
|
|
|
|
associated_type.span,
|
2014-10-19 01:46:08 -05:00
|
|
|
PUBLIC);
|
2014-08-05 21:44:21 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
(associated_type.ident.name, TypeTraitItemKind)
|
2013-06-14 20:21:47 -05:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
self.trait_item_map.insert((name, def_id), kind);
|
2013-05-20 11:41:20 -05:00
|
|
|
}
|
2012-07-11 17:00:40 -05:00
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
name_bindings.define_type(DefTrait(def_id), sp, modifiers);
|
2014-04-14 03:30:59 -05:00
|
|
|
parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-12-25 12:10:33 -06:00
|
|
|
ItemMac(..) => parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-07 21:12:58 -05:00
|
|
|
// Constructs the reduced graph for one variant. Variants exist in the
|
2014-09-11 00:07:49 -05:00
|
|
|
// type and value namespaces.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn build_reduced_graph_for_variant(&mut self,
|
2014-01-09 07:05:33 -06:00
|
|
|
variant: &Variant,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
item_id: DefId,
|
|
|
|
parent: ReducedGraphParent,
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: DefModifiers) {
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = variant.node.name.name;
|
2014-09-11 00:07:49 -05:00
|
|
|
let is_exported = match variant.node.kind {
|
|
|
|
TupleVariantKind(_) => false,
|
2014-01-09 07:05:33 -06:00
|
|
|
StructVariantKind(_) => {
|
2014-05-08 16:35:09 -05:00
|
|
|
// Not adding fields for variants as they are not accessed with a self receiver
|
|
|
|
self.structs.insert(local_def(variant.node.id), Vec::new());
|
2014-09-11 00:07:49 -05:00
|
|
|
true
|
2012-08-07 21:12:58 -05:00
|
|
|
}
|
2014-09-11 00:07:49 -05:00
|
|
|
};
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
let child = self.add_child(name, parent,
|
2014-09-11 00:07:49 -05:00
|
|
|
ForbidDuplicateTypesAndValues,
|
|
|
|
variant.span);
|
|
|
|
child.define_value(DefVariant(item_id,
|
|
|
|
local_def(variant.node.id), is_exported),
|
2014-10-19 01:46:08 -05:00
|
|
|
variant.span, modifiers);
|
2014-09-11 00:07:49 -05:00
|
|
|
child.define_type(DefVariant(item_id,
|
|
|
|
local_def(variant.node.id), is_exported),
|
2014-10-19 01:46:08 -05:00
|
|
|
variant.span, modifiers);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-05-16 17:37:52 -05:00
|
|
|
/// Constructs the reduced graph for one 'view item'. View items consist
|
|
|
|
/// of imports and use directives.
|
2014-01-09 07:05:33 -06:00
|
|
|
fn build_reduced_graph_for_view_item(&mut self, view_item: &ViewItem,
|
|
|
|
parent: ReducedGraphParent) {
|
2013-03-20 00:17:42 -05:00
|
|
|
match view_item.node {
|
2014-04-26 08:33:45 -05:00
|
|
|
ViewItemUse(ref view_path) => {
|
|
|
|
// Extract and intern the module part of the path. For
|
|
|
|
// globs and lists, the path is found directly in the AST;
|
|
|
|
// for simple paths we have to munge the path a little.
|
2014-07-17 17:56:56 -05:00
|
|
|
let module_path = match view_path.node {
|
2014-04-26 08:33:45 -05:00
|
|
|
ViewPathSimple(_, ref full_path, _) => {
|
2014-07-17 17:56:56 -05:00
|
|
|
full_path.segments
|
|
|
|
.as_slice().init()
|
2014-09-30 19:11:34 -05:00
|
|
|
.iter().map(|ident| ident.identifier.name)
|
2014-07-17 17:56:56 -05:00
|
|
|
.collect()
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-04-26 08:33:45 -05:00
|
|
|
ViewPathGlob(ref module_ident_path, _) |
|
|
|
|
ViewPathList(ref module_ident_path, _, _) => {
|
2014-07-17 17:56:56 -05:00
|
|
|
module_ident_path.segments
|
2014-09-30 19:11:34 -05:00
|
|
|
.iter().map(|ident| ident.identifier.name).collect()
|
2014-04-26 08:33:45 -05:00
|
|
|
}
|
2014-07-17 17:56:56 -05:00
|
|
|
};
|
2014-04-26 08:33:45 -05:00
|
|
|
|
|
|
|
// Build up the import directives.
|
|
|
|
let module_ = parent.module();
|
|
|
|
let is_public = view_item.vis == ast::Public;
|
2014-08-12 22:31:30 -05:00
|
|
|
let shadowable =
|
|
|
|
view_item.attrs
|
|
|
|
.iter()
|
|
|
|
.any(|attr| {
|
2014-09-30 19:11:34 -05:00
|
|
|
attr.name() == token::get_name(
|
|
|
|
special_idents::prelude_import.name)
|
2014-08-12 22:31:30 -05:00
|
|
|
});
|
|
|
|
|
2014-04-26 08:33:45 -05:00
|
|
|
match view_path.node {
|
|
|
|
ViewPathSimple(binding, ref full_path, id) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let source_name =
|
|
|
|
full_path.segments.last().unwrap().identifier.name;
|
|
|
|
if token::get_name(source_name).get() == "mod" {
|
2014-07-17 17:56:56 -05:00
|
|
|
self.resolve_error(view_path.span,
|
|
|
|
"`mod` imports are only allowed within a { } list");
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
let subclass = SingleImport(binding.name,
|
|
|
|
source_name);
|
2014-04-26 08:33:45 -05:00
|
|
|
self.build_import_directive(&*module_,
|
|
|
|
module_path,
|
|
|
|
subclass,
|
|
|
|
view_path.span,
|
|
|
|
id,
|
2014-08-12 22:31:30 -05:00
|
|
|
is_public,
|
|
|
|
shadowable);
|
2014-04-26 08:33:45 -05:00
|
|
|
}
|
2014-07-17 17:56:56 -05:00
|
|
|
ViewPathList(_, ref source_items, _) => {
|
|
|
|
// Make sure there's at most one `mod` import in the list.
|
|
|
|
let mod_spans = source_items.iter().filter_map(|item| match item.node {
|
|
|
|
PathListMod { .. } => Some(item.span),
|
|
|
|
_ => None
|
|
|
|
}).collect::<Vec<Span>>();
|
2014-09-06 17:23:55 -05:00
|
|
|
if mod_spans.len() > 1 {
|
|
|
|
self.resolve_error(mod_spans[0],
|
|
|
|
"`mod` import can only appear once in the list");
|
|
|
|
for other_span in mod_spans.iter().skip(1) {
|
|
|
|
self.session.span_note(*other_span,
|
|
|
|
"another `mod` import appears here");
|
|
|
|
}
|
2014-07-17 17:56:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for source_item in source_items.iter() {
|
|
|
|
let (module_path, name) = match source_item.node {
|
|
|
|
PathListIdent { name, .. } =>
|
2014-09-30 19:11:34 -05:00
|
|
|
(module_path.clone(), name.name),
|
2014-07-17 17:56:56 -05:00
|
|
|
PathListMod { .. } => {
|
|
|
|
let name = match module_path.last() {
|
2014-09-30 19:11:34 -05:00
|
|
|
Some(name) => *name,
|
2014-07-17 17:56:56 -05:00
|
|
|
None => {
|
|
|
|
self.resolve_error(source_item.span,
|
|
|
|
"`mod` import can only appear in an import list \
|
|
|
|
with a non-empty prefix");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let module_path = module_path.as_slice().init();
|
2014-10-15 01:05:01 -05:00
|
|
|
(module_path.to_vec(), name)
|
2014-07-17 17:56:56 -05:00
|
|
|
}
|
|
|
|
};
|
2014-04-26 08:33:45 -05:00
|
|
|
self.build_import_directive(
|
|
|
|
&*module_,
|
2014-07-17 17:56:56 -05:00
|
|
|
module_path,
|
2014-04-26 08:33:45 -05:00
|
|
|
SingleImport(name, name),
|
2014-07-17 17:56:56 -05:00
|
|
|
source_item.span,
|
2014-08-12 22:31:30 -05:00
|
|
|
source_item.node.id(),
|
|
|
|
is_public,
|
|
|
|
shadowable);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2014-04-26 08:33:45 -05:00
|
|
|
ViewPathGlob(_, id) => {
|
|
|
|
self.build_import_directive(&*module_,
|
|
|
|
module_path,
|
|
|
|
GlobImport,
|
|
|
|
view_path.span,
|
|
|
|
id,
|
2014-08-12 22:31:30 -05:00
|
|
|
is_public,
|
|
|
|
shadowable);
|
2014-04-26 08:33:45 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-07 01:57:45 -06:00
|
|
|
ViewItemExternCrate(name, _, node_id) => {
|
2013-07-31 15:47:32 -05:00
|
|
|
// n.b. we don't need to look at the path option here, because cstore already did
|
2014-06-05 16:37:52 -05:00
|
|
|
for &crate_id in self.session.cstore
|
|
|
|
.find_extern_mod_stmt_cnum(node_id).iter() {
|
2014-06-04 17:55:10 -05:00
|
|
|
let def_id = DefId { krate: crate_id, node: 0 };
|
|
|
|
self.external_exports.insert(def_id);
|
2014-06-05 16:37:52 -05:00
|
|
|
let parent_link =
|
2014-09-30 19:11:34 -05:00
|
|
|
ModuleParentLink(parent.module().downgrade(), name.name);
|
2014-06-04 17:55:10 -05:00
|
|
|
let external_module = Rc::new(Module::new(parent_link,
|
|
|
|
Some(def_id),
|
|
|
|
NormalModuleKind,
|
|
|
|
false,
|
|
|
|
true));
|
|
|
|
debug!("(build reduced graph for item) found extern `{}`",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*external_module));
|
2014-08-12 22:31:30 -05:00
|
|
|
self.check_for_conflicts_between_external_crates(
|
|
|
|
&*parent.module(),
|
|
|
|
name.name,
|
|
|
|
view_item.span);
|
2014-06-04 17:55:10 -05:00
|
|
|
parent.module().external_module_children.borrow_mut()
|
2014-06-05 16:37:52 -05:00
|
|
|
.insert(name.name, external_module.clone());
|
2014-06-04 17:55:10 -05:00
|
|
|
self.build_reduced_graph_for_external_crate(external_module);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Constructs the reduced graph for one foreign item.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn build_reduced_graph_for_foreign_item(&mut self,
|
2014-01-09 07:05:33 -06:00
|
|
|
foreign_item: &ForeignItem,
|
2013-11-19 15:22:03 -06:00
|
|
|
parent: ReducedGraphParent,
|
2014-04-14 03:30:59 -05:00
|
|
|
f: |&mut Resolver|) {
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = foreign_item.ident.name;
|
2014-01-09 07:05:33 -06:00
|
|
|
let is_public = foreign_item.vis == ast::Public;
|
2014-10-19 01:46:08 -05:00
|
|
|
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
|
2014-04-14 03:30:59 -05:00
|
|
|
let name_bindings =
|
2012-10-15 20:04:15 -05:00
|
|
|
self.add_child(name, parent, ForbidDuplicateValues,
|
|
|
|
foreign_item.span);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-02-14 23:50:03 -06:00
|
|
|
match foreign_item.node {
|
2014-01-09 07:05:33 -06:00
|
|
|
ForeignItemFn(_, ref generics) => {
|
2014-10-15 23:44:24 -05:00
|
|
|
let def = DefFn(local_def(foreign_item.id), false);
|
2014-10-19 01:46:08 -05:00
|
|
|
name_bindings.define_value(def, foreign_item.span, modifiers);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-11-21 17:42:55 -06:00
|
|
|
self.with_type_parameter_rib(
|
|
|
|
HasTypeParameters(generics,
|
2014-05-31 17:53:13 -05:00
|
|
|
FnSpace,
|
2013-11-21 17:42:55 -06:00
|
|
|
foreign_item.id,
|
|
|
|
NormalRibKind),
|
2014-04-14 03:30:59 -05:00
|
|
|
f);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
ForeignItemStatic(_, m) => {
|
2013-09-01 20:45:37 -05:00
|
|
|
let def = DefStatic(local_def(foreign_item.id), m);
|
2014-10-19 01:46:08 -05:00
|
|
|
name_bindings.define_value(def, foreign_item.span, modifiers);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
f(self)
|
2012-08-25 17:09:33 -05:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn build_reduced_graph_for_block(&mut self,
|
2013-07-19 00:38:55 -05:00
|
|
|
block: &Block,
|
2013-09-26 21:10:16 -05:00
|
|
|
parent: ReducedGraphParent)
|
|
|
|
-> ReducedGraphParent
|
|
|
|
{
|
2012-05-22 12:54:12 -05:00
|
|
|
if self.block_needs_anonymous_module(block) {
|
2013-07-16 13:08:35 -05:00
|
|
|
let block_id = block.id;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for block) creating a new \
|
2013-09-28 00:38:08 -05:00
|
|
|
anonymous module for block {}",
|
2012-08-22 19:24:52 -05:00
|
|
|
block_id);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
let parent_module = parent.module();
|
|
|
|
let new_module = Rc::new(Module::new(
|
|
|
|
BlockParentLink(parent_module.downgrade(), block_id),
|
2013-02-21 13:08:50 -06:00
|
|
|
None,
|
2013-08-21 20:39:30 -05:00
|
|
|
AnonymousModuleKind,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
false,
|
2014-04-14 03:30:59 -05:00
|
|
|
false));
|
2014-03-20 21:49:20 -05:00
|
|
|
parent_module.anonymous_children.borrow_mut()
|
2014-04-14 03:30:59 -05:00
|
|
|
.insert(block_id, new_module.clone());
|
2014-03-20 21:49:20 -05:00
|
|
|
ModuleReducedGraphParent(new_module)
|
2012-05-22 12:54:12 -05:00
|
|
|
} else {
|
2013-09-26 21:10:16 -05:00
|
|
|
parent
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-26 21:10:16 -05:00
|
|
|
fn handle_external_def(&mut self,
|
2013-09-01 20:45:37 -05:00
|
|
|
def: Def,
|
2014-01-09 07:05:33 -06:00
|
|
|
vis: Visibility,
|
2014-04-14 03:30:59 -05:00
|
|
|
child_name_bindings: &NameBindings,
|
2013-08-21 19:26:33 -05:00
|
|
|
final_ident: &str,
|
2014-09-30 19:11:34 -05:00
|
|
|
name: Name,
|
2013-08-21 19:26:33 -05:00
|
|
|
new_parent: ReducedGraphParent) {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for \
|
2014-10-15 01:25:34 -05:00
|
|
|
external crate) building external def, priv {}",
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
vis);
|
2014-01-09 07:05:33 -06:00
|
|
|
let is_public = vis == ast::Public;
|
2014-10-19 01:46:08 -05:00
|
|
|
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
|
2013-10-07 15:01:47 -05:00
|
|
|
let is_exported = is_public && match new_parent {
|
2014-04-14 03:30:59 -05:00
|
|
|
ModuleReducedGraphParent(ref module) => {
|
2013-12-19 20:56:20 -06:00
|
|
|
match module.def_id.get() {
|
2013-10-07 15:01:47 -05:00
|
|
|
None => true,
|
|
|
|
Some(did) => self.external_exports.contains(&did)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if is_exported {
|
2014-05-14 14:31:30 -05:00
|
|
|
self.external_exports.insert(def.def_id());
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
}
|
2014-07-16 23:50:54 -05:00
|
|
|
|
|
|
|
let kind = match def {
|
2014-10-19 01:46:08 -05:00
|
|
|
DefTy(_, true) => EnumModuleKind,
|
2014-07-16 23:50:54 -05:00
|
|
|
DefStruct(..) | DefTy(..) => ImplModuleKind,
|
|
|
|
_ => NormalModuleKind
|
|
|
|
};
|
|
|
|
|
2012-08-02 18:01:38 -05:00
|
|
|
match def {
|
2013-09-01 20:45:37 -05:00
|
|
|
DefMod(def_id) | DefForeignMod(def_id) | DefStruct(def_id) |
|
2014-09-15 16:13:00 -05:00
|
|
|
DefTy(def_id, _) => {
|
2014-03-28 12:29:55 -05:00
|
|
|
let type_def = child_name_bindings.type_def.borrow().clone();
|
|
|
|
match type_def {
|
2013-11-28 14:22:53 -06:00
|
|
|
Some(TypeNsDef { module_def: Some(module_def), .. }) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for external crate) \
|
2012-10-15 20:04:15 -05:00
|
|
|
already created module");
|
2013-12-19 20:56:20 -06:00
|
|
|
module_def.def_id.set(Some(def_id));
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
|
|
|
Some(_) | None => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for \
|
2012-08-02 18:01:38 -05:00
|
|
|
external crate) building module \
|
2013-09-28 00:38:08 -05:00
|
|
|
{}", final_ident);
|
2014-09-30 19:11:34 -05:00
|
|
|
let parent_link = self.get_parent_link(new_parent.clone(), name);
|
2012-08-02 18:01:38 -05:00
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
child_name_bindings.define_module(parent_link,
|
2013-08-21 19:26:33 -05:00
|
|
|
Some(def_id),
|
2014-07-16 23:50:54 -05:00
|
|
|
kind,
|
2013-08-21 20:39:30 -05:00
|
|
|
true,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
is_public,
|
2014-01-01 00:53:22 -06:00
|
|
|
DUMMY_SP);
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-23 20:31:43 -05:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
match def {
|
2013-09-01 20:45:37 -05:00
|
|
|
DefMod(_) | DefForeignMod(_) => {}
|
2014-10-19 01:46:08 -05:00
|
|
|
// Still here for staging
|
2014-05-06 18:45:21 -05:00
|
|
|
DefVariant(enum_did, variant_id, is_struct) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for external crate) building \
|
2013-09-28 00:38:08 -05:00
|
|
|
variant {}",
|
2013-05-16 17:37:52 -05:00
|
|
|
final_ident);
|
2014-05-06 18:45:21 -05:00
|
|
|
// If this variant is public, then it was publicly reexported,
|
|
|
|
// otherwise we need to inherit the visibility of the enum
|
|
|
|
// definition.
|
|
|
|
let is_exported = is_public ||
|
|
|
|
self.external_exports.contains(&enum_did);
|
2014-10-19 01:46:08 -05:00
|
|
|
let modifiers = IMPORTABLE | ENUM_STAGING_HACK | if is_exported {
|
|
|
|
PUBLIC
|
|
|
|
} else {
|
|
|
|
DefModifiers::empty()
|
|
|
|
};
|
2013-09-08 19:36:01 -05:00
|
|
|
if is_struct {
|
2014-10-19 01:46:08 -05:00
|
|
|
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
2014-05-08 16:35:09 -05:00
|
|
|
// Not adding fields for variants as they are not accessed with a self receiver
|
|
|
|
self.structs.insert(variant_id, Vec::new());
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
} else {
|
2014-10-19 01:46:08 -05:00
|
|
|
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
|
2013-09-08 19:36:01 -05:00
|
|
|
}
|
2013-05-16 17:37:52 -05:00
|
|
|
}
|
2014-10-15 23:44:24 -05:00
|
|
|
DefFn(ctor_id, true) => {
|
2014-10-01 16:28:54 -05:00
|
|
|
child_name_bindings.define_value(
|
|
|
|
csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
|
2014-10-19 01:46:08 -05:00
|
|
|
.map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
|
2014-10-01 16:28:54 -05:00
|
|
|
}
|
2014-10-15 23:40:01 -05:00
|
|
|
DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for external \
|
2013-09-28 00:38:08 -05:00
|
|
|
crate) building value (fn/static) {}", final_ident);
|
2014-10-19 01:46:08 -05:00
|
|
|
// impl methods have already been defined with the correct importability modifier
|
|
|
|
let mut modifiers = match *child_name_bindings.value_def.borrow() {
|
|
|
|
Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
|
|
|
|
None => modifiers
|
|
|
|
};
|
|
|
|
if new_parent.module().kind.get() != NormalModuleKind {
|
|
|
|
modifiers = modifiers & !IMPORTABLE;
|
|
|
|
}
|
|
|
|
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
2013-09-01 20:45:37 -05:00
|
|
|
DefTrait(def_id) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for external \
|
2013-09-28 00:38:08 -05:00
|
|
|
crate) building type {}", final_ident);
|
2013-03-27 09:26:57 -05:00
|
|
|
|
2014-08-04 15:56:56 -05:00
|
|
|
// If this is a trait, add all the trait item names to the trait
|
|
|
|
// info.
|
2013-03-27 09:26:57 -05:00
|
|
|
|
2014-08-04 15:56:56 -05:00
|
|
|
let trait_item_def_ids =
|
|
|
|
csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
|
|
|
|
for trait_item_def_id in trait_item_def_ids.iter() {
|
|
|
|
let (trait_item_name, trait_item_kind) =
|
|
|
|
csearch::get_trait_item_name_and_kind(
|
|
|
|
&self.session.cstore,
|
|
|
|
trait_item_def_id.def_id());
|
2013-03-27 09:26:57 -05:00
|
|
|
|
2014-08-04 15:56:56 -05:00
|
|
|
debug!("(building reduced graph for external crate) ... \
|
|
|
|
adding trait item '{}'",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(trait_item_name));
|
2013-03-27 09:26:57 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
|
2014-04-22 06:20:08 -05:00
|
|
|
|
2013-10-07 15:01:47 -05:00
|
|
|
if is_exported {
|
2014-08-04 15:56:56 -05:00
|
|
|
self.external_exports
|
|
|
|
.insert(trait_item_def_id.def_id());
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
}
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
2013-05-13 18:13:20 -05:00
|
|
|
|
|
|
|
// Define a module if necessary.
|
2014-09-30 19:11:34 -05:00
|
|
|
let parent_link = self.get_parent_link(new_parent, name);
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
child_name_bindings.set_module_kind(parent_link,
|
2013-05-13 18:13:20 -05:00
|
|
|
Some(def_id),
|
|
|
|
TraitModuleKind,
|
2013-08-21 20:39:30 -05:00
|
|
|
true,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
is_public,
|
2014-01-01 00:53:22 -06:00
|
|
|
DUMMY_SP)
|
2013-03-27 09:26:57 -05:00
|
|
|
}
|
2014-10-19 01:46:08 -05:00
|
|
|
DefTy(def_id, true) => { // enums
|
|
|
|
debug!("(building reduced graph for external crate) building enum {}", final_ident);
|
|
|
|
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
|
|
|
let enum_module = ModuleReducedGraphParent(child_name_bindings.get_module());
|
|
|
|
|
|
|
|
let variants = csearch::get_enum_variant_defs(&self.session.cstore, def_id);
|
|
|
|
for &(v_def, name, vis) in variants.iter() {
|
|
|
|
let (variant_id, is_struct) = match v_def {
|
|
|
|
DefVariant(_, variant_id, is_struct) => (variant_id, is_struct),
|
|
|
|
_ => unreachable!()
|
|
|
|
};
|
|
|
|
let child = self.add_child(name, enum_module.clone(),
|
|
|
|
OverwriteDuplicates,
|
|
|
|
DUMMY_SP);
|
|
|
|
|
|
|
|
// If this variant is public, then it was publicly reexported,
|
|
|
|
// otherwise we need to inherit the visibility of the enum
|
|
|
|
// definition.
|
|
|
|
let variant_exported = vis == ast::Public || is_exported;
|
|
|
|
let modifiers = IMPORTABLE | if variant_exported {
|
|
|
|
PUBLIC
|
|
|
|
} else {
|
|
|
|
DefModifiers::empty()
|
|
|
|
};
|
|
|
|
if is_struct {
|
|
|
|
child.define_type(v_def, DUMMY_SP, modifiers);
|
|
|
|
// Not adding fields for variants as they are not accessed with a self
|
|
|
|
// receiver
|
|
|
|
self.structs.insert(variant_id, Vec::new());
|
|
|
|
} else {
|
|
|
|
child.define_value(v_def, DUMMY_SP, modifiers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-05 21:44:21 -05:00
|
|
|
DefTy(..) | DefAssociatedTy(..) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for external \
|
2013-09-28 00:38:08 -05:00
|
|
|
crate) building type {}", final_ident);
|
2013-03-27 09:26:57 -05:00
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
2013-09-01 20:45:37 -05:00
|
|
|
DefStruct(def_id) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for external \
|
2013-09-28 00:38:08 -05:00
|
|
|
crate) building type and value for {}",
|
2012-10-08 13:49:01 -05:00
|
|
|
final_ident);
|
2014-10-19 01:46:08 -05:00
|
|
|
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
|
2014-05-08 16:35:09 -05:00
|
|
|
let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| {
|
|
|
|
f.name
|
|
|
|
}).collect::<Vec<_>>();
|
|
|
|
|
|
|
|
if fields.len() == 0 {
|
2014-10-19 01:46:08 -05:00
|
|
|
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
|
2013-08-07 13:52:33 -05:00
|
|
|
}
|
2014-05-08 16:35:09 -05:00
|
|
|
|
|
|
|
// Record the def ID and fields of this struct.
|
|
|
|
self.structs.insert(def_id, fields);
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
2014-09-17 09:28:19 -05:00
|
|
|
DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
|
2013-11-28 14:22:53 -06:00
|
|
|
DefUse(..) | DefUpvar(..) | DefRegion(..) |
|
|
|
|
DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("didn't expect `{}`", def);
|
2012-08-02 18:01:38 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-21 19:26:33 -05:00
|
|
|
/// Builds the reduced graph for a single item in an external crate.
|
2013-09-26 21:10:16 -05:00
|
|
|
fn build_reduced_graph_for_external_crate_def(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
root: Rc<Module>,
|
2013-08-31 11:13:04 -05:00
|
|
|
def_like: DefLike,
|
2014-09-30 19:11:34 -05:00
|
|
|
name: Name,
|
2014-01-09 07:05:33 -06:00
|
|
|
visibility: Visibility) {
|
2013-08-21 19:26:33 -05:00
|
|
|
match def_like {
|
2013-08-31 11:13:04 -05:00
|
|
|
DlDef(def) => {
|
2013-08-21 19:26:33 -05:00
|
|
|
// Add the new child item, if necessary.
|
2013-08-21 20:39:30 -05:00
|
|
|
match def {
|
2013-09-01 20:45:37 -05:00
|
|
|
DefForeignMod(def_id) => {
|
2013-08-21 20:39:30 -05:00
|
|
|
// Foreign modules have no names. Recur and populate
|
|
|
|
// eagerly.
|
2014-03-09 08:20:44 -05:00
|
|
|
csearch::each_child_of_item(&self.session.cstore,
|
2013-11-21 17:42:55 -06:00
|
|
|
def_id,
|
|
|
|
|def_like,
|
2014-09-30 19:11:34 -05:00
|
|
|
child_name,
|
2013-11-21 17:42:55 -06:00
|
|
|
vis| {
|
2013-08-21 20:39:30 -05:00
|
|
|
self.build_reduced_graph_for_external_crate_def(
|
2014-04-14 03:30:59 -05:00
|
|
|
root.clone(),
|
2013-08-21 20:39:30 -05:00
|
|
|
def_like,
|
2014-09-30 19:11:34 -05:00
|
|
|
child_name,
|
2013-08-07 02:11:34 -05:00
|
|
|
vis)
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2013-08-21 20:39:30 -05:00
|
|
|
}
|
2013-08-21 19:26:33 -05:00
|
|
|
_ => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let child_name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name,
|
2014-04-14 03:30:59 -05:00
|
|
|
ModuleReducedGraphParent(root.clone()),
|
2013-08-21 19:26:33 -05:00
|
|
|
OverwriteDuplicates,
|
2014-01-01 00:53:22 -06:00
|
|
|
DUMMY_SP);
|
2013-08-21 19:26:33 -05:00
|
|
|
|
|
|
|
self.handle_external_def(def,
|
2013-08-07 02:11:34 -05:00
|
|
|
visibility,
|
2014-04-14 03:30:59 -05:00
|
|
|
&*child_name_bindings,
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name).get(),
|
|
|
|
name,
|
2014-04-14 03:30:59 -05:00
|
|
|
ModuleReducedGraphParent(root));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-31 11:13:04 -05:00
|
|
|
DlImpl(def) => {
|
2014-03-09 08:20:44 -05:00
|
|
|
match csearch::get_type_name_if_impl(&self.session.cstore, def) {
|
2013-08-21 19:26:33 -05:00
|
|
|
None => {}
|
2014-09-30 19:11:34 -05:00
|
|
|
Some(final_name) => {
|
2014-10-19 20:30:31 -05:00
|
|
|
let methods_opt =
|
|
|
|
csearch::get_methods_if_impl(&self.session.cstore, def);
|
|
|
|
match methods_opt {
|
|
|
|
Some(ref methods) if
|
|
|
|
methods.len() >= 1 => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for \
|
2013-08-21 19:26:33 -05:00
|
|
|
external crate) processing \
|
2013-09-28 00:38:08 -05:00
|
|
|
static methods for type name {}",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(final_name));
|
2013-08-21 19:26:33 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
let child_name_bindings =
|
2013-08-21 19:26:33 -05:00
|
|
|
self.add_child(
|
2014-09-30 19:11:34 -05:00
|
|
|
final_name,
|
2014-04-14 03:30:59 -05:00
|
|
|
ModuleReducedGraphParent(root.clone()),
|
2013-08-21 19:26:33 -05:00
|
|
|
OverwriteDuplicates,
|
2014-01-01 00:53:22 -06:00
|
|
|
DUMMY_SP);
|
2013-08-21 19:26:33 -05:00
|
|
|
|
|
|
|
// Process the static methods. First,
|
|
|
|
// create the module.
|
|
|
|
let type_module;
|
2014-03-28 12:29:55 -05:00
|
|
|
let type_def = child_name_bindings.type_def.borrow().clone();
|
|
|
|
match type_def {
|
2013-08-21 19:26:33 -05:00
|
|
|
Some(TypeNsDef {
|
|
|
|
module_def: Some(module_def),
|
2013-11-28 14:22:53 -06:00
|
|
|
..
|
2013-08-21 19:26:33 -05:00
|
|
|
}) => {
|
|
|
|
// We already have a module. This
|
|
|
|
// is OK.
|
|
|
|
type_module = module_def;
|
|
|
|
|
|
|
|
// Mark it as an impl module if
|
|
|
|
// necessary.
|
2013-12-19 20:52:35 -06:00
|
|
|
type_module.kind.set(ImplModuleKind);
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
2013-08-21 19:26:33 -05:00
|
|
|
Some(_) | None => {
|
|
|
|
let parent_link =
|
2014-04-14 03:30:59 -05:00
|
|
|
self.get_parent_link(ModuleReducedGraphParent(root),
|
2014-09-30 19:11:34 -05:00
|
|
|
final_name);
|
2013-08-21 19:26:33 -05:00
|
|
|
child_name_bindings.define_module(
|
|
|
|
parent_link,
|
|
|
|
Some(def),
|
|
|
|
ImplModuleKind,
|
2013-08-21 20:39:30 -05:00
|
|
|
true,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
true,
|
2014-01-01 00:53:22 -06:00
|
|
|
DUMMY_SP);
|
2013-08-21 19:26:33 -05:00
|
|
|
type_module =
|
|
|
|
child_name_bindings.
|
|
|
|
get_module();
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-21 19:26:33 -05:00
|
|
|
// Add each static method to the module.
|
|
|
|
let new_parent =
|
|
|
|
ModuleReducedGraphParent(type_module);
|
2014-10-19 20:30:31 -05:00
|
|
|
for method_info in methods.iter() {
|
|
|
|
let name = method_info.name;
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for \
|
2013-08-21 19:26:33 -05:00
|
|
|
external crate) creating \
|
2013-09-28 00:38:08 -05:00
|
|
|
static method '{}'",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name));
|
2013-08-21 19:26:33 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
let method_name_bindings =
|
2014-09-30 19:11:34 -05:00
|
|
|
self.add_child(name,
|
2014-04-14 03:30:59 -05:00
|
|
|
new_parent.clone(),
|
2013-08-21 19:26:33 -05:00
|
|
|
OverwriteDuplicates,
|
2014-01-01 00:53:22 -06:00
|
|
|
DUMMY_SP);
|
2014-10-19 20:30:31 -05:00
|
|
|
let def = DefFn(method_info.def_id, false);
|
2013-08-07 02:11:34 -05:00
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
// NB: not IMPORTABLE
|
|
|
|
let modifiers = if visibility == ast::Public {
|
|
|
|
PUBLIC
|
|
|
|
} else {
|
|
|
|
DefModifiers::empty()
|
|
|
|
};
|
2013-08-21 19:26:33 -05:00
|
|
|
method_name_bindings.define_value(
|
2014-10-19 01:46:08 -05:00
|
|
|
def, DUMMY_SP, modifiers);
|
2013-08-21 19:26:33 -05:00
|
|
|
}
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
2013-08-21 19:26:33 -05:00
|
|
|
|
|
|
|
// Otherwise, do nothing.
|
|
|
|
Some(_) | None => {}
|
2012-10-18 15:29:34 -05:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2013-08-31 11:13:04 -05:00
|
|
|
DlField => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building reduced graph for external crate) \
|
2013-08-21 19:26:33 -05:00
|
|
|
ignoring field");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-21 20:39:30 -05:00
|
|
|
/// Builds the reduced graph rooted at the given external module.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn populate_external_module(&mut self, module: Rc<Module>) {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(populating external module) attempting to populate {}",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module));
|
2013-08-23 20:31:43 -05:00
|
|
|
|
2013-12-19 20:56:20 -06:00
|
|
|
let def_id = match module.def_id.get() {
|
2013-08-23 20:31:43 -05:00
|
|
|
None => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(populating external module) ... no def ID!");
|
2013-08-23 20:31:43 -05:00
|
|
|
return
|
|
|
|
}
|
2013-08-21 20:39:30 -05:00
|
|
|
Some(def_id) => def_id,
|
|
|
|
};
|
|
|
|
|
2014-03-09 08:20:44 -05:00
|
|
|
csearch::each_child_of_item(&self.session.cstore,
|
2013-11-21 17:42:55 -06:00
|
|
|
def_id,
|
2014-09-30 19:11:34 -05:00
|
|
|
|def_like, child_name, visibility| {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(populating external module) ... found ident: {}",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(child_name));
|
2014-04-14 03:30:59 -05:00
|
|
|
self.build_reduced_graph_for_external_crate_def(module.clone(),
|
2013-08-21 20:39:30 -05:00
|
|
|
def_like,
|
2014-09-30 19:11:34 -05:00
|
|
|
child_name,
|
2013-08-07 02:11:34 -05:00
|
|
|
visibility)
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2013-12-19 20:53:59 -06:00
|
|
|
module.populated.set(true)
|
2013-08-21 20:39:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Ensures that the reduced graph rooted at the given external module
|
|
|
|
/// is built, building it if it is not.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
|
2013-12-19 20:53:59 -06:00
|
|
|
if !module.populated.get() {
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_external_module(module.clone())
|
2013-08-21 20:39:30 -05:00
|
|
|
}
|
2013-12-19 20:53:59 -06:00
|
|
|
assert!(module.populated.get())
|
2013-08-21 20:39:30 -05:00
|
|
|
}
|
|
|
|
|
2013-08-21 19:26:33 -05:00
|
|
|
/// Builds the reduced graph rooted at the 'use' directive for an external
|
|
|
|
/// crate.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn build_reduced_graph_for_external_crate(&mut self, root: Rc<Module>) {
|
2014-03-09 08:20:44 -05:00
|
|
|
csearch::each_top_level_item_of_crate(&self.session.cstore,
|
2013-12-19 20:56:20 -06:00
|
|
|
root.def_id
|
|
|
|
.get()
|
|
|
|
.unwrap()
|
2014-02-05 15:15:24 -06:00
|
|
|
.krate,
|
2014-09-30 19:11:34 -05:00
|
|
|
|def_like, name, visibility| {
|
2014-04-14 03:30:59 -05:00
|
|
|
self.build_reduced_graph_for_external_crate_def(root.clone(),
|
2013-08-21 19:26:33 -05:00
|
|
|
def_like,
|
2014-09-30 19:11:34 -05:00
|
|
|
name,
|
2013-08-07 02:11:34 -05:00
|
|
|
visibility)
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Creates and adds an import directive to the given module.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn build_import_directive(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: &Module,
|
2014-09-30 19:11:34 -05:00
|
|
|
module_path: Vec<Name>,
|
2014-04-14 03:30:59 -05:00
|
|
|
subclass: ImportDirectiveSubclass,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
span: Span,
|
|
|
|
id: NodeId,
|
2014-08-12 22:31:30 -05:00
|
|
|
is_public: bool,
|
|
|
|
shadowable: bool) {
|
2014-04-14 03:30:59 -05:00
|
|
|
module_.imports.borrow_mut().push(ImportDirective::new(module_path,
|
|
|
|
subclass,
|
2014-08-12 22:31:30 -05:00
|
|
|
span,
|
|
|
|
id,
|
|
|
|
is_public,
|
|
|
|
shadowable));
|
2014-04-14 03:30:59 -05:00
|
|
|
self.unresolved_imports += 1;
|
2012-05-22 12:54:12 -05:00
|
|
|
// Bump the reference count on the name. Or, if this is a glob, set
|
|
|
|
// the appropriate flag.
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
match subclass {
|
2013-03-26 21:53:33 -05:00
|
|
|
SingleImport(target, _) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building import directive) building import \
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
directive: {}::{}",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.names_to_string(module_.imports.borrow().last().unwrap()
|
2014-04-14 03:30:59 -05:00
|
|
|
.module_path.as_slice()),
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(target));
|
2012-10-02 20:13:56 -05:00
|
|
|
|
2013-12-21 17:15:54 -06:00
|
|
|
let mut import_resolutions = module_.import_resolutions
|
|
|
|
.borrow_mut();
|
2014-09-30 19:11:34 -05:00
|
|
|
match import_resolutions.find_mut(&target) {
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(resolution) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(building import directive) bumping \
|
2012-10-02 20:13:56 -05:00
|
|
|
reference");
|
2014-04-14 03:30:59 -05:00
|
|
|
resolution.outstanding_references += 1;
|
2013-05-20 13:02:08 -05:00
|
|
|
|
|
|
|
// the source of this name is different now
|
2014-04-14 03:30:59 -05:00
|
|
|
resolution.type_id = id;
|
|
|
|
resolution.value_id = id;
|
|
|
|
resolution.is_public = is_public;
|
|
|
|
return;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
None => {}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
debug!("(building import directive) creating new");
|
|
|
|
let mut resolution = ImportResolution::new(id, is_public);
|
|
|
|
resolution.outstanding_references = 1;
|
2014-09-30 19:11:34 -05:00
|
|
|
import_resolutions.insert(target, resolution);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
GlobImport => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Set the glob flag. This tells us that we don't know the
|
|
|
|
// module's exports ahead of time.
|
|
|
|
|
2013-12-19 20:59:03 -06:00
|
|
|
module_.glob_count.set(module_.glob_count.get() + 1);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Import resolution
|
|
|
|
//
|
|
|
|
// This is a fixed-point algorithm. We resolve imports until our efforts
|
|
|
|
// are stymied by an unresolved import; then we bail out of the current
|
|
|
|
// module and continue. We terminate successfully once no more imports
|
|
|
|
// remain or unsuccessfully when no forward progress in resolving imports
|
|
|
|
// is made.
|
|
|
|
|
2013-05-13 18:13:20 -05:00
|
|
|
/// Resolves all imports for the crate. This method performs the fixed-
|
|
|
|
/// point iteration.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_imports(&mut self) {
|
2014-04-21 16:58:52 -05:00
|
|
|
let mut i = 0u;
|
2012-11-29 14:08:40 -06:00
|
|
|
let mut prev_unresolved_imports = 0;
|
2012-05-22 12:54:12 -05:00
|
|
|
loop {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving imports) iteration {}, {} imports left",
|
2012-08-22 19:24:52 -05:00
|
|
|
i, self.unresolved_imports);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-02-04 16:02:01 -06:00
|
|
|
let module_root = self.graph_root.get_module();
|
2014-04-14 03:30:59 -05:00
|
|
|
self.resolve_imports_for_module_subtree(module_root.clone());
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-11-29 14:08:40 -06:00
|
|
|
if self.unresolved_imports == 0 {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving imports) success");
|
2012-05-22 12:54:12 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if self.unresolved_imports == prev_unresolved_imports {
|
|
|
|
self.report_unresolved_imports(module_root);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-11-29 14:08:40 -06:00
|
|
|
i += 1;
|
2012-05-22 12:54:12 -05:00
|
|
|
prev_unresolved_imports = self.unresolved_imports;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
/// Attempts to resolve imports for the given module and all of its
|
|
|
|
/// submodules.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving imports for module subtree) resolving {}",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module_));
|
2014-06-04 17:55:10 -05:00
|
|
|
let orig_module = replace(&mut self.current_module, module_.clone());
|
2014-04-14 03:30:59 -05:00
|
|
|
self.resolve_imports_for_module(module_.clone());
|
2014-06-04 17:55:10 -05:00
|
|
|
self.current_module = orig_module;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&module_);
|
|
|
|
for (_, child_node) in module_.children.borrow().iter() {
|
2014-03-20 21:49:20 -05:00
|
|
|
match child_node.get_module_if_available() {
|
|
|
|
None => {
|
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
Some(child_module) => {
|
|
|
|
self.resolve_imports_for_module_subtree(child_module);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
for (_, child_module) in module_.anonymous_children.borrow().iter() {
|
|
|
|
self.resolve_imports_for_module_subtree(child_module.clone());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Attempts to resolve imports for the given module only.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn resolve_imports_for_module(&mut self, module: Rc<Module>) {
|
2013-03-01 12:44:43 -06:00
|
|
|
if module.all_imports_resolved() {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving imports for module) all imports resolved for \
|
2013-09-28 00:38:08 -05:00
|
|
|
{}",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module));
|
2012-08-01 19:30:05 -05:00
|
|
|
return;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-05-20 23:00:56 -05:00
|
|
|
let imports = module.imports.borrow();
|
2014-03-20 21:49:20 -05:00
|
|
|
let import_count = imports.len();
|
2013-12-19 21:01:02 -06:00
|
|
|
while module.resolved_import_count.get() < import_count {
|
|
|
|
let import_index = module.resolved_import_count.get();
|
2014-10-15 01:05:01 -05:00
|
|
|
let import_directive = &(*imports)[import_index];
|
2014-05-15 17:32:15 -05:00
|
|
|
match self.resolve_import_for_module(module.clone(),
|
|
|
|
import_directive) {
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => {
|
|
|
|
let (span, help) = match err {
|
|
|
|
Some((span, msg)) => (span, format!(". {}", msg)),
|
|
|
|
None => (import_directive.span, String::new())
|
|
|
|
};
|
|
|
|
let msg = format!("unresolved import `{}`{}",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.import_path_to_string(
|
2014-06-05 16:37:52 -05:00
|
|
|
import_directive.module_path
|
|
|
|
.as_slice(),
|
|
|
|
import_directive.subclass),
|
|
|
|
help);
|
|
|
|
self.resolve_error(span, msg.as_slice());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-06-05 16:37:52 -05:00
|
|
|
Indeterminate => break, // Bail out. We'll come around next time.
|
|
|
|
Success(()) => () // Good. Continue.
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-12-19 21:01:02 -06:00
|
|
|
module.resolved_import_count
|
|
|
|
.set(module.resolved_import_count.get() + 1);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn names_to_string(&self, names: &[Name]) -> String {
|
2013-03-20 00:17:42 -05:00
|
|
|
let mut first = true;
|
2014-05-22 18:57:53 -05:00
|
|
|
let mut result = String::new();
|
2014-09-30 19:11:34 -05:00
|
|
|
for name in names.iter() {
|
2013-06-11 21:13:42 -05:00
|
|
|
if first {
|
|
|
|
first = false
|
|
|
|
} else {
|
|
|
|
result.push_str("::")
|
|
|
|
}
|
2014-09-30 19:11:34 -05:00
|
|
|
result.push_str(token::get_name(*name).get());
|
2013-02-10 18:33:16 -06:00
|
|
|
};
|
2014-05-09 20:45:36 -05:00
|
|
|
result
|
2012-07-18 18:18:02 -05:00
|
|
|
}
|
2012-12-29 05:44:02 -06:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn path_names_to_string(&self, path: &Path) -> String {
|
|
|
|
let names: Vec<ast::Name> = path.segments
|
|
|
|
.iter()
|
|
|
|
.map(|seg| seg.identifier.name)
|
|
|
|
.collect();
|
|
|
|
self.names_to_string(names.as_slice())
|
2013-08-07 11:47:28 -05:00
|
|
|
}
|
|
|
|
|
2014-06-21 05:39:03 -05:00
|
|
|
fn import_directive_subclass_to_string(&mut self,
|
2014-01-31 14:25:11 -06:00
|
|
|
subclass: ImportDirectiveSubclass)
|
2014-05-22 18:57:53 -05:00
|
|
|
-> String {
|
2012-12-27 13:54:34 -06:00
|
|
|
match subclass {
|
2014-02-13 23:07:09 -06:00
|
|
|
SingleImport(_, source) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(source).get().to_string()
|
2014-01-31 14:25:11 -06:00
|
|
|
}
|
2014-05-25 05:17:19 -05:00
|
|
|
GlobImport => "*".to_string()
|
2012-12-27 13:54:34 -06:00
|
|
|
}
|
|
|
|
}
|
2012-12-29 05:44:02 -06:00
|
|
|
|
2014-06-21 05:39:03 -05:00
|
|
|
fn import_path_to_string(&mut self,
|
2014-09-30 19:11:34 -05:00
|
|
|
names: &[Name],
|
2014-01-31 14:25:11 -06:00
|
|
|
subclass: ImportDirectiveSubclass)
|
2014-05-22 18:57:53 -05:00
|
|
|
-> String {
|
2014-09-30 19:11:34 -05:00
|
|
|
if names.is_empty() {
|
2014-06-21 05:39:03 -05:00
|
|
|
self.import_directive_subclass_to_string(subclass)
|
2012-12-27 13:54:34 -06:00
|
|
|
} else {
|
2013-09-28 00:38:08 -05:00
|
|
|
(format!("{}::{}",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.names_to_string(names),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.import_directive_subclass_to_string(
|
2014-05-25 05:17:19 -05:00
|
|
|
subclass))).to_string()
|
2012-12-27 13:54:34 -06:00
|
|
|
}
|
|
|
|
}
|
2012-12-29 05:44:02 -06:00
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
/// Attempts to resolve the given import. The return value indicates
|
|
|
|
/// failure if we're certain the name does not exist, indeterminate if we
|
|
|
|
/// don't know whether the name exists at the moment due to other
|
|
|
|
/// currently-unresolved imports, or success if we know the name exists.
|
|
|
|
/// If successful, the resolved bindings are written into the module.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_import_for_module(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: Rc<Module>,
|
|
|
|
import_directive: &ImportDirective)
|
2013-12-22 18:39:46 -06:00
|
|
|
-> ResolveResult<()> {
|
2014-06-05 16:37:52 -05:00
|
|
|
let mut resolution_result = Failed(None);
|
2013-03-07 17:37:14 -06:00
|
|
|
let module_path = &import_directive.module_path;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving import for module) resolving import `{}::...` in \
|
2013-09-28 00:38:08 -05:00
|
|
|
`{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.names_to_string(module_path.as_slice()),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module_));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
// First, resolve the module path for the directive, if necessary.
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let container = if module_path.len() == 0 {
|
2013-03-01 12:44:43 -06:00
|
|
|
// Use the crate root.
|
2014-02-11 13:19:18 -06:00
|
|
|
Some((self.graph_root.get_module(), LastMod(AllPublic)))
|
2012-05-22 12:54:12 -05:00
|
|
|
} else {
|
2014-04-14 03:30:59 -05:00
|
|
|
match self.resolve_module_path(module_.clone(),
|
2014-03-08 14:36:22 -06:00
|
|
|
module_path.as_slice(),
|
2013-05-13 18:13:20 -05:00
|
|
|
DontUseLexicalScope,
|
|
|
|
import_directive.span,
|
|
|
|
ImportSearch) {
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => {
|
|
|
|
resolution_result = Failed(err);
|
|
|
|
None
|
|
|
|
},
|
2012-08-03 21:59:04 -05:00
|
|
|
Indeterminate => {
|
2012-05-22 12:54:12 -05:00
|
|
|
resolution_result = Indeterminate;
|
2013-03-01 12:44:43 -06:00
|
|
|
None
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Success(container) => Some(container),
|
2013-03-01 12:44:43 -06:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
match container {
|
2013-03-01 12:44:43 -06:00
|
|
|
None => {}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Some((containing_module, lp)) => {
|
2013-03-01 12:44:43 -06:00
|
|
|
// We found the module that the target is contained
|
|
|
|
// within. Attempt to resolve the import within it.
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
match import_directive.subclass {
|
2013-03-26 21:53:33 -05:00
|
|
|
SingleImport(target, source) => {
|
2013-03-01 12:44:43 -06:00
|
|
|
resolution_result =
|
2014-04-14 03:30:59 -05:00
|
|
|
self.resolve_single_import(&*module_,
|
2013-03-01 12:44:43 -06:00
|
|
|
containing_module,
|
|
|
|
target,
|
2013-05-14 13:19:59 -05:00
|
|
|
source,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
import_directive,
|
|
|
|
lp);
|
2013-03-01 12:44:43 -06:00
|
|
|
}
|
|
|
|
GlobImport => {
|
|
|
|
resolution_result =
|
2014-04-14 03:30:59 -05:00
|
|
|
self.resolve_glob_import(&*module_,
|
2013-03-01 12:44:43 -06:00
|
|
|
containing_module,
|
2014-08-12 22:31:30 -05:00
|
|
|
import_directive,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
lp);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decrement the count of unresolved imports.
|
2012-08-06 14:34:08 -05:00
|
|
|
match resolution_result {
|
2012-08-03 21:59:04 -05:00
|
|
|
Success(()) => {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(self.unresolved_imports >= 1);
|
2012-11-29 14:08:40 -06:00
|
|
|
self.unresolved_imports -= 1;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Nothing to do here; just return the error.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decrement the count of unresolved globs if necessary. But only if
|
|
|
|
// the resolution result is indeterminate -- otherwise we'll stop
|
|
|
|
// processing imports here. (See the loop in
|
|
|
|
// resolve_imports_for_module.)
|
|
|
|
|
2012-09-07 20:53:14 -05:00
|
|
|
if !resolution_result.indeterminate() {
|
2014-04-14 03:30:59 -05:00
|
|
|
match import_directive.subclass {
|
2012-08-03 21:59:04 -05:00
|
|
|
GlobImport => {
|
2013-12-19 20:59:03 -06:00
|
|
|
assert!(module_.glob_count.get() >= 1);
|
|
|
|
module_.glob_count.set(module_.glob_count.get() - 1);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-11-28 14:22:53 -06:00
|
|
|
SingleImport(..) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Ignore.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-01 19:30:05 -05:00
|
|
|
return resolution_result;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
|
2013-03-26 21:53:33 -05:00
|
|
|
NameBindings {
|
2013-12-21 16:13:06 -06:00
|
|
|
type_def: RefCell::new(Some(TypeNsDef {
|
2014-10-19 01:46:08 -05:00
|
|
|
modifiers: IMPORTABLE,
|
2013-03-26 21:53:33 -05:00
|
|
|
module_def: Some(module),
|
|
|
|
type_def: None,
|
2013-05-14 23:49:30 -05:00
|
|
|
type_span: None
|
2013-12-21 16:13:06 -06:00
|
|
|
})),
|
2013-12-21 16:15:07 -06:00
|
|
|
value_def: RefCell::new(None),
|
2013-03-26 21:53:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_single_import(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: &Module,
|
|
|
|
containing_module: Rc<Module>,
|
2014-09-30 19:11:34 -05:00
|
|
|
target: Name,
|
|
|
|
source: Name,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
directive: &ImportDirective,
|
|
|
|
lp: LastPrivate)
|
2013-05-31 17:17:22 -05:00
|
|
|
-> ResolveResult<()> {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving single import) resolving `{}` = `{}::{}` from \
|
2014-10-15 01:25:34 -05:00
|
|
|
`{}` id {}, last private {}",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(target),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*containing_module),
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(source),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(module_),
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
directive.id,
|
|
|
|
lp);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-02-11 13:19:18 -06:00
|
|
|
let lp = match lp {
|
|
|
|
LastMod(lp) => lp,
|
2014-05-09 20:45:36 -05:00
|
|
|
LastImport {..} => {
|
|
|
|
self.session
|
|
|
|
.span_bug(directive.span,
|
|
|
|
"not expecting Import here, must be LastMod")
|
|
|
|
}
|
2014-02-11 13:19:18 -06:00
|
|
|
};
|
|
|
|
|
2012-10-15 16:56:42 -05:00
|
|
|
// We need to resolve both namespaces for this to succeed.
|
2012-05-22 12:54:12 -05:00
|
|
|
//
|
|
|
|
|
|
|
|
let mut value_result = UnknownResult;
|
|
|
|
let mut type_result = UnknownResult;
|
|
|
|
|
|
|
|
// Search for direct children of the containing module.
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&containing_module);
|
2013-12-21 17:32:44 -06:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
match containing_module.children.borrow().find(&source) {
|
2014-03-20 21:49:20 -05:00
|
|
|
None => {
|
|
|
|
// Continue.
|
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref child_name_bindings) => {
|
2014-03-20 21:49:20 -05:00
|
|
|
if child_name_bindings.defined_in_namespace(ValueNS) {
|
2014-04-08 16:31:25 -05:00
|
|
|
debug!("(resolving single import) found value binding");
|
2014-04-14 03:30:59 -05:00
|
|
|
value_result = BoundResult(containing_module.clone(),
|
|
|
|
(*child_name_bindings).clone());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-03-20 21:49:20 -05:00
|
|
|
if child_name_bindings.defined_in_namespace(TypeNS) {
|
2014-04-08 16:31:25 -05:00
|
|
|
debug!("(resolving single import) found type binding");
|
2014-04-14 03:30:59 -05:00
|
|
|
type_result = BoundResult(containing_module.clone(),
|
|
|
|
(*child_name_bindings).clone());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-15 16:56:42 -05:00
|
|
|
// Unless we managed to find a result in both namespaces (unlikely),
|
|
|
|
// search imports as well.
|
2014-02-11 13:19:18 -06:00
|
|
|
let mut value_used_reexport = false;
|
|
|
|
let mut type_used_reexport = false;
|
2014-04-14 03:30:59 -05:00
|
|
|
match (value_result.clone(), type_result.clone()) {
|
2013-11-28 14:22:53 -06:00
|
|
|
(BoundResult(..), BoundResult(..)) => {} // Continue.
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// If there is an unresolved glob at this point in the
|
|
|
|
// containing module, bail out. We don't know enough to be
|
|
|
|
// able to resolve this import.
|
|
|
|
|
2013-12-19 20:59:03 -06:00
|
|
|
if containing_module.glob_count.get() > 0 {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving single import) unresolved glob; \
|
2012-08-22 19:24:52 -05:00
|
|
|
bailing out");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Indeterminate;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
// Now search the exported imports within the containing module.
|
2014-09-30 19:11:34 -05:00
|
|
|
match containing_module.import_resolutions.borrow().find(&source) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2014-04-08 16:31:25 -05:00
|
|
|
debug!("(resolving single import) no import");
|
2012-05-22 12:54:12 -05:00
|
|
|
// The containing module definitely doesn't have an
|
|
|
|
// exported import with the name in question. We can
|
|
|
|
// therefore accurately report that the names are
|
|
|
|
// unbound.
|
|
|
|
|
2012-08-27 18:26:35 -05:00
|
|
|
if value_result.is_unknown() {
|
2012-05-22 12:54:12 -05:00
|
|
|
value_result = UnboundResult;
|
|
|
|
}
|
2012-08-27 18:26:35 -05:00
|
|
|
if type_result.is_unknown() {
|
2012-05-22 12:54:12 -05:00
|
|
|
type_result = UnboundResult;
|
|
|
|
}
|
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(import_resolution)
|
2014-04-14 03:30:59 -05:00
|
|
|
if import_resolution.outstanding_references == 0 => {
|
2012-07-06 21:06:58 -05:00
|
|
|
|
2013-09-26 21:10:16 -05:00
|
|
|
fn get_binding(this: &mut Resolver,
|
2014-04-14 03:30:59 -05:00
|
|
|
import_resolution: &ImportResolution,
|
2012-05-22 12:54:12 -05:00
|
|
|
namespace: Namespace)
|
|
|
|
-> NamespaceResult {
|
2012-11-29 14:08:40 -06:00
|
|
|
|
2012-10-02 20:13:56 -05:00
|
|
|
// Import resolutions must be declared with "pub"
|
|
|
|
// in order to be exported.
|
2014-04-14 03:30:59 -05:00
|
|
|
if !import_resolution.is_public {
|
2012-10-02 20:13:56 -05:00
|
|
|
return UnboundResult;
|
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
match import_resolution.
|
2012-05-22 12:54:12 -05:00
|
|
|
target_for_namespace(namespace) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-08-01 19:30:05 -05:00
|
|
|
return UnboundResult;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-08-12 22:31:30 -05:00
|
|
|
Some(Target {
|
|
|
|
target_module,
|
|
|
|
bindings,
|
|
|
|
shadowable: _
|
|
|
|
}) => {
|
2014-04-08 16:31:25 -05:00
|
|
|
debug!("(resolving single import) found \
|
2014-10-15 01:25:34 -05:00
|
|
|
import in ns {}", namespace);
|
2013-06-09 23:39:15 -05:00
|
|
|
let id = import_resolution.id(namespace);
|
2014-09-11 12:14:43 -05:00
|
|
|
// track used imports and extern crates as well
|
2014-02-11 13:19:18 -06:00
|
|
|
this.used_imports.insert((id, namespace));
|
2014-09-11 12:14:43 -05:00
|
|
|
match target_module.def_id.get() {
|
|
|
|
Some(DefId{krate: kid, ..}) => {
|
|
|
|
this.used_crates.insert(kid);
|
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
return BoundResult(target_module, bindings);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The name is an import which has been fully
|
|
|
|
// resolved. We can, therefore, just follow it.
|
2012-08-27 18:26:35 -05:00
|
|
|
if value_result.is_unknown() {
|
2014-04-14 03:30:59 -05:00
|
|
|
value_result = get_binding(self, import_resolution,
|
2012-05-22 12:54:12 -05:00
|
|
|
ValueNS);
|
2014-04-14 03:30:59 -05:00
|
|
|
value_used_reexport = import_resolution.is_public;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-27 18:26:35 -05:00
|
|
|
if type_result.is_unknown() {
|
2014-04-14 03:30:59 -05:00
|
|
|
type_result = get_binding(self, import_resolution,
|
2012-05-22 12:54:12 -05:00
|
|
|
TypeNS);
|
2014-04-14 03:30:59 -05:00
|
|
|
type_used_reexport = import_resolution.is_public;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(_) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// The import is unresolved. Bail out.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving single import) unresolved import; \
|
2012-08-22 19:24:52 -05:00
|
|
|
bailing out");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Indeterminate;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-26 21:53:33 -05:00
|
|
|
// If we didn't find a result in the type namespace, search the
|
|
|
|
// external modules.
|
2014-02-11 13:19:18 -06:00
|
|
|
let mut value_used_public = false;
|
|
|
|
let mut type_used_public = false;
|
2013-03-26 21:53:33 -05:00
|
|
|
match type_result {
|
2013-11-28 14:22:53 -06:00
|
|
|
BoundResult(..) => {}
|
2013-03-26 21:53:33 -05:00
|
|
|
_ => {
|
2014-03-20 21:49:20 -05:00
|
|
|
match containing_module.external_module_children.borrow_mut()
|
2014-09-30 19:11:34 -05:00
|
|
|
.find_copy(&source) {
|
2013-03-26 21:53:33 -05:00
|
|
|
None => {} // Continue.
|
|
|
|
Some(module) => {
|
2014-04-08 16:31:25 -05:00
|
|
|
debug!("(resolving single import) found external \
|
|
|
|
module");
|
2014-09-11 12:14:43 -05:00
|
|
|
// track the module as used.
|
|
|
|
match module.def_id.get() {
|
|
|
|
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
|
|
|
|
_ => {}
|
|
|
|
}
|
2013-03-26 21:53:33 -05:00
|
|
|
let name_bindings =
|
2014-04-14 03:30:59 -05:00
|
|
|
Rc::new(Resolver::create_name_bindings_from_module(
|
|
|
|
module));
|
|
|
|
type_result = BoundResult(containing_module.clone(),
|
2013-03-26 21:53:33 -05:00
|
|
|
name_bindings);
|
2014-02-11 13:19:18 -06:00
|
|
|
type_used_public = true;
|
2013-03-26 21:53:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// We've successfully resolved the import. Write the results in.
|
2014-04-14 03:30:59 -05:00
|
|
|
let mut import_resolutions = module_.import_resolutions.borrow_mut();
|
2014-10-23 10:42:21 -05:00
|
|
|
let import_resolution = &mut (*import_resolutions)[target];
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
match value_result {
|
2014-04-14 03:30:59 -05:00
|
|
|
BoundResult(ref target_module, ref name_bindings) => {
|
2014-10-15 01:25:34 -05:00
|
|
|
debug!("(resolving single import) found value target: {}",
|
2014-09-29 11:27:07 -05:00
|
|
|
{ name_bindings.value_def.borrow().clone().unwrap().def });
|
2014-08-12 22:31:30 -05:00
|
|
|
self.check_for_conflicting_import(
|
|
|
|
&import_resolution.value_target,
|
|
|
|
directive.span,
|
2014-09-30 19:11:34 -05:00
|
|
|
target,
|
2014-08-12 22:31:30 -05:00
|
|
|
ValueNS);
|
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
self.check_that_import_is_importable(
|
|
|
|
&**name_bindings,
|
|
|
|
directive.span,
|
|
|
|
target,
|
|
|
|
ValueNS);
|
|
|
|
|
2014-08-12 22:31:30 -05:00
|
|
|
import_resolution.value_target =
|
|
|
|
Some(Target::new(target_module.clone(),
|
|
|
|
name_bindings.clone(),
|
|
|
|
directive.shadowable));
|
2014-04-14 03:30:59 -05:00
|
|
|
import_resolution.value_id = directive.id;
|
2014-05-15 17:32:15 -05:00
|
|
|
import_resolution.is_public = directive.is_public;
|
2014-02-11 13:19:18 -06:00
|
|
|
value_used_public = name_bindings.defined_in_public_namespace(ValueNS);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
UnboundResult => { /* Continue. */ }
|
|
|
|
UnknownResult => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("value result should be known at this point");
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-06 14:34:08 -05:00
|
|
|
match type_result {
|
2014-04-14 03:30:59 -05:00
|
|
|
BoundResult(ref target_module, ref name_bindings) => {
|
2014-10-15 01:25:34 -05:00
|
|
|
debug!("(resolving single import) found type target: {}",
|
2014-03-28 12:29:55 -05:00
|
|
|
{ name_bindings.type_def.borrow().clone().unwrap().type_def });
|
2014-08-12 22:31:30 -05:00
|
|
|
self.check_for_conflicting_import(
|
|
|
|
&import_resolution.type_target,
|
|
|
|
directive.span,
|
2014-09-30 19:11:34 -05:00
|
|
|
target,
|
2014-08-12 22:31:30 -05:00
|
|
|
TypeNS);
|
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
self.check_that_import_is_importable(
|
|
|
|
&**name_bindings,
|
|
|
|
directive.span,
|
|
|
|
target,
|
|
|
|
TypeNS);
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
import_resolution.type_target =
|
2014-08-12 22:31:30 -05:00
|
|
|
Some(Target::new(target_module.clone(),
|
|
|
|
name_bindings.clone(),
|
|
|
|
directive.shadowable));
|
2014-04-14 03:30:59 -05:00
|
|
|
import_resolution.type_id = directive.id;
|
2014-05-15 17:32:15 -05:00
|
|
|
import_resolution.is_public = directive.is_public;
|
2014-02-11 13:19:18 -06:00
|
|
|
type_used_public = name_bindings.defined_in_public_namespace(TypeNS);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
UnboundResult => { /* Continue. */ }
|
|
|
|
UnknownResult => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("type result should be known at this point");
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-12 22:31:30 -05:00
|
|
|
self.check_for_conflicts_between_imports_and_items(
|
|
|
|
module_,
|
|
|
|
import_resolution,
|
|
|
|
directive.span,
|
2014-09-30 19:11:34 -05:00
|
|
|
target);
|
2014-08-12 22:31:30 -05:00
|
|
|
|
2014-04-08 17:03:29 -05:00
|
|
|
if value_result.is_unbound() && type_result.is_unbound() {
|
2014-06-05 16:37:52 -05:00
|
|
|
let msg = format!("There is no `{}` in `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(source),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*containing_module));
|
2014-06-05 16:37:52 -05:00
|
|
|
return Failed(Some((directive.span, msg)));
|
2013-05-12 08:03:39 -05:00
|
|
|
}
|
2014-02-11 13:19:18 -06:00
|
|
|
let value_used_public = value_used_reexport || value_used_public;
|
|
|
|
let type_used_public = type_used_reexport || type_used_public;
|
2013-05-12 08:03:39 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
assert!(import_resolution.outstanding_references >= 1);
|
|
|
|
import_resolution.outstanding_references -= 1;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-09-24 15:56:52 -05:00
|
|
|
// record what this import resolves to for later uses in documentation,
|
|
|
|
// this may resolve to either a value or a type, but for documentation
|
|
|
|
// purposes it's good enough to just favor one over the other.
|
2014-04-14 03:30:59 -05:00
|
|
|
let value_private = match import_resolution.value_target {
|
|
|
|
Some(ref target) => {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let def = target.bindings.def_for_namespace(ValueNS).unwrap();
|
2014-03-20 21:49:20 -05:00
|
|
|
self.def_map.borrow_mut().insert(directive.id, def);
|
2014-05-14 14:31:30 -05:00
|
|
|
let did = def.def_id();
|
2014-02-11 13:19:18 -06:00
|
|
|
if value_used_public {Some(lp)} else {Some(DependsOn(did))}
|
|
|
|
},
|
|
|
|
// AllPublic here and below is a dummy value, it should never be used because
|
|
|
|
// _exists is false.
|
|
|
|
None => None,
|
|
|
|
};
|
2014-04-14 03:30:59 -05:00
|
|
|
let type_private = match import_resolution.type_target {
|
|
|
|
Some(ref target) => {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let def = target.bindings.def_for_namespace(TypeNS).unwrap();
|
2014-03-20 21:49:20 -05:00
|
|
|
self.def_map.borrow_mut().insert(directive.id, def);
|
2014-05-14 14:31:30 -05:00
|
|
|
let did = def.def_id();
|
2014-02-11 13:19:18 -06:00
|
|
|
if type_used_public {Some(lp)} else {Some(DependsOn(did))}
|
|
|
|
},
|
|
|
|
None => None,
|
|
|
|
};
|
|
|
|
|
|
|
|
self.last_private.insert(directive.id, LastImport{value_priv: value_private,
|
|
|
|
value_used: Used,
|
|
|
|
type_priv: type_private,
|
|
|
|
type_used: Used});
|
2013-09-24 15:56:52 -05:00
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving single import) successfully resolved import");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Success(());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-03-26 21:53:33 -05:00
|
|
|
// Resolves a glob import. Note that this function cannot fail; it either
|
|
|
|
// succeeds or bails out (as importing * from an empty module or a module
|
|
|
|
// that exports nothing is valid).
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_glob_import(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: &Module,
|
|
|
|
containing_module: Rc<Module>,
|
2014-08-12 22:31:30 -05:00
|
|
|
import_directive: &ImportDirective,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
lp: LastPrivate)
|
|
|
|
-> ResolveResult<()> {
|
2014-08-12 22:31:30 -05:00
|
|
|
let id = import_directive.id;
|
|
|
|
let is_public = import_directive.is_public;
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// This function works in a highly imperative manner; it eagerly adds
|
|
|
|
// everything it can to the list of import resolutions of the module
|
|
|
|
// node.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving glob import) resolving glob import {}", id);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// We must bail out if the node has unresolved imports of any kind
|
|
|
|
// (including globs).
|
|
|
|
if !(*containing_module).all_imports_resolved() {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving glob import) target module has unresolved \
|
2012-08-22 19:24:52 -05:00
|
|
|
imports; bailing out");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Indeterminate;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-12-19 20:59:03 -06:00
|
|
|
assert_eq!(containing_module.glob_count.get(), 0);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Add all resolved imports from the containing module.
|
2013-12-21 17:15:54 -06:00
|
|
|
let import_resolutions = containing_module.import_resolutions
|
|
|
|
.borrow();
|
2014-03-20 21:49:20 -05:00
|
|
|
for (ident, target_import_resolution) in import_resolutions.iter() {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving glob import) writing module resolution \
|
2014-10-15 01:25:34 -05:00
|
|
|
{} into `{}`",
|
2014-04-14 03:30:59 -05:00
|
|
|
target_import_resolution.type_target.is_none(),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(module_));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
if !target_import_resolution.is_public {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving glob import) nevermind, just kidding");
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// Here we merge two import resolutions.
|
2014-03-20 21:49:20 -05:00
|
|
|
let mut import_resolutions = module_.import_resolutions.borrow_mut();
|
2014-04-14 03:30:59 -05:00
|
|
|
match import_resolutions.find_mut(ident) {
|
|
|
|
Some(dest_import_resolution) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Merge the two import resolutions at a finer-grained
|
|
|
|
// level.
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
match target_import_resolution.value_target {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Continue.
|
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref value_target) => {
|
|
|
|
dest_import_resolution.value_target =
|
|
|
|
Some(value_target.clone());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
match target_import_resolution.type_target {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Continue.
|
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref type_target) => {
|
|
|
|
dest_import_resolution.type_target =
|
|
|
|
Some(type_target.clone());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
dest_import_resolution.is_public = is_public;
|
|
|
|
continue;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
None => {}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
|
|
|
|
// Simple: just copy the old import resolution.
|
|
|
|
let mut new_import_resolution = ImportResolution::new(id, is_public);
|
|
|
|
new_import_resolution.value_target =
|
|
|
|
target_import_resolution.value_target.clone();
|
|
|
|
new_import_resolution.type_target =
|
|
|
|
target_import_resolution.type_target.clone();
|
|
|
|
|
|
|
|
import_resolutions.insert(*ident, new_import_resolution);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-03-26 21:53:33 -05:00
|
|
|
// Add all children from the containing module.
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&containing_module);
|
2013-12-21 17:32:44 -06:00
|
|
|
|
2014-03-20 21:49:20 -05:00
|
|
|
for (&name, name_bindings) in containing_module.children
|
|
|
|
.borrow().iter() {
|
2014-08-12 22:31:30 -05:00
|
|
|
self.merge_import_resolution(module_,
|
|
|
|
containing_module.clone(),
|
|
|
|
import_directive,
|
|
|
|
name,
|
|
|
|
name_bindings.clone());
|
|
|
|
|
2013-03-26 21:53:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add external module children from the containing module.
|
2014-03-20 21:49:20 -05:00
|
|
|
for (&name, module) in containing_module.external_module_children
|
|
|
|
.borrow().iter() {
|
|
|
|
let name_bindings =
|
2014-04-14 03:30:59 -05:00
|
|
|
Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
|
2014-08-12 22:31:30 -05:00
|
|
|
self.merge_import_resolution(module_,
|
|
|
|
containing_module.clone(),
|
|
|
|
import_directive,
|
|
|
|
name,
|
|
|
|
name_bindings);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-09-24 15:56:52 -05:00
|
|
|
// Record the destination of this import
|
2013-12-19 20:56:20 -06:00
|
|
|
match containing_module.def_id.get() {
|
2013-09-24 15:56:52 -05:00
|
|
|
Some(did) => {
|
2014-03-20 21:49:20 -05:00
|
|
|
self.def_map.borrow_mut().insert(id, DefMod(did));
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
self.last_private.insert(id, lp);
|
2013-09-24 15:56:52 -05:00
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving glob import) successfully resolved import");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Success(());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-02-07 13:45:18 -06:00
|
|
|
fn merge_import_resolution(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: &Module,
|
|
|
|
containing_module: Rc<Module>,
|
2014-08-12 22:31:30 -05:00
|
|
|
import_directive: &ImportDirective,
|
2014-02-07 13:45:18 -06:00
|
|
|
name: Name,
|
2014-04-14 03:30:59 -05:00
|
|
|
name_bindings: Rc<NameBindings>) {
|
2014-08-12 22:31:30 -05:00
|
|
|
let id = import_directive.id;
|
|
|
|
let is_public = import_directive.is_public;
|
|
|
|
|
2014-02-07 13:45:18 -06:00
|
|
|
let mut import_resolutions = module_.import_resolutions.borrow_mut();
|
2014-09-18 16:05:52 -05:00
|
|
|
let dest_import_resolution = match import_resolutions.entry(name) {
|
|
|
|
Occupied(entry) => entry.into_mut(),
|
|
|
|
Vacant(entry) => {
|
|
|
|
// Create a new import resolution from this child.
|
|
|
|
entry.set(ImportResolution::new(id, is_public))
|
|
|
|
}
|
|
|
|
};
|
2014-02-07 13:45:18 -06:00
|
|
|
|
|
|
|
debug!("(resolving glob import) writing resolution `{}` in `{}` \
|
|
|
|
to `{}`",
|
2014-06-21 05:39:03 -05:00
|
|
|
token::get_name(name).get().to_string(),
|
|
|
|
self.module_to_string(&*containing_module),
|
|
|
|
self.module_to_string(module_));
|
2014-02-07 13:45:18 -06:00
|
|
|
|
|
|
|
// Merge the child item into the import resolution.
|
2014-10-19 01:46:08 -05:00
|
|
|
if name_bindings.defined_in_namespace_with(ValueNS, IMPORTABLE | PUBLIC) {
|
2014-02-07 13:45:18 -06:00
|
|
|
debug!("(resolving glob import) ... for value target");
|
2014-04-14 03:30:59 -05:00
|
|
|
dest_import_resolution.value_target =
|
2014-08-12 22:31:30 -05:00
|
|
|
Some(Target::new(containing_module.clone(),
|
|
|
|
name_bindings.clone(),
|
|
|
|
import_directive.shadowable));
|
2014-04-14 03:30:59 -05:00
|
|
|
dest_import_resolution.value_id = id;
|
2014-02-07 13:45:18 -06:00
|
|
|
}
|
2014-10-19 01:46:08 -05:00
|
|
|
if name_bindings.defined_in_namespace_with(TypeNS, IMPORTABLE | PUBLIC) {
|
2014-02-07 13:45:18 -06:00
|
|
|
debug!("(resolving glob import) ... for type target");
|
2014-04-14 03:30:59 -05:00
|
|
|
dest_import_resolution.type_target =
|
2014-08-12 22:31:30 -05:00
|
|
|
Some(Target::new(containing_module,
|
|
|
|
name_bindings.clone(),
|
|
|
|
import_directive.shadowable));
|
2014-04-14 03:30:59 -05:00
|
|
|
dest_import_resolution.type_id = id;
|
2014-02-07 13:45:18 -06:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
dest_import_resolution.is_public = is_public;
|
2014-08-12 22:31:30 -05:00
|
|
|
|
|
|
|
self.check_for_conflicts_between_imports_and_items(
|
|
|
|
module_,
|
|
|
|
dest_import_resolution,
|
|
|
|
import_directive.span,
|
|
|
|
name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks that imported names and items don't have the same name.
|
|
|
|
fn check_for_conflicting_import(&mut self,
|
|
|
|
target: &Option<Target>,
|
|
|
|
import_span: Span,
|
|
|
|
name: Name,
|
|
|
|
namespace: Namespace) {
|
2014-09-10 19:55:42 -05:00
|
|
|
if self.session.features.borrow().import_shadowing {
|
2014-08-12 22:31:30 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
match *target {
|
|
|
|
Some(ref target) if !target.shadowable => {
|
|
|
|
let msg = format!("a {} named `{}` has already been imported \
|
|
|
|
in this module",
|
|
|
|
match namespace {
|
|
|
|
TypeNS => "type",
|
|
|
|
ValueNS => "value",
|
|
|
|
},
|
|
|
|
token::get_name(name).get());
|
|
|
|
self.session.span_err(import_span, msg.as_slice());
|
|
|
|
}
|
|
|
|
Some(_) | None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
/// Checks that an import is actually importable
|
|
|
|
fn check_that_import_is_importable(&mut self,
|
|
|
|
name_bindings: &NameBindings,
|
|
|
|
import_span: Span,
|
|
|
|
name: Name,
|
|
|
|
namespace: Namespace) {
|
|
|
|
if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) {
|
|
|
|
let msg = format!("`{}` is not directly importable",
|
|
|
|
token::get_name(name));
|
|
|
|
self.session.span_err(import_span, msg.as_slice());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-12 22:31:30 -05:00
|
|
|
/// Checks that imported names and items don't have the same name.
|
|
|
|
fn check_for_conflicts_between_imports_and_items(&mut self,
|
|
|
|
module: &Module,
|
|
|
|
import_resolution:
|
|
|
|
&mut ImportResolution,
|
|
|
|
import_span: Span,
|
|
|
|
name: Name) {
|
2014-09-10 19:55:42 -05:00
|
|
|
if self.session.features.borrow().import_shadowing {
|
2014-08-12 22:31:30 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// First, check for conflicts between imports and `extern crate`s.
|
|
|
|
if module.external_module_children
|
|
|
|
.borrow()
|
|
|
|
.contains_key(&name) {
|
|
|
|
match import_resolution.type_target {
|
|
|
|
Some(ref target) if !target.shadowable => {
|
2014-08-19 02:07:30 -05:00
|
|
|
let msg = format!("import `{}` conflicts with imported \
|
|
|
|
crate in this module",
|
|
|
|
token::get_name(name).get());
|
|
|
|
self.session.span_err(import_span, msg.as_slice());
|
2014-08-12 22:31:30 -05:00
|
|
|
}
|
|
|
|
Some(_) | None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for item conflicts.
|
|
|
|
let children = module.children.borrow();
|
|
|
|
let name_bindings = match children.find(&name) {
|
|
|
|
None => {
|
|
|
|
// There can't be any conflicts.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
Some(ref name_bindings) => (*name_bindings).clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
match import_resolution.value_target {
|
|
|
|
Some(ref target) if !target.shadowable => {
|
|
|
|
match *name_bindings.value_def.borrow() {
|
2014-10-19 01:46:08 -05:00
|
|
|
// We want to allow the "flat" def of enum variants to be shadowed
|
|
|
|
Some(ref value) if !value.modifiers.contains(ENUM_STAGING_HACK) => {
|
2014-08-19 02:07:30 -05:00
|
|
|
let msg = format!("import `{}` conflicts with value \
|
|
|
|
in this module",
|
|
|
|
token::get_name(name).get());
|
|
|
|
self.session.span_err(import_span, msg.as_slice());
|
2014-08-12 22:31:30 -05:00
|
|
|
match value.value_span {
|
|
|
|
None => {}
|
|
|
|
Some(span) => {
|
|
|
|
self.session
|
|
|
|
.span_note(span,
|
2014-09-21 00:18:30 -05:00
|
|
|
"conflicting value here");
|
2014-08-12 22:31:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-10-19 01:46:08 -05:00
|
|
|
_ => {}
|
2014-08-12 22:31:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(_) | None => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
match import_resolution.type_target {
|
|
|
|
Some(ref target) if !target.shadowable => {
|
|
|
|
match *name_bindings.type_def.borrow() {
|
2014-10-19 01:46:08 -05:00
|
|
|
// We want to allow the "flat" def of enum variants to be shadowed
|
|
|
|
Some(ref ty) if !ty.modifiers.contains(ENUM_STAGING_HACK) => {
|
2014-09-16 17:39:18 -05:00
|
|
|
match ty.module_def {
|
|
|
|
None => {
|
|
|
|
let msg = format!("import `{}` conflicts with type in \
|
|
|
|
this module",
|
|
|
|
token::get_name(name).get());
|
|
|
|
self.session.span_err(import_span, msg.as_slice());
|
|
|
|
match ty.type_span {
|
|
|
|
None => {}
|
|
|
|
Some(span) => {
|
|
|
|
self.session
|
|
|
|
.span_note(span,
|
|
|
|
"note conflicting type here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(ref module_def) => {
|
|
|
|
match module_def.kind.get() {
|
|
|
|
ImplModuleKind => {
|
|
|
|
match ty.type_span {
|
|
|
|
None => { /* this can't ever happen */ }
|
|
|
|
Some(span) => {
|
|
|
|
let msg = format!("inherent implementations \
|
|
|
|
are only allowed on types \
|
|
|
|
defined in the current module");
|
|
|
|
self.session
|
|
|
|
.span_err(span, msg.as_slice());
|
|
|
|
self.session
|
|
|
|
.span_note(import_span,
|
|
|
|
"import from other module here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let msg = format!("import `{}` conflicts with existing \
|
|
|
|
submodule",
|
|
|
|
token::get_name(name).get());
|
|
|
|
self.session.span_err(import_span, msg.as_slice());
|
|
|
|
match ty.type_span {
|
|
|
|
None => {}
|
|
|
|
Some(span) => {
|
|
|
|
self.session
|
|
|
|
.span_note(span,
|
|
|
|
"note conflicting module here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-08-12 22:31:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-10-19 01:46:08 -05:00
|
|
|
_ => {}
|
2014-08-12 22:31:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(_) | None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks that the names of external crates don't collide with other
|
|
|
|
/// external crates.
|
|
|
|
fn check_for_conflicts_between_external_crates(&self,
|
|
|
|
module: &Module,
|
|
|
|
name: Name,
|
|
|
|
span: Span) {
|
2014-09-10 19:55:42 -05:00
|
|
|
if self.session.features.borrow().import_shadowing {
|
2014-08-12 22:31:30 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if module.external_module_children.borrow().contains_key(&name) {
|
|
|
|
self.session
|
|
|
|
.span_err(span,
|
|
|
|
format!("an external crate named `{}` has already \
|
|
|
|
been imported into this module",
|
|
|
|
token::get_name(name).get()).as_slice());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks that the names of items don't collide with external crates.
|
|
|
|
fn check_for_conflicts_between_external_crates_and_items(&self,
|
|
|
|
module: &Module,
|
|
|
|
name: Name,
|
|
|
|
span: Span) {
|
2014-09-10 19:55:42 -05:00
|
|
|
if self.session.features.borrow().import_shadowing {
|
2014-08-12 22:31:30 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if module.external_module_children.borrow().contains_key(&name) {
|
|
|
|
self.session
|
|
|
|
.span_err(span,
|
|
|
|
format!("the name `{}` conflicts with an external \
|
|
|
|
crate that has been imported into this \
|
|
|
|
module",
|
|
|
|
token::get_name(name).get()).as_slice());
|
|
|
|
}
|
2014-02-07 13:45:18 -06:00
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
/// Resolves the given module path from the given root `module_`.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_module_path_from_root(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: Rc<Module>,
|
2014-09-30 19:11:34 -05:00
|
|
|
module_path: &[Name],
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
index: uint,
|
|
|
|
span: Span,
|
|
|
|
name_search_type: NameSearchType,
|
|
|
|
lp: LastPrivate)
|
2014-04-14 03:30:59 -05:00
|
|
|
-> ResolveResult<(Rc<Module>, LastPrivate)> {
|
2014-06-04 17:55:10 -05:00
|
|
|
fn search_parent_externals(needle: Name, module: &Rc<Module>)
|
|
|
|
-> Option<Rc<Module>> {
|
|
|
|
module.external_module_children.borrow()
|
|
|
|
.find_copy(&needle)
|
|
|
|
.map(|_| module.clone())
|
|
|
|
.or_else(|| {
|
|
|
|
match module.parent_link.clone() {
|
|
|
|
ModuleParentLink(parent, _) => {
|
|
|
|
search_parent_externals(needle,
|
|
|
|
&parent.upgrade().unwrap())
|
|
|
|
}
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2012-07-31 18:38:41 -05:00
|
|
|
let mut search_module = module_;
|
2012-05-22 12:54:12 -05:00
|
|
|
let mut index = index;
|
2013-03-07 17:37:14 -06:00
|
|
|
let module_path_len = module_path.len();
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let mut closest_private = lp;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Resolve the module part of the path. This does not involve looking
|
|
|
|
// upward though scope chains; we simply resolve names directly in
|
|
|
|
// modules as we go.
|
|
|
|
while index < module_path_len {
|
2013-03-07 17:37:14 -06:00
|
|
|
let name = module_path[index];
|
2014-04-14 03:30:59 -05:00
|
|
|
match self.resolve_name_in_module(search_module.clone(),
|
2014-09-30 19:11:34 -05:00
|
|
|
name,
|
2012-12-13 15:05:22 -06:00
|
|
|
TypeNS,
|
2014-04-08 16:31:25 -05:00
|
|
|
name_search_type,
|
|
|
|
false) {
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(None) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let segment_name = token::get_name(name);
|
2014-06-21 05:39:03 -05:00
|
|
|
let module_name = self.module_to_string(&*search_module);
|
2014-06-05 16:37:52 -05:00
|
|
|
let mut span = span;
|
|
|
|
let msg = if "???" == module_name.as_slice() {
|
|
|
|
span.hi = span.lo + Pos::from_uint(segment_name.get().len());
|
2014-06-04 17:55:10 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
match search_parent_externals(name,
|
2014-06-05 16:37:52 -05:00
|
|
|
&self.current_module) {
|
2014-06-04 17:55:10 -05:00
|
|
|
Some(module) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let path_str = self.names_to_string(module_path);
|
2014-06-21 05:39:03 -05:00
|
|
|
let target_mod_str = self.module_to_string(&*module);
|
2014-06-05 16:37:52 -05:00
|
|
|
let current_mod_str =
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*self.current_module);
|
2014-06-04 17:55:10 -05:00
|
|
|
|
|
|
|
let prefix = if target_mod_str == current_mod_str {
|
|
|
|
"self::".to_string()
|
|
|
|
} else {
|
|
|
|
format!("{}::", target_mod_str)
|
|
|
|
};
|
|
|
|
|
2014-06-05 16:37:52 -05:00
|
|
|
format!("Did you mean `{}{}`?", prefix, path_str)
|
2014-06-04 17:55:10 -05:00
|
|
|
},
|
2014-06-05 16:37:52 -05:00
|
|
|
None => format!("Maybe a missing `extern crate {}`?",
|
|
|
|
segment_name),
|
2014-06-04 17:55:10 -05:00
|
|
|
}
|
2014-06-05 16:37:52 -05:00
|
|
|
} else {
|
|
|
|
format!("Could not find `{}` in `{}`.",
|
|
|
|
segment_name,
|
|
|
|
module_name)
|
|
|
|
};
|
2014-06-04 17:55:10 -05:00
|
|
|
|
2014-06-05 16:37:52 -05:00
|
|
|
return Failed(Some((span, msg)));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => return Failed(err),
|
2012-08-03 21:59:04 -05:00
|
|
|
Indeterminate => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving module path for import) module \
|
2013-09-28 00:38:08 -05:00
|
|
|
resolution is indeterminate: {}",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name));
|
2012-08-01 19:30:05 -05:00
|
|
|
return Indeterminate;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Success((target, used_proxy)) => {
|
2012-10-15 20:04:15 -05:00
|
|
|
// Check to see whether there are type bindings, and, if
|
|
|
|
// so, whether there is a module within.
|
2014-03-28 12:29:55 -05:00
|
|
|
match *target.bindings.type_def.borrow() {
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref type_def) => {
|
2012-10-15 20:04:15 -05:00
|
|
|
match type_def.module_def {
|
|
|
|
None => {
|
2014-06-05 16:37:52 -05:00
|
|
|
let msg = format!("Not a module `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name));
|
2014-06-05 16:37:52 -05:00
|
|
|
|
|
|
|
return Failed(Some((span, msg)));
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref module_def) => {
|
2014-10-19 01:46:08 -05:00
|
|
|
search_module = module_def.clone();
|
|
|
|
|
|
|
|
// track extern crates for unused_extern_crate lint
|
|
|
|
match module_def.def_id.get() {
|
|
|
|
Some(did) => {
|
|
|
|
self.used_crates.insert(did.krate);
|
2013-05-13 18:13:20 -05:00
|
|
|
}
|
2014-10-19 01:46:08 -05:00
|
|
|
_ => {}
|
|
|
|
}
|
2014-09-11 12:14:43 -05:00
|
|
|
|
2014-10-19 01:46:08 -05:00
|
|
|
// Keep track of the closest
|
|
|
|
// private module used when
|
|
|
|
// resolving this import chain.
|
|
|
|
if !used_proxy &&
|
|
|
|
!search_module.is_public {
|
|
|
|
match search_module.def_id
|
|
|
|
.get() {
|
|
|
|
Some(did) => {
|
|
|
|
closest_private =
|
|
|
|
LastMod(DependsOn(did));
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
}
|
2014-10-19 01:46:08 -05:00
|
|
|
None => {}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
}
|
2013-05-13 18:13:20 -05:00
|
|
|
}
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
// There are no type bindings at all.
|
2014-06-05 16:37:52 -05:00
|
|
|
let msg = format!("Not a module `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name));
|
2014-06-05 16:37:52 -05:00
|
|
|
return Failed(Some((span, msg)));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-29 14:08:40 -06:00
|
|
|
index += 1;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
return Success((search_module, closest_private));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
/// Attempts to resolve the module part of an import directive or path
|
|
|
|
/// rooted at the given module.
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
///
|
|
|
|
/// On success, returns the resolved module, and the closest *private*
|
|
|
|
/// module found to the destination when resolving this path.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_module_path(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: Rc<Module>,
|
2014-09-30 19:11:34 -05:00
|
|
|
module_path: &[Name],
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
use_lexical_scope: UseLexicalScopeFlag,
|
|
|
|
span: Span,
|
|
|
|
name_search_type: NameSearchType)
|
2014-04-14 03:30:59 -05:00
|
|
|
-> ResolveResult<(Rc<Module>, LastPrivate)> {
|
2013-03-01 12:44:43 -06:00
|
|
|
let module_path_len = module_path.len();
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(module_path_len > 0);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving module path for import) processing `{}` rooted at \
|
2013-09-28 00:38:08 -05:00
|
|
|
`{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.names_to_string(module_path),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module_));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
// Resolve the module prefix, if any.
|
2014-04-14 03:30:59 -05:00
|
|
|
let module_prefix_result = self.resolve_module_prefix(module_.clone(),
|
2012-12-23 16:41:37 -06:00
|
|
|
module_path);
|
2012-12-13 15:05:22 -06:00
|
|
|
|
2013-04-12 00:15:30 -05:00
|
|
|
let search_module;
|
|
|
|
let start_index;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let last_private;
|
2012-12-23 16:41:37 -06:00
|
|
|
match module_prefix_result {
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(None) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let mpath = self.names_to_string(module_path);
|
2014-06-05 16:37:52 -05:00
|
|
|
let mpath = mpath.as_slice();
|
|
|
|
match mpath.rfind(':') {
|
2013-05-14 18:49:04 -05:00
|
|
|
Some(idx) => {
|
2014-06-05 16:37:52 -05:00
|
|
|
let msg = format!("Could not find `{}` in `{}`",
|
|
|
|
// idx +- 1 to account for the
|
|
|
|
// colons on either side
|
|
|
|
mpath.slice_from(idx + 1),
|
|
|
|
mpath.slice_to(idx - 1));
|
|
|
|
return Failed(Some((span, msg)));
|
2013-05-14 18:49:04 -05:00
|
|
|
},
|
2014-06-05 16:37:52 -05:00
|
|
|
None => return Failed(None),
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => return Failed(err),
|
2012-08-03 21:59:04 -05:00
|
|
|
Indeterminate => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving module path for import) indeterminate; \
|
2012-08-22 19:24:52 -05:00
|
|
|
bailing");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Indeterminate;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-12-23 16:41:37 -06:00
|
|
|
Success(NoPrefixFound) => {
|
|
|
|
// There was no prefix, so we're considering the first element
|
|
|
|
// of the path. How we handle this depends on whether we were
|
|
|
|
// instructed to use lexical scope or not.
|
|
|
|
match use_lexical_scope {
|
|
|
|
DontUseLexicalScope => {
|
|
|
|
// This is a crate-relative path. We will start the
|
|
|
|
// resolution process at index zero.
|
|
|
|
search_module = self.graph_root.get_module();
|
|
|
|
start_index = 0;
|
2014-02-11 13:19:18 -06:00
|
|
|
last_private = LastMod(AllPublic);
|
2012-12-23 16:41:37 -06:00
|
|
|
}
|
|
|
|
UseLexicalScope => {
|
|
|
|
// This is not a crate-relative path. We resolve the
|
|
|
|
// first component of the path in the current lexical
|
|
|
|
// scope and then proceed to resolve below that.
|
2014-06-05 16:37:52 -05:00
|
|
|
match self.resolve_module_in_lexical_scope(
|
|
|
|
module_,
|
|
|
|
module_path[0]) {
|
|
|
|
Failed(err) => return Failed(err),
|
2012-12-23 16:41:37 -06:00
|
|
|
Indeterminate => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving module path for import) \
|
2012-12-23 16:41:37 -06:00
|
|
|
indeterminate; bailing");
|
|
|
|
return Indeterminate;
|
|
|
|
}
|
|
|
|
Success(containing_module) => {
|
|
|
|
search_module = containing_module;
|
|
|
|
start_index = 1;
|
2014-02-11 13:19:18 -06:00
|
|
|
last_private = LastMod(AllPublic);
|
2012-12-23 16:41:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
Success(PrefixFound(ref containing_module, index)) => {
|
|
|
|
search_module = containing_module.clone();
|
2012-12-23 16:41:37 -06:00
|
|
|
start_index = index;
|
2014-02-11 13:19:18 -06:00
|
|
|
last_private = LastMod(DependsOn(containing_module.def_id
|
|
|
|
.get()
|
|
|
|
.unwrap()));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
self.resolve_module_path_from_root(search_module,
|
|
|
|
module_path,
|
|
|
|
start_index,
|
|
|
|
span,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
name_search_type,
|
|
|
|
last_private)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
/// Invariant: This must only be called during main resolution, not during
|
|
|
|
/// import resolution.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_item_in_lexical_scope(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: Rc<Module>,
|
2014-09-30 19:11:34 -05:00
|
|
|
name: Name,
|
2014-05-16 17:44:14 -05:00
|
|
|
namespace: Namespace)
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
-> ResolveResult<(Target, bool)> {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item in lexical scope) resolving `{}` in \
|
2014-10-15 01:25:34 -05:00
|
|
|
namespace {} in `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name),
|
2012-05-22 12:54:12 -05:00
|
|
|
namespace,
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module_));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// The current module node is handled specially. First, check for
|
|
|
|
// its immediate children.
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&module_);
|
2013-12-21 17:32:44 -06:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
match module_.children.borrow().find(&name) {
|
2014-03-20 21:49:20 -05:00
|
|
|
Some(name_bindings)
|
|
|
|
if name_bindings.defined_in_namespace(namespace) => {
|
|
|
|
debug!("top name bindings succeeded");
|
2014-08-12 22:31:30 -05:00
|
|
|
return Success((Target::new(module_.clone(),
|
|
|
|
name_bindings.clone(),
|
|
|
|
false),
|
2014-03-20 21:49:20 -05:00
|
|
|
false));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-03-20 21:49:20 -05:00
|
|
|
Some(_) | None => { /* Not found; continue. */ }
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Now check for its import directives. We don't have to have resolved
|
|
|
|
// all its imports in the usual way; this is because chains of
|
|
|
|
// adjacent import statements are processed as though they mutated the
|
|
|
|
// current scope.
|
2014-09-30 19:11:34 -05:00
|
|
|
match module_.import_resolutions.borrow().find(&name) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Not found; continue.
|
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(import_resolution) => {
|
2012-08-06 14:34:08 -05:00
|
|
|
match (*import_resolution).target_for_namespace(namespace) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Not found; continue.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item in lexical scope) found \
|
2014-10-15 01:25:34 -05:00
|
|
|
import resolution, but not in namespace {}",
|
2012-08-22 19:24:52 -05:00
|
|
|
namespace);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(target) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item in lexical scope) using \
|
2013-02-25 13:10:42 -06:00
|
|
|
import resolution");
|
2014-09-11 12:14:43 -05:00
|
|
|
// track used imports and extern crates as well
|
2014-02-11 13:19:18 -06:00
|
|
|
self.used_imports.insert((import_resolution.id(namespace), namespace));
|
2014-09-11 12:14:43 -05:00
|
|
|
match target.target_module.def_id.get() {
|
|
|
|
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
|
|
|
|
_ => {}
|
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
return Success((target, false));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-26 21:53:33 -05:00
|
|
|
// Search for external modules.
|
|
|
|
if namespace == TypeNS {
|
2014-09-30 19:11:34 -05:00
|
|
|
match module_.external_module_children.borrow().find_copy(&name) {
|
2013-03-26 21:53:33 -05:00
|
|
|
None => {}
|
|
|
|
Some(module) => {
|
|
|
|
let name_bindings =
|
2014-04-14 03:30:59 -05:00
|
|
|
Rc::new(Resolver::create_name_bindings_from_module(module));
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("lower name bindings succeeded");
|
2014-08-12 22:31:30 -05:00
|
|
|
return Success((Target::new(module_,
|
|
|
|
name_bindings,
|
|
|
|
false),
|
|
|
|
false));
|
2013-03-26 21:53:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// Finally, proceed up the scope chain looking for parent modules.
|
2012-07-31 18:38:41 -05:00
|
|
|
let mut search_module = module_;
|
2012-05-22 12:54:12 -05:00
|
|
|
loop {
|
|
|
|
// Go to the next parent.
|
2014-04-14 03:30:59 -05:00
|
|
|
match search_module.parent_link.clone() {
|
2012-08-03 21:59:04 -05:00
|
|
|
NoParentLink => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// No more parents. This module was unresolved.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item in lexical scope) unresolved \
|
2012-08-22 19:24:52 -05:00
|
|
|
module");
|
2014-06-05 16:37:52 -05:00
|
|
|
return Failed(None);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-12-23 16:41:37 -06:00
|
|
|
ModuleParentLink(parent_module_node, _) => {
|
2014-05-16 17:44:14 -05:00
|
|
|
match search_module.kind.get() {
|
|
|
|
NormalModuleKind => {
|
|
|
|
// We stop the search here.
|
|
|
|
debug!("(resolving item in lexical \
|
|
|
|
scope) unresolved module: not \
|
|
|
|
searching through module \
|
|
|
|
parents");
|
2014-06-05 16:37:52 -05:00
|
|
|
return Failed(None);
|
2012-12-23 16:41:37 -06:00
|
|
|
}
|
2014-05-16 17:44:14 -05:00
|
|
|
TraitModuleKind |
|
|
|
|
ImplModuleKind |
|
2014-10-19 01:46:08 -05:00
|
|
|
EnumModuleKind |
|
2014-05-16 17:44:14 -05:00
|
|
|
AnonymousModuleKind => {
|
2014-04-14 03:30:59 -05:00
|
|
|
search_module = parent_module_node.upgrade().unwrap();
|
2012-12-23 16:41:37 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
BlockParentLink(ref parent_module_node, _) => {
|
|
|
|
search_module = parent_module_node.upgrade().unwrap();
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve the name in the parent module.
|
2014-04-14 03:30:59 -05:00
|
|
|
match self.resolve_name_in_module(search_module.clone(),
|
2014-09-30 19:11:34 -05:00
|
|
|
name,
|
2012-12-13 15:05:22 -06:00
|
|
|
namespace,
|
2014-04-08 16:31:25 -05:00
|
|
|
PathSearch,
|
|
|
|
true) {
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(Some((span, msg))) =>
|
|
|
|
self.resolve_error(span, format!("failed to resolve. {}",
|
|
|
|
msg)),
|
|
|
|
Failed(None) => (), // Continue up the search chain.
|
2012-08-03 21:59:04 -05:00
|
|
|
Indeterminate => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// We couldn't see through the higher scope because of an
|
|
|
|
// unresolved import higher up. Bail.
|
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item in lexical scope) indeterminate \
|
2012-08-22 19:24:52 -05:00
|
|
|
higher scope; bailing");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Indeterminate;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Success((target, used_reexport)) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// We found the module.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item in lexical scope) found name \
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
in module, done");
|
|
|
|
return Success((target, used_reexport));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
/// Resolves a module name in the current lexical scope.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_module_in_lexical_scope(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: Rc<Module>,
|
2014-09-30 19:11:34 -05:00
|
|
|
name: Name)
|
2014-04-14 03:30:59 -05:00
|
|
|
-> ResolveResult<Rc<Module>> {
|
2012-12-13 15:05:22 -06:00
|
|
|
// If this module is an anonymous module, resolve the item in the
|
|
|
|
// lexical scope. Otherwise, resolve the item from the crate root.
|
2012-12-23 16:41:37 -06:00
|
|
|
let resolve_result = self.resolve_item_in_lexical_scope(
|
2014-05-16 17:44:14 -05:00
|
|
|
module_, name, TypeNS);
|
2012-12-13 15:05:22 -06:00
|
|
|
match resolve_result {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Success((target, _)) => {
|
2013-12-21 16:20:57 -06:00
|
|
|
let bindings = &*target.bindings;
|
2014-03-28 12:29:55 -05:00
|
|
|
match *bindings.type_def.borrow() {
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref type_def) => {
|
2013-12-21 16:13:06 -06:00
|
|
|
match type_def.module_def {
|
2012-10-15 20:04:15 -05:00
|
|
|
None => {
|
2014-05-15 17:52:58 -05:00
|
|
|
debug!("!!! (resolving module in lexical \
|
2012-10-15 20:04:15 -05:00
|
|
|
scope) module wasn't actually a \
|
|
|
|
module!");
|
2014-06-05 16:37:52 -05:00
|
|
|
return Failed(None);
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(ref module_def) => {
|
|
|
|
return Success(module_def.clone());
|
2012-10-15 20:04:15 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
2014-05-15 17:52:58 -05:00
|
|
|
debug!("!!! (resolving module in lexical scope) module
|
2012-08-22 19:24:52 -05:00
|
|
|
wasn't actually a module!");
|
2014-06-05 16:37:52 -05:00
|
|
|
return Failed(None);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
Indeterminate => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving module in lexical scope) indeterminate; \
|
2012-08-22 19:24:52 -05:00
|
|
|
bailing");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Indeterminate;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => {
|
|
|
|
debug!("(resolving module in lexical scope) failed to resolve");
|
|
|
|
return Failed(err);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
/// Returns the nearest normal module parent of the given module.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn get_nearest_normal_module_parent(&mut self, module_: Rc<Module>)
|
|
|
|
-> Option<Rc<Module>> {
|
2012-12-23 16:41:37 -06:00
|
|
|
let mut module_ = module_;
|
|
|
|
loop {
|
2014-04-14 03:30:59 -05:00
|
|
|
match module_.parent_link.clone() {
|
2012-12-23 16:41:37 -06:00
|
|
|
NoParentLink => return None,
|
|
|
|
ModuleParentLink(new_module, _) |
|
|
|
|
BlockParentLink(new_module, _) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
let new_module = new_module.upgrade().unwrap();
|
2013-12-19 20:52:35 -06:00
|
|
|
match new_module.kind.get() {
|
2012-12-23 16:41:37 -06:00
|
|
|
NormalModuleKind => return Some(new_module),
|
|
|
|
TraitModuleKind |
|
2013-05-13 18:13:20 -05:00
|
|
|
ImplModuleKind |
|
2014-10-19 01:46:08 -05:00
|
|
|
EnumModuleKind |
|
2012-12-23 16:41:37 -06:00
|
|
|
AnonymousModuleKind => module_ = new_module,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
/// Returns the nearest normal module parent of the given module, or the
|
|
|
|
/// module itself if it is a normal module.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc<Module>)
|
|
|
|
-> Rc<Module> {
|
2013-12-19 20:52:35 -06:00
|
|
|
match module_.kind.get() {
|
2012-12-23 16:41:37 -06:00
|
|
|
NormalModuleKind => return module_,
|
2013-05-13 18:13:20 -05:00
|
|
|
TraitModuleKind |
|
|
|
|
ImplModuleKind |
|
2014-10-19 01:46:08 -05:00
|
|
|
EnumModuleKind |
|
2013-05-13 18:13:20 -05:00
|
|
|
AnonymousModuleKind => {
|
2014-04-14 03:30:59 -05:00
|
|
|
match self.get_nearest_normal_module_parent(module_.clone()) {
|
2012-12-23 16:41:37 -06:00
|
|
|
None => module_,
|
|
|
|
Some(new_module) => new_module
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-26 17:56:13 -05:00
|
|
|
/// Resolves a "module prefix". A module prefix is one or both of (a) `self::`;
|
2013-05-31 17:17:22 -05:00
|
|
|
/// (b) some chain of `super::`.
|
2013-06-26 17:56:13 -05:00
|
|
|
/// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_module_prefix(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: Rc<Module>,
|
2014-09-30 19:11:34 -05:00
|
|
|
module_path: &[Name])
|
2013-05-31 17:17:22 -05:00
|
|
|
-> ResolveResult<ModulePrefixResult> {
|
2012-12-23 16:41:37 -06:00
|
|
|
// Start at the current module if we see `self` or `super`, or at the
|
|
|
|
// top of the crate otherwise.
|
|
|
|
let mut containing_module;
|
|
|
|
let mut i;
|
2014-09-30 19:11:34 -05:00
|
|
|
let first_module_path_string = token::get_name(module_path[0]);
|
2014-01-31 15:48:49 -06:00
|
|
|
if "self" == first_module_path_string.get() {
|
2012-12-23 16:41:37 -06:00
|
|
|
containing_module =
|
|
|
|
self.get_nearest_normal_module_parent_or_self(module_);
|
|
|
|
i = 1;
|
2014-01-31 15:48:49 -06:00
|
|
|
} else if "super" == first_module_path_string.get() {
|
2012-12-23 16:41:37 -06:00
|
|
|
containing_module =
|
|
|
|
self.get_nearest_normal_module_parent_or_self(module_);
|
|
|
|
i = 0; // We'll handle `super` below.
|
|
|
|
} else {
|
|
|
|
return Success(NoPrefixFound);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now loop through all the `super`s we find.
|
2014-01-31 15:48:49 -06:00
|
|
|
while i < module_path.len() {
|
2014-09-30 19:11:34 -05:00
|
|
|
let string = token::get_name(module_path[i]);
|
2014-01-31 15:48:49 -06:00
|
|
|
if "super" != string.get() {
|
|
|
|
break
|
|
|
|
}
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving module prefix) resolving `super` at {}",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*containing_module));
|
2012-12-23 16:41:37 -06:00
|
|
|
match self.get_nearest_normal_module_parent(containing_module) {
|
2014-06-05 16:37:52 -05:00
|
|
|
None => return Failed(None),
|
2012-12-23 16:41:37 -06:00
|
|
|
Some(new_module) => {
|
|
|
|
containing_module = new_module;
|
|
|
|
i += 1;
|
2012-12-13 15:05:22 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving module prefix) finished resolving prefix at {}",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*containing_module));
|
2012-12-23 16:41:37 -06:00
|
|
|
|
|
|
|
return Success(PrefixFound(containing_module, i));
|
2012-12-13 15:05:22 -06:00
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
/// Attempts to resolve the supplied name in the given module for the
|
|
|
|
/// given namespace. If successful, returns the target corresponding to
|
|
|
|
/// the name.
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
///
|
|
|
|
/// The boolean returned on success is an indicator of whether this lookup
|
|
|
|
/// passed through a public re-export proxy.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_name_in_module(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: Rc<Module>,
|
2014-05-08 16:35:09 -05:00
|
|
|
name: Name,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
namespace: Namespace,
|
2014-04-08 16:31:25 -05:00
|
|
|
name_search_type: NameSearchType,
|
|
|
|
allow_private_imports: bool)
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
-> ResolveResult<(Target, bool)> {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving name in module) resolving `{}` in `{}`",
|
2014-05-08 16:35:09 -05:00
|
|
|
token::get_name(name).get(),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module_));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// First, check the direct children of the module.
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&module_);
|
2013-12-21 17:32:44 -06:00
|
|
|
|
2014-05-08 16:35:09 -05:00
|
|
|
match module_.children.borrow().find(&name) {
|
2014-03-20 21:49:20 -05:00
|
|
|
Some(name_bindings)
|
|
|
|
if name_bindings.defined_in_namespace(namespace) => {
|
|
|
|
debug!("(resolving name in module) found node as child");
|
2014-08-12 22:31:30 -05:00
|
|
|
return Success((Target::new(module_.clone(),
|
|
|
|
name_bindings.clone(),
|
|
|
|
false),
|
2014-03-20 21:49:20 -05:00
|
|
|
false));
|
|
|
|
}
|
|
|
|
Some(_) | None => {
|
|
|
|
// Continue.
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
// Next, check the module's imports if necessary.
|
|
|
|
|
|
|
|
// If this is a search of all imports, we should be done with glob
|
|
|
|
// resolution at this point.
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
if name_search_type == PathSearch {
|
2013-12-19 20:59:03 -06:00
|
|
|
assert_eq!(module_.glob_count.get(), 0);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
// Check the list of resolved imports.
|
2014-05-08 16:35:09 -05:00
|
|
|
match module_.import_resolutions.borrow().find(&name) {
|
2014-04-08 16:31:25 -05:00
|
|
|
Some(import_resolution) if allow_private_imports ||
|
2014-04-14 03:30:59 -05:00
|
|
|
import_resolution.is_public => {
|
2014-04-08 16:31:25 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
if import_resolution.is_public &&
|
|
|
|
import_resolution.outstanding_references != 0 {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving name in module) import \
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
unresolved; bailing out");
|
2012-08-01 19:30:05 -05:00
|
|
|
return Indeterminate;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-03-01 12:44:43 -06:00
|
|
|
match import_resolution.target_for_namespace(namespace) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving name in module) name found, \
|
2014-10-15 01:25:34 -05:00
|
|
|
but not in namespace {}",
|
2012-08-22 19:24:52 -05:00
|
|
|
namespace);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Some(target) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving name in module) resolved to \
|
2012-08-22 19:24:52 -05:00
|
|
|
import");
|
2014-09-11 12:14:43 -05:00
|
|
|
// track used imports and extern crates as well
|
2014-02-11 13:19:18 -06:00
|
|
|
self.used_imports.insert((import_resolution.id(namespace), namespace));
|
2014-09-11 12:14:43 -05:00
|
|
|
match target.target_module.def_id.get() {
|
|
|
|
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
|
|
|
|
_ => {}
|
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
return Success((target, true));
|
2013-03-01 12:44:43 -06:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2014-04-08 16:31:25 -05:00
|
|
|
Some(..) | None => {} // Continue.
|
2013-03-26 21:53:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, search through external children.
|
|
|
|
if namespace == TypeNS {
|
2014-05-08 16:35:09 -05:00
|
|
|
match module_.external_module_children.borrow().find_copy(&name) {
|
2013-03-26 21:53:33 -05:00
|
|
|
None => {}
|
|
|
|
Some(module) => {
|
|
|
|
let name_bindings =
|
2014-04-14 03:30:59 -05:00
|
|
|
Rc::new(Resolver::create_name_bindings_from_module(module));
|
2014-08-12 22:31:30 -05:00
|
|
|
return Success((Target::new(module_,
|
|
|
|
name_bindings,
|
|
|
|
false),
|
|
|
|
false));
|
2013-03-26 21:53:33 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We're out of luck.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving name in module) failed to resolve `{}`",
|
2014-05-08 16:35:09 -05:00
|
|
|
token::get_name(name).get());
|
2014-06-05 16:37:52 -05:00
|
|
|
return Failed(None);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
fn report_unresolved_imports(&mut self, module_: Rc<Module>) {
|
2013-12-19 21:01:02 -06:00
|
|
|
let index = module_.resolved_import_count.get();
|
2014-03-20 21:49:20 -05:00
|
|
|
let imports = module_.imports.borrow();
|
|
|
|
let import_count = imports.len();
|
2012-05-22 12:54:12 -05:00
|
|
|
if index != import_count {
|
2013-12-22 18:39:46 -06:00
|
|
|
let sn = self.session
|
2014-03-16 13:56:24 -05:00
|
|
|
.codemap()
|
2014-10-15 01:05:01 -05:00
|
|
|
.span_to_snippet((*imports)[index].span)
|
2013-12-22 18:39:46 -06:00
|
|
|
.unwrap();
|
2014-05-07 18:33:43 -05:00
|
|
|
if sn.as_slice().contains("::") {
|
2014-10-15 01:05:01 -05:00
|
|
|
self.resolve_error((*imports)[index].span,
|
2013-12-22 18:39:46 -06:00
|
|
|
"unresolved import");
|
2013-04-26 03:59:28 -05:00
|
|
|
} else {
|
2013-09-28 00:38:08 -05:00
|
|
|
let err = format!("unresolved import (maybe you meant `{}::*`?)",
|
2014-05-07 18:33:43 -05:00
|
|
|
sn.as_slice().slice(0, sn.len()));
|
2014-10-15 01:05:01 -05:00
|
|
|
self.resolve_error((*imports)[index].span, err.as_slice());
|
2013-04-26 03:59:28 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Descend into children and anonymous children.
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&module_);
|
2013-12-21 17:32:44 -06:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
for (_, child_node) in module_.children.borrow().iter() {
|
2014-03-20 21:49:20 -05:00
|
|
|
match child_node.get_module_if_available() {
|
|
|
|
None => {
|
|
|
|
// Continue.
|
|
|
|
}
|
|
|
|
Some(child_module) => {
|
|
|
|
self.report_unresolved_imports(child_module);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
for (_, module_) in module_.anonymous_children.borrow().iter() {
|
|
|
|
self.report_unresolved_imports(module_.clone());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Export recording
|
|
|
|
//
|
|
|
|
// This pass simply determines what all "export" keywords refer to and
|
|
|
|
// writes the results into the export map.
|
|
|
|
//
|
2013-02-14 20:37:25 -06:00
|
|
|
// FIXME #4953 This pass will be removed once exports change to per-item.
|
|
|
|
// Then this operation can simply be performed as part of item (or import)
|
2012-05-22 12:54:12 -05:00
|
|
|
// processing.
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn record_exports(&mut self) {
|
2013-02-04 16:02:01 -06:00
|
|
|
let root_module = self.graph_root.get_module();
|
2012-05-22 12:54:12 -05:00
|
|
|
self.record_exports_for_module_subtree(root_module);
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn record_exports_for_module_subtree(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: Rc<Module>) {
|
2014-02-05 15:15:24 -06:00
|
|
|
// If this isn't a local krate, then bail out. We don't need to record
|
2012-11-13 17:43:54 -06:00
|
|
|
// exports for nonlocal crates.
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-12-19 20:56:20 -06:00
|
|
|
match module_.def_id.get() {
|
2014-02-05 15:15:24 -06:00
|
|
|
Some(def_id) if def_id.krate == LOCAL_CRATE => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// OK. Continue.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(recording exports for module subtree) recording \
|
2013-09-28 00:38:08 -05:00
|
|
|
exports for local module `{}`",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module_));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Record exports for the root module.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(recording exports for module subtree) recording \
|
2013-09-28 00:38:08 -05:00
|
|
|
exports for root module `{}`",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module_));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(_) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Bail out.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(recording exports for module subtree) not recording \
|
2013-09-28 00:38:08 -05:00
|
|
|
exports for `{}`",
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*module_));
|
2012-08-01 19:30:05 -05:00
|
|
|
return;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
self.record_exports_for_module(&*module_);
|
|
|
|
self.populate_module_if_necessary(&module_);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
for (_, child_name_bindings) in module_.children.borrow().iter() {
|
2014-03-20 21:49:20 -05:00
|
|
|
match child_name_bindings.get_module_if_available() {
|
|
|
|
None => {
|
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
Some(child_module) => {
|
|
|
|
self.record_exports_for_module_subtree(child_module);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
for (_, child_module) in module_.anonymous_children.borrow().iter() {
|
|
|
|
self.record_exports_for_module_subtree(child_module.clone());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
fn record_exports_for_module(&mut self, module_: &Module) {
|
2014-03-04 12:02:49 -06:00
|
|
|
let mut exports2 = Vec::new();
|
2012-09-24 19:29:20 -05:00
|
|
|
|
2013-01-30 19:20:02 -06:00
|
|
|
self.add_exports_for_module(&mut exports2, module_);
|
2013-12-19 20:56:20 -06:00
|
|
|
match module_.def_id.get() {
|
2012-09-24 19:29:20 -05:00
|
|
|
Some(def_id) => {
|
2014-09-29 18:06:13 -05:00
|
|
|
self.export_map2.insert(def_id.node, exports2);
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(computing exports) writing exports for {} (some)",
|
2012-09-24 19:29:20 -05:00
|
|
|
def_id.node);
|
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn add_exports_of_namebindings(&mut self,
|
2014-03-04 12:02:49 -06:00
|
|
|
exports2: &mut Vec<Export2> ,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
name: Name,
|
2014-04-14 03:30:59 -05:00
|
|
|
namebindings: &NameBindings,
|
2014-01-24 05:46:19 -06:00
|
|
|
ns: Namespace) {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
match namebindings.def_for_namespace(ns) {
|
|
|
|
Some(d) => {
|
2014-02-13 23:07:09 -06:00
|
|
|
let name = token::get_name(name);
|
2014-10-15 01:25:34 -05:00
|
|
|
debug!("(computing exports) YES: export '{}' => {}",
|
2014-05-14 14:31:30 -05:00
|
|
|
name, d.def_id());
|
2012-11-15 18:59:43 -06:00
|
|
|
exports2.push(Export2 {
|
2014-05-25 05:17:19 -05:00
|
|
|
name: name.get().to_string(),
|
2014-05-14 14:31:30 -05:00
|
|
|
def_id: d.def_id()
|
2012-11-15 18:59:43 -06:00
|
|
|
});
|
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
d_opt => {
|
2014-10-15 01:25:34 -05:00
|
|
|
debug!("(computing exports) NO: {}", d_opt);
|
2012-09-24 19:29:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn add_exports_for_module(&mut self,
|
2014-03-04 12:02:49 -06:00
|
|
|
exports2: &mut Vec<Export2> ,
|
2014-04-14 03:30:59 -05:00
|
|
|
module_: &Module) {
|
2014-03-20 21:49:20 -05:00
|
|
|
for (name, importresolution) in module_.import_resolutions.borrow().iter() {
|
2014-04-14 03:30:59 -05:00
|
|
|
if !importresolution.is_public {
|
2013-12-21 17:15:54 -06:00
|
|
|
continue
|
|
|
|
}
|
2013-06-21 07:29:53 -05:00
|
|
|
let xs = [TypeNS, ValueNS];
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
for &ns in xs.iter() {
|
|
|
|
match importresolution.target_for_namespace(ns) {
|
2012-09-24 19:29:20 -05:00
|
|
|
Some(target) => {
|
2014-01-24 05:46:19 -06:00
|
|
|
debug!("(computing exports) maybe export '{}'",
|
2014-02-13 23:07:09 -06:00
|
|
|
token::get_name(*name));
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
self.add_exports_of_namebindings(exports2,
|
2013-06-26 17:56:13 -05:00
|
|
|
*name,
|
2014-04-14 03:30:59 -05:00
|
|
|
&*target.bindings,
|
2014-01-24 05:46:19 -06:00
|
|
|
ns)
|
2012-09-24 19:29:20 -05:00
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// AST resolution
|
|
|
|
//
|
2012-07-06 21:06:58 -05:00
|
|
|
// We maintain a list of value ribs and type ribs.
|
2012-05-22 12:54:12 -05:00
|
|
|
//
|
|
|
|
// Simultaneously, we keep track of the current position in the module
|
|
|
|
// graph in the `current_module` pointer. When we go to resolve a name in
|
|
|
|
// the value or type namespaces, we first look through all the ribs and
|
|
|
|
// then query the module graph. When we resolve a name in the module
|
|
|
|
// namespace, we can skip all the ribs (since nested modules are not
|
|
|
|
// allowed within blocks in Rust) and jump straight to the current module
|
|
|
|
// graph node.
|
|
|
|
//
|
|
|
|
// Named implementations are handled separately. When we find a method
|
|
|
|
// call, we consult the module node to find all of the implementations in
|
|
|
|
// scope. This information is lazily cached in the module node. We then
|
|
|
|
// generate a fake "implementation scope" containing all the
|
|
|
|
// implementations thus found, for compatibility with old resolve pass.
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn with_scope(&mut self, name: Option<Name>, f: |&mut Resolver|) {
|
2014-04-14 03:30:59 -05:00
|
|
|
let orig_module = self.current_module.clone();
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Move down in the graph.
|
2012-08-06 14:34:08 -05:00
|
|
|
match name {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-07-11 17:00:40 -05:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(name) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&orig_module);
|
2013-12-21 17:32:44 -06:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
match orig_module.children.borrow().find(&name) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("!!! (with scope) didn't find `{}` in `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*orig_module));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(name_bindings) => {
|
2012-08-06 14:34:08 -05:00
|
|
|
match (*name_bindings).get_module_if_available() {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("!!! (with scope) didn't find module \
|
2013-09-28 00:38:08 -05:00
|
|
|
for `{}` in `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name),
|
2014-06-21 05:39:03 -05:00
|
|
|
self.module_to_string(&*orig_module));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(module_) => {
|
2012-07-31 18:38:41 -05:00
|
|
|
self.current_module = module_;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-26 21:10:16 -05:00
|
|
|
f(self);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
self.current_module = orig_module;
|
|
|
|
}
|
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
/// Wraps the given definition in the appropriate number of `DefUpvar`
|
2013-05-31 17:17:22 -05:00
|
|
|
/// wrappers.
|
2014-04-22 11:06:43 -05:00
|
|
|
fn upvarify(&self,
|
2014-04-14 03:30:59 -05:00
|
|
|
ribs: &[Rib],
|
2014-04-22 11:06:43 -05:00
|
|
|
def_like: DefLike,
|
|
|
|
span: Span)
|
|
|
|
-> Option<DefLike> {
|
2012-08-06 14:34:08 -05:00
|
|
|
match def_like {
|
2014-09-17 21:45:21 -05:00
|
|
|
DlDef(d @ DefUpvar(..)) => {
|
|
|
|
self.session.span_bug(span,
|
|
|
|
format!("unexpected {} in bindings", d).as_slice())
|
|
|
|
}
|
|
|
|
DlDef(d @ DefLocal(_)) => {
|
|
|
|
let node_id = d.def_id().node;
|
|
|
|
let mut def = d;
|
|
|
|
let mut last_proc_body_id = ast::DUMMY_NODE_ID;
|
|
|
|
for rib in ribs.iter() {
|
|
|
|
match rib.kind {
|
|
|
|
NormalRibKind => {
|
|
|
|
// Nothing to do. Continue.
|
|
|
|
}
|
|
|
|
ClosureRibKind(function_id, maybe_proc_body) => {
|
|
|
|
let prev_def = def;
|
|
|
|
if maybe_proc_body != ast::DUMMY_NODE_ID {
|
|
|
|
last_proc_body_id = maybe_proc_body;
|
|
|
|
}
|
2014-09-14 17:22:50 -05:00
|
|
|
def = DefUpvar(node_id, function_id, last_proc_body_id);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
let mut seen = self.freevars_seen.borrow_mut();
|
2014-10-15 01:05:01 -05:00
|
|
|
let seen = match seen.entry(function_id) {
|
|
|
|
Occupied(v) => v.into_mut(),
|
|
|
|
Vacant(v) => v.set(NodeSet::new()),
|
|
|
|
};
|
2014-09-17 21:45:21 -05:00
|
|
|
if seen.contains(&node_id) {
|
|
|
|
continue;
|
|
|
|
}
|
2014-10-15 01:05:01 -05:00
|
|
|
match self.freevars.borrow_mut().entry(function_id) {
|
|
|
|
Occupied(v) => v.into_mut(),
|
|
|
|
Vacant(v) => v.set(vec![]),
|
|
|
|
}.push(Freevar { def: prev_def, span: span });
|
2014-09-17 21:45:21 -05:00
|
|
|
seen.insert(node_id);
|
|
|
|
}
|
|
|
|
MethodRibKind(item_id, _) => {
|
|
|
|
// If the def is a ty param, and came from the parent
|
|
|
|
// item, it's ok
|
|
|
|
match def {
|
|
|
|
DefTyParam(_, did, _) if {
|
|
|
|
self.def_map.borrow().find_copy(&did.node)
|
|
|
|
== Some(DefTyParamBinder(item_id))
|
|
|
|
} => {} // ok
|
|
|
|
DefSelfTy(did) if did == item_id => {} // ok
|
|
|
|
_ => {
|
|
|
|
// This was an attempt to access an upvar inside a
|
|
|
|
// named function item. This is not allowed, so we
|
|
|
|
// report an error.
|
2014-05-31 00:54:04 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
self.resolve_error(
|
|
|
|
span,
|
|
|
|
"can't capture dynamic environment in a fn item; \
|
|
|
|
use the || { ... } closure form instead");
|
2014-05-31 00:54:04 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ItemRibKind => {
|
|
|
|
// This was an attempt to access an upvar inside a
|
|
|
|
// named function item. This is not allowed, so we
|
|
|
|
// report an error.
|
2012-07-26 16:04:03 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
self.resolve_error(
|
|
|
|
span,
|
|
|
|
"can't capture dynamic environment in a fn item; \
|
|
|
|
use the || { ... } closure form instead");
|
2012-07-26 16:04:03 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
ConstantItemRibKind => {
|
|
|
|
// Still doesn't deal with upvars
|
|
|
|
self.resolve_error(span,
|
|
|
|
"attempt to use a non-constant \
|
|
|
|
value in a constant");
|
2012-07-26 16:04:03 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
}
|
2012-07-26 16:04:03 -05:00
|
|
|
}
|
|
|
|
}
|
2014-09-17 21:45:21 -05:00
|
|
|
Some(DlDef(def))
|
|
|
|
}
|
|
|
|
DlDef(def @ DefTyParam(..)) |
|
|
|
|
DlDef(def @ DefSelfTy(..)) => {
|
|
|
|
for rib in ribs.iter() {
|
|
|
|
match rib.kind {
|
|
|
|
NormalRibKind | ClosureRibKind(..) => {
|
|
|
|
// Nothing to do. Continue.
|
|
|
|
}
|
|
|
|
MethodRibKind(item_id, _) => {
|
|
|
|
// If the def is a ty param, and came from the parent
|
|
|
|
// item, it's ok
|
|
|
|
match def {
|
|
|
|
DefTyParam(_, did, _) if {
|
|
|
|
self.def_map.borrow().find_copy(&did.node)
|
|
|
|
== Some(DefTyParamBinder(item_id))
|
|
|
|
} => {} // ok
|
|
|
|
DefSelfTy(did) if did == item_id => {} // ok
|
2012-07-06 21:06:58 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
_ => {
|
|
|
|
// This was an attempt to use a type parameter outside
|
|
|
|
// its scope.
|
2012-07-06 21:06:58 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
self.resolve_error(span,
|
|
|
|
"can't use type parameters from \
|
|
|
|
outer function; try using a local \
|
|
|
|
type parameter instead");
|
2012-07-06 21:06:58 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ItemRibKind => {
|
|
|
|
// This was an attempt to use a type parameter outside
|
|
|
|
// its scope.
|
2012-10-15 14:27:09 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
self.resolve_error(span,
|
|
|
|
"can't use type parameters from \
|
|
|
|
outer function; try using a local \
|
|
|
|
type parameter instead");
|
|
|
|
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
ConstantItemRibKind => {
|
|
|
|
// see #9186
|
|
|
|
self.resolve_error(span,
|
|
|
|
"cannot use an outer type \
|
|
|
|
parameter in this context");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2012-10-15 14:27:09 -05:00
|
|
|
}
|
2014-09-17 21:45:21 -05:00
|
|
|
Some(DlDef(def))
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-09-17 21:45:21 -05:00
|
|
|
_ => Some(def_like)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-22 11:06:43 -05:00
|
|
|
fn search_ribs(&self,
|
2014-04-14 03:30:59 -05:00
|
|
|
ribs: &[Rib],
|
2014-04-22 11:06:43 -05:00
|
|
|
name: Name,
|
|
|
|
span: Span)
|
|
|
|
-> Option<DefLike> {
|
2013-02-14 20:37:25 -06:00
|
|
|
// FIXME #4950: Try caching?
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
for (i, rib) in ribs.iter().enumerate().rev() {
|
2014-09-29 18:06:13 -05:00
|
|
|
match rib.bindings.find_copy(&name) {
|
2013-12-21 15:58:11 -06:00
|
|
|
Some(def_like) => {
|
2014-09-24 06:41:09 -05:00
|
|
|
return self.upvarify(ribs[i + 1..], def_like, span);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Continue.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-17 21:45:21 -05:00
|
|
|
None
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-02-05 15:15:24 -06:00
|
|
|
fn resolve_crate(&mut self, krate: &ast::Crate) {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving crate) starting");
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_crate(self, krate);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
fn resolve_item(&mut self, item: &Item) {
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = item.ident.name;
|
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item) resolving {}",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-03-20 00:17:42 -05:00
|
|
|
match item.node {
|
2012-10-15 14:27:09 -05:00
|
|
|
|
|
|
|
// enum item: resolve all the variants' discrs,
|
|
|
|
// then resolve the ty params
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemEnum(ref enum_def, ref generics) => {
|
2013-08-03 11:45:23 -05:00
|
|
|
for variant in (*enum_def).variants.iter() {
|
|
|
|
for dis_expr in variant.node.disr_expr.iter() {
|
2012-10-15 14:27:09 -05:00
|
|
|
// resolve the discriminator expr
|
|
|
|
// as a constant
|
2013-09-26 21:10:16 -05:00
|
|
|
self.with_constant_rib(|this| {
|
2014-05-16 12:15:33 -05:00
|
|
|
this.resolve_expr(&**dis_expr);
|
2012-10-15 14:27:09 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-20 23:49:39 -05:00
|
|
|
// n.b. the discr expr gets visited twice.
|
2012-10-15 14:27:09 -05:00
|
|
|
// but maybe it's okay since the first time will signal an
|
|
|
|
// error if there is one? -- tjc
|
2013-11-21 17:42:55 -06:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
2014-05-31 17:53:13 -05:00
|
|
|
TypeSpace,
|
2013-11-21 17:42:55 -06:00
|
|
|
item.id,
|
2014-05-31 00:54:04 -05:00
|
|
|
ItemRibKind),
|
2013-11-21 17:42:55 -06:00
|
|
|
|this| {
|
2014-07-07 21:26:02 -05:00
|
|
|
this.resolve_type_parameters(&generics.ty_params);
|
2014-08-11 11:32:26 -05:00
|
|
|
this.resolve_where_clause(&generics.where_clause);
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_item(this, item);
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-10-15 14:27:09 -05:00
|
|
|
}
|
2012-10-15 15:14:23 -05:00
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemTy(_, ref generics) => {
|
2013-11-21 17:42:55 -06:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
2014-05-31 17:53:13 -05:00
|
|
|
TypeSpace,
|
2013-11-21 17:42:55 -06:00
|
|
|
item.id,
|
2014-05-31 00:54:04 -05:00
|
|
|
ItemRibKind),
|
2013-11-21 17:42:55 -06:00
|
|
|
|this| {
|
2014-09-09 01:22:20 -05:00
|
|
|
this.resolve_type_parameters(&generics.ty_params);
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_item(this, item);
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemImpl(ref generics,
|
2014-05-16 12:15:33 -05:00
|
|
|
ref implemented_traits,
|
|
|
|
ref self_type,
|
2014-08-04 15:56:56 -05:00
|
|
|
ref impl_items) => {
|
2012-10-22 19:57:10 -05:00
|
|
|
self.resolve_implementation(item.id,
|
2013-02-14 23:50:03 -06:00
|
|
|
generics,
|
2012-07-18 18:28:31 -05:00
|
|
|
implemented_traits,
|
2014-05-16 12:15:33 -05:00
|
|
|
&**self_type,
|
2014-08-04 15:56:56 -05:00
|
|
|
impl_items.as_slice());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Create a new rib for the self type.
|
2014-09-29 18:06:13 -05:00
|
|
|
let mut self_type_rib = Rib::new(ItemRibKind);
|
2014-05-31 00:54:04 -05:00
|
|
|
|
2014-07-06 18:02:48 -05:00
|
|
|
// plain insert (no renaming, types are not currently hygienic....)
|
|
|
|
let name = self.type_self_name;
|
2014-09-29 18:06:13 -05:00
|
|
|
self_type_rib.bindings.insert(name, DlDef(DefSelfTy(item.id)));
|
|
|
|
self.type_ribs.push(self_type_rib);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-07-31 12:27:51 -05:00
|
|
|
// Create a new rib for the trait-wide type parameters.
|
2013-11-21 17:42:55 -06:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
2014-05-31 17:53:13 -05:00
|
|
|
TypeSpace,
|
2013-11-21 17:42:55 -06:00
|
|
|
item.id,
|
|
|
|
NormalRibKind),
|
|
|
|
|this| {
|
2013-09-26 21:10:16 -05:00
|
|
|
this.resolve_type_parameters(&generics.ty_params);
|
2014-08-11 11:32:26 -05:00
|
|
|
this.resolve_where_clause(&generics.where_clause);
|
2012-07-12 20:04:40 -05:00
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
this.resolve_type_parameter_bounds(item.id, bounds,
|
|
|
|
TraitDerivation);
|
|
|
|
|
2014-07-07 21:26:02 -05:00
|
|
|
match unbound {
|
|
|
|
&Some(ast::TraitTyParamBound(ref tpb)) => {
|
|
|
|
this.resolve_trait_reference(item.id, tpb, TraitDerivation);
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2012-08-03 17:02:01 -05:00
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for method in (*methods).iter() {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Create a new rib for the method-specific type
|
|
|
|
// parameters.
|
|
|
|
//
|
2013-02-14 20:37:25 -06:00
|
|
|
// FIXME #4951: Do we need a node ID here?
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-09-19 18:55:01 -05:00
|
|
|
match *method {
|
2014-08-04 15:56:56 -05:00
|
|
|
ast::RequiredMethod(ref ty_m) => {
|
2013-11-21 17:42:55 -06:00
|
|
|
this.with_type_parameter_rib
|
2013-02-14 23:50:03 -06:00
|
|
|
(HasTypeParameters(&ty_m.generics,
|
2014-05-31 17:53:13 -05:00
|
|
|
FnSpace,
|
2012-05-22 12:54:12 -05:00
|
|
|
item.id,
|
2014-08-04 15:56:56 -05:00
|
|
|
MethodRibKind(item.id, RequiredMethod)),
|
2013-11-21 17:42:55 -06:00
|
|
|
|this| {
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-07-10 15:44:20 -05:00
|
|
|
// Resolve the method-specific type
|
|
|
|
// parameters.
|
2013-09-26 21:10:16 -05:00
|
|
|
this.resolve_type_parameters(
|
|
|
|
&ty_m.generics.ty_params);
|
2014-08-11 11:32:26 -05:00
|
|
|
this.resolve_where_clause(&ty_m.generics
|
|
|
|
.where_clause);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for argument in ty_m.decl.inputs.iter() {
|
2014-05-16 12:15:33 -05:00
|
|
|
this.resolve_type(&*argument.ty);
|
2012-07-10 15:44:20 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-05-06 18:37:32 -05:00
|
|
|
match ty_m.explicit_self.node {
|
|
|
|
SelfExplicit(ref typ, _) => {
|
2014-07-07 18:35:15 -05:00
|
|
|
this.resolve_type(&**typ)
|
2014-05-06 18:37:32 -05:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2014-05-16 12:15:33 -05:00
|
|
|
this.resolve_type(&*ty_m.decl.output);
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-07-10 15:44:20 -05:00
|
|
|
}
|
2014-08-04 15:56:56 -05:00
|
|
|
ast::ProvidedMethod(ref m) => {
|
2013-09-26 21:10:16 -05:00
|
|
|
this.resolve_method(MethodRibKind(item.id,
|
2014-08-04 15:56:56 -05:00
|
|
|
ProvidedMethod(m.id)),
|
2014-05-31 17:53:13 -05:00
|
|
|
&**m)
|
2012-07-10 15:44:20 -05:00
|
|
|
}
|
2014-08-05 21:44:21 -05:00
|
|
|
ast::TypeTraitItem(_) => {
|
|
|
|
visit::walk_trait_item(this, method);
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
self.type_ribs.pop();
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemStruct(ref struct_def, ref generics) => {
|
2012-12-10 15:47:54 -06:00
|
|
|
self.resolve_struct(item.id,
|
2013-02-14 23:50:03 -06:00
|
|
|
generics,
|
2014-02-28 17:25:15 -06:00
|
|
|
struct_def.fields.as_slice());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemMod(ref module_) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
self.with_scope(Some(name), |this| {
|
|
|
|
this.resolve_module(module_, item.span, name,
|
2013-09-26 21:10:16 -05:00
|
|
|
item.id);
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
ItemForeignMod(ref foreign_module) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
self.with_scope(Some(name), |this| {
|
2013-08-03 11:45:23 -05:00
|
|
|
for foreign_item in foreign_module.items.iter() {
|
2013-02-14 23:50:03 -06:00
|
|
|
match foreign_item.node {
|
2014-01-09 07:05:33 -06:00
|
|
|
ForeignItemFn(_, ref generics) => {
|
2013-09-26 21:10:16 -05:00
|
|
|
this.with_type_parameter_rib(
|
2013-02-14 23:50:03 -06:00
|
|
|
HasTypeParameters(
|
2014-05-31 17:53:13 -05:00
|
|
|
generics, FnSpace, foreign_item.id,
|
2014-05-31 00:54:04 -05:00
|
|
|
ItemRibKind),
|
2013-09-26 21:10:16 -05:00
|
|
|
|this| visit::walk_foreign_item(this,
|
2014-09-12 05:10:30 -05:00
|
|
|
&**foreign_item));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-01-09 07:05:33 -06:00
|
|
|
ForeignItemStatic(..) => {
|
2013-09-26 21:10:16 -05:00
|
|
|
visit::walk_foreign_item(this,
|
2014-09-12 05:10:30 -05:00
|
|
|
&**foreign_item);
|
2012-08-25 17:09:33 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-09-07 12:09:06 -05:00
|
|
|
ItemFn(ref fn_decl, _, _, ref generics, ref block) => {
|
2014-05-31 00:54:04 -05:00
|
|
|
self.resolve_function(ItemRibKind,
|
2014-09-07 12:09:06 -05:00
|
|
|
Some(&**fn_decl),
|
2012-07-06 21:06:58 -05:00
|
|
|
HasTypeParameters
|
2013-02-14 23:50:03 -06:00
|
|
|
(generics,
|
2014-05-31 17:53:13 -05:00
|
|
|
FnSpace,
|
2012-07-06 21:06:58 -05:00
|
|
|
item.id,
|
2014-05-31 00:54:04 -05:00
|
|
|
ItemRibKind),
|
2014-09-07 12:09:06 -05:00
|
|
|
&**block);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 10:17:01 -05:00
|
|
|
ItemConst(..) | ItemStatic(..) => {
|
2013-09-26 21:10:16 -05:00
|
|
|
self.with_constant_rib(|this| {
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_item(this, item);
|
2012-10-15 14:27:09 -05:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-07-05 14:10:33 -05:00
|
|
|
|
2013-12-25 12:10:33 -06:00
|
|
|
ItemMac(..) => {
|
|
|
|
// do nothing, these are just around to be encoded
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn with_type_parameter_rib(&mut self,
|
2013-11-19 15:22:03 -06:00
|
|
|
type_parameters: TypeParameters,
|
|
|
|
f: |&mut Resolver|) {
|
2012-08-06 14:34:08 -05:00
|
|
|
match type_parameters {
|
2014-10-08 23:28:50 -05:00
|
|
|
HasTypeParameters(generics, space, node_id, rib_kind) => {
|
2014-09-29 18:06:13 -05:00
|
|
|
let mut function_type_rib = Rib::new(rib_kind);
|
2014-10-08 23:28:50 -05:00
|
|
|
let mut seen_bindings = HashSet::new();
|
2013-08-03 11:45:23 -05:00
|
|
|
for (index, type_parameter) in generics.ty_params.iter().enumerate() {
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = type_parameter.ident.name;
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("with_type_parameter_rib: {} {}", node_id,
|
2012-08-22 19:24:52 -05:00
|
|
|
type_parameter.id);
|
2014-10-08 23:28:50 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
if seen_bindings.contains(&name) {
|
2014-10-08 23:28:50 -05:00
|
|
|
self.resolve_error(type_parameter.span,
|
|
|
|
format!("the name `{}` is already \
|
|
|
|
used for a type \
|
|
|
|
parameter in this type \
|
|
|
|
parameter list",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(
|
|
|
|
name)).as_slice())
|
2014-10-08 23:28:50 -05:00
|
|
|
}
|
2014-09-30 19:11:34 -05:00
|
|
|
seen_bindings.insert(name);
|
2014-10-08 23:28:50 -05:00
|
|
|
|
2014-05-31 17:53:13 -05:00
|
|
|
let def_like = DlDef(DefTyParam(space,
|
|
|
|
local_def(type_parameter.id),
|
|
|
|
index));
|
2012-07-26 16:04:03 -05:00
|
|
|
// Associate this type parameter with
|
|
|
|
// the item that bound it
|
|
|
|
self.record_def(type_parameter.id,
|
2014-02-11 13:19:18 -06:00
|
|
|
(DefTyParamBinder(node_id), LastMod(AllPublic)));
|
2013-06-26 17:56:13 -05:00
|
|
|
// plain insert (no renaming)
|
2014-09-30 19:11:34 -05:00
|
|
|
function_type_rib.bindings.insert(name, def_like);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-09-29 18:06:13 -05:00
|
|
|
self.type_ribs.push(function_type_rib);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:04 -05:00
|
|
|
NoTypeParameters => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-26 21:10:16 -05:00
|
|
|
f(self);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
match type_parameters {
|
2014-09-29 18:06:13 -05:00
|
|
|
HasTypeParameters(..) => { self.type_ribs.pop(); }
|
2014-03-20 21:49:20 -05:00
|
|
|
NoTypeParameters => { }
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-19 15:22:03 -06:00
|
|
|
fn with_label_rib(&mut self, f: |&mut Resolver|) {
|
2014-09-29 18:06:13 -05:00
|
|
|
self.label_ribs.push(Rib::new(NormalRibKind));
|
2013-09-26 21:10:16 -05:00
|
|
|
f(self);
|
2014-09-29 18:06:13 -05:00
|
|
|
self.label_ribs.pop();
|
2012-08-14 21:20:56 -05:00
|
|
|
}
|
2013-02-21 13:08:50 -06:00
|
|
|
|
2013-11-19 15:22:03 -06:00
|
|
|
fn with_constant_rib(&mut self, f: |&mut Resolver|) {
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.push(Rib::new(ConstantItemRibKind));
|
|
|
|
self.type_ribs.push(Rib::new(ConstantItemRibKind));
|
2013-09-26 21:10:16 -05:00
|
|
|
f(self);
|
2014-09-29 18:06:13 -05:00
|
|
|
self.type_ribs.pop();
|
|
|
|
self.value_ribs.pop();
|
2012-10-15 14:27:09 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_function(&mut self,
|
2014-01-27 06:18:36 -06:00
|
|
|
rib_kind: RibKind,
|
2014-09-07 12:09:06 -05:00
|
|
|
optional_declaration: Option<&FnDecl>,
|
2014-01-27 06:18:36 -06:00
|
|
|
type_parameters: TypeParameters,
|
2014-09-07 12:09:06 -05:00
|
|
|
block: &Block) {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Create a value rib for the function.
|
2014-04-14 03:30:59 -05:00
|
|
|
let function_value_rib = Rib::new(rib_kind);
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.push(function_value_rib);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-08-14 21:20:56 -05:00
|
|
|
// Create a label rib for the function.
|
2014-04-14 03:30:59 -05:00
|
|
|
let function_label_rib = Rib::new(rib_kind);
|
2014-09-29 18:06:13 -05:00
|
|
|
self.label_ribs.push(function_label_rib);
|
2012-08-14 21:20:56 -05:00
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// If this function has type parameters, add them now.
|
2013-11-21 17:42:55 -06:00
|
|
|
self.with_type_parameter_rib(type_parameters, |this| {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Resolve the type parameters.
|
2012-08-06 14:34:08 -05:00
|
|
|
match type_parameters {
|
2012-08-03 21:59:04 -05:00
|
|
|
NoTypeParameters => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Continue.
|
|
|
|
}
|
2013-02-14 23:50:03 -06:00
|
|
|
HasTypeParameters(ref generics, _, _, _) => {
|
2013-09-26 21:10:16 -05:00
|
|
|
this.resolve_type_parameters(&generics.ty_params);
|
2014-08-11 11:32:26 -05:00
|
|
|
this.resolve_where_clause(&generics.where_clause);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add each argument to the rib.
|
2012-08-06 14:34:08 -05:00
|
|
|
match optional_declaration {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(declaration) => {
|
2014-10-08 23:28:50 -05:00
|
|
|
let mut bindings_list = HashMap::new();
|
2013-08-03 11:45:23 -05:00
|
|
|
for argument in declaration.inputs.iter() {
|
2014-05-16 12:15:33 -05:00
|
|
|
this.resolve_pattern(&*argument.pat,
|
2014-04-02 19:38:45 -05:00
|
|
|
ArgumentIrrefutableMode,
|
2014-06-10 16:39:10 -05:00
|
|
|
&mut bindings_list);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-05-16 12:15:33 -05:00
|
|
|
this.resolve_type(&*argument.ty);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving function) recorded argument");
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-05-16 12:15:33 -05:00
|
|
|
this.resolve_type(&*declaration.output);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve the function body.
|
2014-05-16 12:15:33 -05:00
|
|
|
this.resolve_block(&*block);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving function) leaving function");
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
self.label_ribs.pop();
|
|
|
|
self.value_ribs.pop();
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_type_parameters(&mut self,
|
2014-07-07 21:26:02 -05:00
|
|
|
type_parameters: &OwnedSlice<TyParam>) {
|
2013-08-03 11:45:23 -05:00
|
|
|
for type_parameter in type_parameters.iter() {
|
|
|
|
for bound in type_parameter.bounds.iter() {
|
2014-08-27 20:46:52 -05:00
|
|
|
self.resolve_type_parameter_bound(type_parameter.id, bound,
|
|
|
|
TraitBoundingTypeParameter);
|
2013-05-10 14:57:27 -05:00
|
|
|
}
|
2014-07-07 21:26:02 -05:00
|
|
|
match &type_parameter.unbound {
|
2014-08-27 20:46:52 -05:00
|
|
|
&Some(ref unbound) =>
|
|
|
|
self.resolve_type_parameter_bound(
|
|
|
|
type_parameter.id, unbound, TraitBoundingTypeParameter),
|
2014-07-07 21:26:02 -05:00
|
|
|
&None => {}
|
|
|
|
}
|
2014-01-30 11:28:02 -06:00
|
|
|
match type_parameter.default {
|
2014-05-16 12:15:33 -05:00
|
|
|
Some(ref ty) => self.resolve_type(&**ty),
|
2014-01-30 11:28:02 -06:00
|
|
|
None => {}
|
|
|
|
}
|
2013-05-10 14:57:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-27 20:46:52 -05:00
|
|
|
fn resolve_type_parameter_bounds(&mut self,
|
|
|
|
id: NodeId,
|
|
|
|
type_parameter_bounds: &OwnedSlice<TyParamBound>,
|
|
|
|
reference_type: TraitReferenceType) {
|
|
|
|
for type_parameter_bound in type_parameter_bounds.iter() {
|
|
|
|
self.resolve_type_parameter_bound(id, type_parameter_bound,
|
|
|
|
reference_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_type_parameter_bound(&mut self,
|
2014-06-01 20:41:46 -05:00
|
|
|
id: NodeId,
|
2014-08-27 20:46:52 -05:00
|
|
|
type_parameter_bound: &TyParamBound,
|
|
|
|
reference_type: TraitReferenceType) {
|
2013-05-10 14:57:27 -05:00
|
|
|
match *type_parameter_bound {
|
2013-07-05 19:47:42 -05:00
|
|
|
TraitTyParamBound(ref tref) => {
|
2014-08-27 20:46:52 -05:00
|
|
|
self.resolve_trait_reference(id, tref, reference_type)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-06-01 20:41:46 -05:00
|
|
|
UnboxedFnTyParamBound(ref unboxed_function) => {
|
2014-09-05 23:27:47 -05:00
|
|
|
match self.resolve_path(unboxed_function.ref_id,
|
|
|
|
&unboxed_function.path,
|
|
|
|
TypeNS,
|
|
|
|
true) {
|
|
|
|
None => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let path_str = self.path_names_to_string(
|
2014-09-05 23:27:47 -05:00
|
|
|
&unboxed_function.path);
|
|
|
|
self.resolve_error(unboxed_function.path.span,
|
|
|
|
format!("unresolved trait `{}`",
|
|
|
|
path_str).as_slice())
|
|
|
|
}
|
|
|
|
Some(def) => {
|
|
|
|
match def {
|
|
|
|
(DefTrait(_), _) => {
|
|
|
|
self.record_def(unboxed_function.ref_id, def);
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let msg =
|
|
|
|
format!("`{}` is not a trait",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.path_names_to_string(
|
2014-09-05 23:27:47 -05:00
|
|
|
&unboxed_function.path));
|
|
|
|
self.resolve_error(unboxed_function.path.span,
|
|
|
|
msg.as_slice());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-01 20:41:46 -05:00
|
|
|
for argument in unboxed_function.decl.inputs.iter() {
|
2014-05-16 12:15:33 -05:00
|
|
|
self.resolve_type(&*argument.ty);
|
2014-06-01 20:41:46 -05:00
|
|
|
}
|
|
|
|
|
2014-05-16 12:15:33 -05:00
|
|
|
self.resolve_type(&*unboxed_function.decl.output);
|
2014-06-01 20:41:46 -05:00
|
|
|
}
|
2014-08-27 20:46:52 -05:00
|
|
|
RegionTyParamBound(..) => {}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_trait_reference(&mut self,
|
2014-07-07 21:26:02 -05:00
|
|
|
id: NodeId,
|
|
|
|
trait_reference: &TraitRef,
|
|
|
|
reference_type: TraitReferenceType) {
|
2013-09-26 21:10:16 -05:00
|
|
|
match self.resolve_path(id, &trait_reference.path, TypeNS, true) {
|
2013-03-27 05:16:28 -05:00
|
|
|
None => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let path_str = self.path_names_to_string(&trait_reference.path);
|
2013-07-03 16:16:08 -05:00
|
|
|
let usage_str = match reference_type {
|
2013-07-03 17:43:03 -05:00
|
|
|
TraitBoundingTypeParameter => "bound type parameter with",
|
2013-07-03 16:16:08 -05:00
|
|
|
TraitImplementation => "implement",
|
2014-08-27 20:46:52 -05:00
|
|
|
TraitDerivation => "derive",
|
2013-07-03 16:16:08 -05:00
|
|
|
};
|
|
|
|
|
2013-09-28 00:38:08 -05:00
|
|
|
let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
|
2014-05-16 12:45:16 -05:00
|
|
|
self.resolve_error(trait_reference.path.span, msg.as_slice());
|
2013-03-27 05:16:28 -05:00
|
|
|
}
|
|
|
|
Some(def) => {
|
2014-06-19 17:23:51 -05:00
|
|
|
match def {
|
|
|
|
(DefTrait(_), _) => {
|
2014-10-15 01:25:34 -05:00
|
|
|
debug!("(resolving trait) found trait def: {}", def);
|
2014-06-19 17:23:51 -05:00
|
|
|
self.record_def(trait_reference.ref_id, def);
|
|
|
|
}
|
|
|
|
(def, _) => {
|
|
|
|
self.resolve_error(trait_reference.path.span,
|
|
|
|
format!("`{}` is not a trait",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.path_names_to_string(
|
2014-06-19 17:23:51 -05:00
|
|
|
&trait_reference.path)));
|
|
|
|
|
|
|
|
// If it's a typedef, give a note
|
|
|
|
match def {
|
2014-09-15 16:13:00 -05:00
|
|
|
DefTy(..) => {
|
2014-06-19 17:23:51 -05:00
|
|
|
self.session.span_note(
|
|
|
|
trait_reference.path.span,
|
|
|
|
format!("`type` aliases cannot \
|
|
|
|
be used for traits")
|
|
|
|
.as_slice());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-27 05:16:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-11 11:32:26 -05:00
|
|
|
fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
|
|
|
|
for predicate in where_clause.predicates.iter() {
|
|
|
|
match self.resolve_identifier(predicate.ident,
|
|
|
|
TypeNS,
|
|
|
|
true,
|
|
|
|
predicate.span) {
|
|
|
|
Some((def @ DefTyParam(_, _, _), last_private)) => {
|
|
|
|
self.record_def(predicate.id, (def, last_private));
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.resolve_error(
|
|
|
|
predicate.span,
|
|
|
|
format!("undeclared type parameter `{}`",
|
|
|
|
token::get_ident(
|
|
|
|
predicate.ident)).as_slice());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for bound in predicate.bounds.iter() {
|
2014-08-27 20:46:52 -05:00
|
|
|
self.resolve_type_parameter_bound(predicate.id, bound,
|
|
|
|
TraitBoundingTypeParameter);
|
2014-08-11 11:32:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_struct(&mut self,
|
2014-02-24 01:17:02 -06:00
|
|
|
id: NodeId,
|
|
|
|
generics: &Generics,
|
|
|
|
fields: &[StructField]) {
|
2012-05-22 12:54:12 -05:00
|
|
|
// If applicable, create a rib for the type parameters.
|
2013-11-21 17:42:55 -06:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
2014-05-31 17:53:13 -05:00
|
|
|
TypeSpace,
|
2013-11-21 17:42:55 -06:00
|
|
|
id,
|
2014-05-31 00:54:04 -05:00
|
|
|
ItemRibKind),
|
2013-11-21 17:42:55 -06:00
|
|
|
|this| {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Resolve the type parameters.
|
2013-09-26 21:10:16 -05:00
|
|
|
this.resolve_type_parameters(&generics.ty_params);
|
2014-08-11 11:32:26 -05:00
|
|
|
this.resolve_where_clause(&generics.where_clause);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-08-15 17:53:58 -05:00
|
|
|
// Resolve fields.
|
2013-08-03 11:45:23 -05:00
|
|
|
for field in fields.iter() {
|
2014-05-16 12:15:33 -05:00
|
|
|
this.resolve_type(&*field.node.ty);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-07-10 15:44:20 -05:00
|
|
|
// Does this really need to take a RibKind or is it always going
|
|
|
|
// to be NormalRibKind?
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_method(&mut self,
|
2014-01-27 06:18:36 -06:00
|
|
|
rib_kind: RibKind,
|
2014-09-11 00:07:49 -05:00
|
|
|
method: &ast::Method) {
|
2014-07-14 18:31:52 -05:00
|
|
|
let method_generics = method.pe_generics();
|
2014-05-31 17:53:13 -05:00
|
|
|
let type_parameters = HasTypeParameters(method_generics,
|
|
|
|
FnSpace,
|
|
|
|
method.id,
|
|
|
|
rib_kind);
|
2012-08-02 18:01:38 -05:00
|
|
|
|
2014-05-06 18:37:32 -05:00
|
|
|
match method.pe_explicit_self().node {
|
2014-07-07 18:35:15 -05:00
|
|
|
SelfExplicit(ref typ, _) => self.resolve_type(&**typ),
|
2014-05-06 18:37:32 -05:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.resolve_function(rib_kind,
|
|
|
|
Some(method.pe_fn_decl()),
|
|
|
|
type_parameters,
|
2014-07-14 18:31:52 -05:00
|
|
|
method.pe_body());
|
2012-07-10 15:44:20 -05:00
|
|
|
}
|
|
|
|
|
2014-05-08 16:35:09 -05:00
|
|
|
fn with_current_self_type<T>(&mut self, self_type: &Ty, f: |&mut Resolver| -> T) -> T {
|
|
|
|
// Handle nested impls (inside fn bodies)
|
|
|
|
let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
|
|
|
|
let result = f(self);
|
|
|
|
self.current_self_type = previous_value;
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
fn with_optional_trait_ref<T>(&mut self, id: NodeId,
|
|
|
|
opt_trait_ref: &Option<TraitRef>,
|
|
|
|
f: |&mut Resolver| -> T) -> T {
|
|
|
|
let new_val = match *opt_trait_ref {
|
|
|
|
Some(ref trait_ref) => {
|
|
|
|
self.resolve_trait_reference(id, trait_ref, TraitImplementation);
|
|
|
|
|
|
|
|
match self.def_map.borrow().find(&trait_ref.ref_id) {
|
|
|
|
Some(def) => {
|
2014-05-14 14:31:30 -05:00
|
|
|
let did = def.def_id();
|
2014-05-08 16:35:09 -05:00
|
|
|
Some((did, trait_ref.clone()))
|
|
|
|
}
|
|
|
|
None => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => None
|
|
|
|
};
|
|
|
|
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
|
|
|
|
let result = f(self);
|
|
|
|
self.current_trait_ref = original_trait_ref;
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_implementation(&mut self,
|
2014-05-31 17:53:13 -05:00
|
|
|
id: NodeId,
|
|
|
|
generics: &Generics,
|
|
|
|
opt_trait_reference: &Option<TraitRef>,
|
|
|
|
self_type: &Ty,
|
2014-08-04 15:56:56 -05:00
|
|
|
impl_items: &[ImplItem]) {
|
2012-05-22 12:54:12 -05:00
|
|
|
// If applicable, create a rib for the type parameters.
|
2013-11-21 17:42:55 -06:00
|
|
|
self.with_type_parameter_rib(HasTypeParameters(generics,
|
2014-05-31 17:53:13 -05:00
|
|
|
TypeSpace,
|
2013-11-21 17:42:55 -06:00
|
|
|
id,
|
|
|
|
NormalRibKind),
|
|
|
|
|this| {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Resolve the type parameters.
|
2013-09-26 21:10:16 -05:00
|
|
|
this.resolve_type_parameters(&generics.ty_params);
|
2014-08-11 11:32:26 -05:00
|
|
|
this.resolve_where_clause(&generics.where_clause);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-07-31 12:27:51 -05:00
|
|
|
// Resolve the trait reference, if necessary.
|
2014-05-08 16:35:09 -05:00
|
|
|
this.with_optional_trait_ref(id, opt_trait_reference, |this| {
|
|
|
|
// Resolve the self type.
|
|
|
|
this.resolve_type(self_type);
|
|
|
|
|
|
|
|
this.with_current_self_type(self_type, |this| {
|
2014-08-04 15:56:56 -05:00
|
|
|
for impl_item in impl_items.iter() {
|
|
|
|
match *impl_item {
|
2014-09-07 12:09:06 -05:00
|
|
|
MethodImplItem(ref method) => {
|
2014-08-04 15:56:56 -05:00
|
|
|
// If this is a trait impl, ensure the method
|
|
|
|
// exists in trait
|
2014-09-30 19:11:34 -05:00
|
|
|
this.check_trait_item(method.pe_ident().name,
|
2014-08-04 15:56:56 -05:00
|
|
|
method.span);
|
|
|
|
|
|
|
|
// We also need a new scope for the method-
|
|
|
|
// specific type parameters.
|
|
|
|
this.resolve_method(
|
2014-10-14 19:33:20 -05:00
|
|
|
MethodRibKind(id, ProvidedMethod(method.id)),
|
2014-09-07 12:09:06 -05:00
|
|
|
&**method);
|
2014-08-04 15:56:56 -05:00
|
|
|
}
|
2014-08-05 21:44:21 -05:00
|
|
|
TypeImplItem(ref typedef) => {
|
|
|
|
// If this is a trait impl, ensure the method
|
|
|
|
// exists in trait
|
2014-09-30 19:11:34 -05:00
|
|
|
this.check_trait_item(typedef.ident.name,
|
2014-08-05 21:44:21 -05:00
|
|
|
typedef.span);
|
|
|
|
|
|
|
|
this.resolve_type(&*typedef.typ);
|
|
|
|
}
|
2014-08-04 15:56:56 -05:00
|
|
|
}
|
2013-03-27 05:16:28 -05:00
|
|
|
}
|
2014-05-08 16:35:09 -05:00
|
|
|
});
|
|
|
|
});
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2014-09-16 17:39:18 -05:00
|
|
|
|
|
|
|
// Check that the current type is indeed a type, if we have an anonymous impl
|
|
|
|
if opt_trait_reference.is_none() {
|
|
|
|
match self_type.node {
|
|
|
|
// TyPath is the only thing that we handled in `build_reduced_graph_for_item`,
|
|
|
|
// where we created a module with the name of the type in order to implement
|
|
|
|
// an anonymous trait. In the case that the path does not resolve to an actual
|
|
|
|
// type, the result will be that the type name resolves to a module but not
|
|
|
|
// a type (shadowing any imported modules or types with this name), leading
|
|
|
|
// to weird user-visible bugs. So we ward this off here. See #15060.
|
|
|
|
TyPath(ref path, _, path_id) => {
|
|
|
|
match self.def_map.borrow().find(&path_id) {
|
|
|
|
// FIXME: should we catch other options and give more precise errors?
|
|
|
|
Some(&DefMod(_)) => {
|
|
|
|
self.resolve_error(path.span, "inherent implementations are not \
|
|
|
|
allowed for types not defined in \
|
|
|
|
the current module.");
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => { }
|
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn check_trait_item(&self, name: Name, span: Span) {
|
2014-06-18 08:16:45 -05:00
|
|
|
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
|
|
|
|
for &(did, ref trait_ref) in self.current_trait_ref.iter() {
|
2014-09-30 19:11:34 -05:00
|
|
|
if self.trait_item_map.find(&(name, did)).is_none() {
|
|
|
|
let path_str = self.path_names_to_string(&trait_ref.path);
|
2014-08-04 15:56:56 -05:00
|
|
|
self.resolve_error(span,
|
2014-06-18 08:16:45 -05:00
|
|
|
format!("method `{}` is not a member of trait `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name),
|
2014-06-18 08:16:45 -05:00
|
|
|
path_str).as_slice());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
fn resolve_module(&mut self, module: &Mod, _span: Span,
|
2014-09-30 19:11:34 -05:00
|
|
|
_name: Name, id: NodeId) {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Write the implementations in scope into the module metadata.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving module) resolving module ID {}", id);
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_mod(self, module);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
fn resolve_local(&mut self, local: &Local) {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Resolve the type.
|
2014-05-16 12:15:33 -05:00
|
|
|
self.resolve_type(&*local.ty);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Resolve the initializer, if necessary.
|
2013-07-19 00:38:55 -05:00
|
|
|
match local.init {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
2014-05-16 12:15:33 -05:00
|
|
|
Some(ref initializer) => {
|
|
|
|
self.resolve_expr(&**initializer);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve the pattern.
|
2014-06-10 16:39:10 -05:00
|
|
|
let mut bindings_list = HashMap::new();
|
|
|
|
self.resolve_pattern(&*local.pat,
|
|
|
|
LocalIrrefutableMode,
|
|
|
|
&mut bindings_list);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-09-05 16:15:00 -05:00
|
|
|
// build a map from pattern identifiers to binding-info's.
|
|
|
|
// this is done hygienically. This could arise for a macro
|
|
|
|
// that expands into an or-pattern where one 'x' was from the
|
|
|
|
// user and one 'x' came from the macro.
|
2014-04-14 03:30:59 -05:00
|
|
|
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
|
2013-04-03 08:28:36 -05:00
|
|
|
let mut result = HashMap::new();
|
2014-06-30 20:02:14 -05:00
|
|
|
pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
|
|
|
|
let name = mtwt::resolve(path1.node);
|
2013-06-26 17:56:13 -05:00
|
|
|
result.insert(name,
|
2012-08-06 09:20:23 -05:00
|
|
|
binding_info {span: sp,
|
|
|
|
binding_mode: binding_mode});
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-08-06 09:20:23 -05:00
|
|
|
return result;
|
2012-07-10 20:24:41 -05:00
|
|
|
}
|
|
|
|
|
2013-09-05 16:15:00 -05:00
|
|
|
// check that all of the arms in an or-pattern have exactly the
|
|
|
|
// same set of bindings, with the same binding modes for each.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn check_consistent_bindings(&mut self, arm: &Arm) {
|
2014-02-28 17:25:15 -06:00
|
|
|
if arm.pats.len() == 0 {
|
|
|
|
return
|
|
|
|
}
|
2014-10-15 01:05:01 -05:00
|
|
|
let map_0 = self.binding_mode_map(&*arm.pats[0]);
|
2013-08-03 11:45:23 -05:00
|
|
|
for (i, p) in arm.pats.iter().enumerate() {
|
2014-05-16 12:15:33 -05:00
|
|
|
let map_i = self.binding_mode_map(&**p);
|
2012-08-06 09:20:23 -05:00
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for (&key, &binding_0) in map_0.iter() {
|
2013-02-03 22:29:17 -06:00
|
|
|
match map_i.find(&key) {
|
2014-05-28 11:24:28 -05:00
|
|
|
None => {
|
|
|
|
self.resolve_error(
|
|
|
|
p.span,
|
|
|
|
format!("variable `{}` from pattern #1 is \
|
|
|
|
not bound in pattern #{}",
|
|
|
|
token::get_name(key),
|
|
|
|
i + 1).as_slice());
|
|
|
|
}
|
|
|
|
Some(binding_i) => {
|
|
|
|
if binding_0.binding_mode != binding_i.binding_mode {
|
|
|
|
self.resolve_error(
|
|
|
|
binding_i.span,
|
|
|
|
format!("variable `{}` is bound with different \
|
|
|
|
mode in pattern #{} than in pattern #1",
|
|
|
|
token::get_name(key),
|
|
|
|
i + 1).as_slice());
|
|
|
|
}
|
|
|
|
}
|
2012-08-06 09:20:23 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-03 11:45:23 -05:00
|
|
|
for (&key, &binding) in map_i.iter() {
|
2013-02-08 16:08:02 -06:00
|
|
|
if !map_0.contains_key(&key) {
|
2013-08-13 19:54:14 -05:00
|
|
|
self.resolve_error(
|
2012-08-06 09:20:23 -05:00
|
|
|
binding.span,
|
2014-05-28 11:24:28 -05:00
|
|
|
format!("variable `{}` from pattern {}{} is \
|
|
|
|
not bound in pattern {}1",
|
2014-02-13 23:07:09 -06:00
|
|
|
token::get_name(key),
|
2014-05-28 11:24:28 -05:00
|
|
|
"#", i + 1, "#").as_slice());
|
2012-08-06 09:20:23 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-10 20:24:41 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_arm(&mut self, arm: &Arm) {
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.push(Rib::new(NormalRibKind));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-12-21 17:27:26 -06:00
|
|
|
let mut bindings_list = HashMap::new();
|
2013-08-03 11:45:23 -05:00
|
|
|
for pattern in arm.pats.iter() {
|
2014-06-10 16:39:10 -05:00
|
|
|
self.resolve_pattern(&**pattern, RefutableMode, &mut bindings_list);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-07-10 20:24:41 -05:00
|
|
|
// This has to happen *after* we determine which
|
|
|
|
// pat_idents are variants
|
|
|
|
self.check_consistent_bindings(arm);
|
|
|
|
|
2014-09-09 17:54:36 -05:00
|
|
|
visit::walk_expr_opt(self, &arm.guard);
|
2014-05-16 12:15:33 -05:00
|
|
|
self.resolve_expr(&*arm.body);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.pop();
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
fn resolve_block(&mut self, block: &Block) {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving block) entering block");
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.push(Rib::new(NormalRibKind));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Move down in the graph, if there's an anonymous module rooted here.
|
2014-04-14 03:30:59 -05:00
|
|
|
let orig_module = self.current_module.clone();
|
|
|
|
match orig_module.anonymous_children.borrow().find(&block.id) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => { /* Nothing to do. */ }
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(anonymous_module) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving block) found anonymous module, moving \
|
2012-08-22 19:24:52 -05:00
|
|
|
down");
|
2014-04-14 03:30:59 -05:00
|
|
|
self.current_module = anonymous_module.clone();
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Descend into the block.
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_block(self, block);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Move back up.
|
|
|
|
self.current_module = orig_module;
|
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.pop();
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving block) leaving block");
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_type(&mut self, ty: &Ty) {
|
2012-08-06 14:34:08 -05:00
|
|
|
match ty.node {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Like path expressions, the interpretation of path types depends
|
|
|
|
// on whether the path has multiple elements in it or not.
|
|
|
|
|
2014-01-09 07:05:33 -06:00
|
|
|
TyPath(ref path, ref bounds, path_id) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// This is a path in the type namespace. Walk through scopes
|
2014-03-06 01:35:12 -06:00
|
|
|
// looking for it.
|
2012-10-15 16:56:42 -05:00
|
|
|
let mut result_def = None;
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2012-10-15 16:56:42 -05:00
|
|
|
// First, check to see whether the name is a primitive type.
|
2013-08-07 11:47:28 -05:00
|
|
|
if path.segments.len() == 1 {
|
2013-12-23 08:08:23 -06:00
|
|
|
let id = path.segments.last().unwrap().identifier;
|
2012-10-15 16:56:42 -05:00
|
|
|
|
|
|
|
match self.primitive_type_table
|
|
|
|
.primitive_types
|
2013-06-26 17:56:13 -05:00
|
|
|
.find(&id.name) {
|
2012-10-15 16:56:42 -05:00
|
|
|
|
2013-03-22 21:26:41 -05:00
|
|
|
Some(&primitive_type) => {
|
2012-10-15 16:56:42 -05:00
|
|
|
result_def =
|
2014-02-11 13:19:18 -06:00
|
|
|
Some((DefPrimTy(primitive_type), LastMod(AllPublic)));
|
2013-08-08 13:38:10 -05:00
|
|
|
|
|
|
|
if path.segments
|
|
|
|
.iter()
|
2013-10-29 05:03:32 -05:00
|
|
|
.any(|s| !s.lifetimes.is_empty()) {
|
2014-07-17 12:56:37 -05:00
|
|
|
span_err!(self.session, path.span, E0157,
|
|
|
|
"lifetime parameters are not allowed on this type");
|
2013-08-08 13:38:10 -05:00
|
|
|
} else if path.segments
|
|
|
|
.iter()
|
|
|
|
.any(|s| s.types.len() > 0) {
|
2014-07-17 12:56:37 -05:00
|
|
|
span_err!(self.session, path.span, E0153,
|
|
|
|
"type parameters are not allowed on this type");
|
2013-08-08 13:38:10 -05:00
|
|
|
}
|
2012-10-15 16:56:42 -05:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
// Continue.
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-06 14:34:08 -05:00
|
|
|
match result_def {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
match self.resolve_path(ty.id, path, TypeNS, true) {
|
2012-10-15 16:56:42 -05:00
|
|
|
Some(def) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving type) resolved `{}` to \
|
2014-10-15 01:25:34 -05:00
|
|
|
type {}",
|
2014-02-13 23:07:09 -06:00
|
|
|
token::get_ident(path.segments
|
|
|
|
.last().unwrap()
|
|
|
|
.identifier),
|
2012-10-18 15:29:34 -05:00
|
|
|
def);
|
2012-10-15 16:56:42 -05:00
|
|
|
result_def = Some(def);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
result_def = None;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-08-08 13:38:10 -05:00
|
|
|
Some(_) => {} // Continue.
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-03-20 00:17:42 -05:00
|
|
|
match result_def {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(def) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Write the result into the def map.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving type) writing resolution for `{}` \
|
2013-09-28 00:38:08 -05:00
|
|
|
(id {})",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.path_names_to_string(path),
|
2012-08-22 19:24:52 -05:00
|
|
|
path_id);
|
2012-05-22 12:54:12 -05:00
|
|
|
self.record_def(path_id, def);
|
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2013-09-28 00:38:08 -05:00
|
|
|
let msg = format!("use of undeclared type name `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.path_names_to_string(path));
|
2014-05-16 12:45:16 -05:00
|
|
|
self.resolve_error(ty.span, msg.as_slice());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2013-06-17 14:16:30 -05:00
|
|
|
|
2013-11-21 17:42:55 -06:00
|
|
|
bounds.as_ref().map(|bound_vec| {
|
2014-08-27 20:46:52 -05:00
|
|
|
self.resolve_type_parameter_bounds(ty.id, bound_vec,
|
|
|
|
TraitBoundingTypeParameter);
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-08-05 21:44:21 -05:00
|
|
|
TyQPath(ref qpath) => {
|
|
|
|
self.resolve_type(&*qpath.for_type);
|
|
|
|
|
|
|
|
let current_module = self.current_module.clone();
|
2014-09-30 19:11:34 -05:00
|
|
|
let module_path: Vec<_> =
|
2014-08-05 21:44:21 -05:00
|
|
|
qpath.trait_name
|
|
|
|
.segments
|
|
|
|
.iter()
|
2014-09-30 19:11:34 -05:00
|
|
|
.map(|ps| ps.identifier.name)
|
2014-08-05 21:44:21 -05:00
|
|
|
.collect();
|
|
|
|
match self.resolve_module_path(
|
|
|
|
current_module,
|
2014-09-30 19:11:34 -05:00
|
|
|
module_path.as_slice(),
|
2014-08-05 21:44:21 -05:00
|
|
|
UseLexicalScope,
|
|
|
|
qpath.trait_name.span,
|
|
|
|
PathSearch) {
|
|
|
|
Success((ref module, _)) if module.kind.get() ==
|
|
|
|
TraitModuleKind => {
|
|
|
|
match self.resolve_definition_of_name_in_module(
|
|
|
|
(*module).clone(),
|
|
|
|
qpath.item_name.name,
|
|
|
|
TypeNS) {
|
|
|
|
ChildNameDefinition(def, lp) |
|
|
|
|
ImportNameDefinition(def, lp) => {
|
|
|
|
match def {
|
|
|
|
DefAssociatedTy(trait_type_id) => {
|
|
|
|
let def = DefAssociatedTy(
|
|
|
|
trait_type_id);
|
|
|
|
self.record_def(ty.id, (def, lp));
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
self.resolve_error(
|
|
|
|
ty.span,
|
|
|
|
"not an associated type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NoNameDefinition => {
|
|
|
|
self.resolve_error(ty.span,
|
|
|
|
"unresolved associated \
|
|
|
|
type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Success(..) => self.resolve_error(ty.span, "not a trait"),
|
|
|
|
Indeterminate => {
|
|
|
|
self.session.span_bug(ty.span,
|
|
|
|
"indeterminate result when \
|
|
|
|
resolving associated type")
|
|
|
|
}
|
|
|
|
Failed(error) => {
|
|
|
|
let (span, help) = match error {
|
|
|
|
Some((span, msg)) => (span, format!("; {}", msg)),
|
|
|
|
None => (ty.span, String::new()),
|
|
|
|
};
|
|
|
|
self.resolve_error(span,
|
|
|
|
format!("unresolved trait: {}",
|
|
|
|
help).as_slice())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-07 12:09:06 -05:00
|
|
|
TyClosure(ref c) | TyProc(ref c) => {
|
2014-08-05 21:44:21 -05:00
|
|
|
self.resolve_type_parameter_bounds(
|
|
|
|
ty.id,
|
|
|
|
&c.bounds,
|
|
|
|
TraitBoundingTypeParameter);
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_ty(self, ty);
|
2013-05-10 14:57:27 -05:00
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Just resolve embedded types.
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_ty(self, ty);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_pattern(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
pattern: &Pat,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
mode: PatternBindingMode,
|
|
|
|
// Maps idents to the node ID for the (outermost)
|
|
|
|
// pattern that binds them
|
2014-09-30 19:11:34 -05:00
|
|
|
bindings_list: &mut HashMap<Name, NodeId>) {
|
2012-07-27 15:03:04 -05:00
|
|
|
let pat_id = pattern.id;
|
2013-11-21 17:42:55 -06:00
|
|
|
walk_pat(pattern, |pattern| {
|
2012-08-06 14:34:08 -05:00
|
|
|
match pattern.node {
|
2014-06-30 20:02:14 -05:00
|
|
|
PatIdent(binding_mode, ref path1, _) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// The meaning of pat_ident with no type parameters
|
2012-10-30 17:53:06 -05:00
|
|
|
// depends on whether an enum variant or unit-like struct
|
|
|
|
// with that name is in scope. The probing lookup has to
|
|
|
|
// be careful not to emit spurious errors. Only matching
|
|
|
|
// patterns (match) can match nullary variants or
|
|
|
|
// unit-like structs. For binding patterns (let), matching
|
|
|
|
// such a value is simply disallowed (since it's rarely
|
|
|
|
// what you want).
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-06-30 20:02:14 -05:00
|
|
|
let ident = path1.node;
|
2014-02-24 14:47:19 -06:00
|
|
|
let renamed = mtwt::resolve(ident);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
match self.resolve_bare_identifier_pattern(ident.name, pattern.span) {
|
2014-09-07 12:09:06 -05:00
|
|
|
FoundStructOrEnumVariant(ref def, lp)
|
2012-10-30 17:53:06 -05:00
|
|
|
if mode == RefutableMode => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving pattern) resolving `{}` to \
|
2012-10-30 17:53:06 -05:00
|
|
|
struct or enum variant",
|
2014-02-13 23:07:09 -06:00
|
|
|
token::get_name(renamed));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-01-24 18:24:45 -06:00
|
|
|
self.enforce_default_binding_mode(
|
|
|
|
pattern,
|
|
|
|
binding_mode,
|
|
|
|
"an enum variant");
|
2014-09-07 12:09:06 -05:00
|
|
|
self.record_def(pattern.id, (def.clone(), lp));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-11-28 14:22:53 -06:00
|
|
|
FoundStructOrEnumVariant(..) => {
|
2014-05-16 12:45:16 -05:00
|
|
|
self.resolve_error(
|
|
|
|
pattern.span,
|
|
|
|
format!("declaration of `{}` shadows an enum \
|
|
|
|
variant or unit-like struct in \
|
|
|
|
scope",
|
|
|
|
token::get_name(renamed)).as_slice());
|
2012-07-06 21:06:58 -05:00
|
|
|
}
|
2014-09-07 12:09:06 -05:00
|
|
|
FoundConst(ref def, lp) if mode == RefutableMode => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving pattern) resolving `{}` to \
|
2012-11-13 00:10:15 -06:00
|
|
|
constant",
|
2014-02-13 23:07:09 -06:00
|
|
|
token::get_name(renamed));
|
2012-11-13 00:10:15 -06:00
|
|
|
|
2013-01-24 18:24:45 -06:00
|
|
|
self.enforce_default_binding_mode(
|
|
|
|
pattern,
|
|
|
|
binding_mode,
|
|
|
|
"a constant");
|
2014-09-07 12:09:06 -05:00
|
|
|
self.record_def(pattern.id, (def.clone(), lp));
|
2012-11-13 00:10:15 -06:00
|
|
|
}
|
2013-11-28 14:22:53 -06:00
|
|
|
FoundConst(..) => {
|
2013-08-13 19:54:14 -05:00
|
|
|
self.resolve_error(pattern.span,
|
2013-10-02 07:33:01 -05:00
|
|
|
"only irrefutable patterns \
|
2013-05-19 00:07:44 -05:00
|
|
|
allowed here");
|
2012-07-06 21:06:58 -05:00
|
|
|
}
|
2012-10-30 17:53:06 -05:00
|
|
|
BareIdentifierPatternUnresolved => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving pattern) binding `{}`",
|
2014-02-13 23:07:09 -06:00
|
|
|
token::get_name(renamed));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-17 10:17:09 -05:00
|
|
|
let def = DefLocal(pattern.id);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Record the definition so that later passes
|
|
|
|
// will be able to distinguish variants from
|
|
|
|
// locals in patterns.
|
|
|
|
|
2014-02-11 13:19:18 -06:00
|
|
|
self.record_def(pattern.id, (def, LastMod(AllPublic)));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
|
|
|
// Add the binding to the local ribs, if it
|
|
|
|
// doesn't already exist in the bindings list. (We
|
|
|
|
// must not add it if it's in the bindings list
|
|
|
|
// because that breaks the assumptions later
|
|
|
|
// passes make about or-patterns.)
|
2014-06-10 16:39:10 -05:00
|
|
|
if !bindings_list.contains_key(&renamed) {
|
|
|
|
let this = &mut *self;
|
2014-09-29 18:06:13 -05:00
|
|
|
let last_rib = this.value_ribs.last_mut().unwrap();
|
|
|
|
last_rib.bindings.insert(renamed, DlDef(def));
|
2014-06-10 16:39:10 -05:00
|
|
|
bindings_list.insert(renamed, pat_id);
|
2014-10-08 23:28:50 -05:00
|
|
|
} else if mode == ArgumentIrrefutableMode &&
|
|
|
|
bindings_list.contains_key(&renamed) {
|
|
|
|
// Forbid duplicate bindings in the same
|
|
|
|
// parameter list.
|
|
|
|
self.resolve_error(pattern.span,
|
|
|
|
format!("identifier `{}` \
|
|
|
|
is bound more \
|
|
|
|
than once in \
|
|
|
|
this parameter \
|
|
|
|
list",
|
|
|
|
token::get_ident(
|
|
|
|
ident))
|
|
|
|
.as_slice())
|
2014-06-10 16:39:10 -05:00
|
|
|
} else if bindings_list.find(&renamed) ==
|
|
|
|
Some(&pat_id) {
|
|
|
|
// Then this is a duplicate variable in the
|
|
|
|
// same disjunction, which is an error.
|
|
|
|
self.resolve_error(pattern.span,
|
|
|
|
format!("identifier `{}` is bound \
|
|
|
|
more than once in the same \
|
|
|
|
pattern",
|
2014-06-30 20:02:14 -05:00
|
|
|
token::get_ident(ident)).as_slice());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-06-10 16:39:10 -05:00
|
|
|
// Else, not bound in the same pattern: do
|
|
|
|
// nothing.
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-01 20:45:37 -05:00
|
|
|
PatEnum(ref path, _) => {
|
2013-03-21 02:27:26 -05:00
|
|
|
// This must be an enum variant, struct or const.
|
2013-09-26 21:10:16 -05:00
|
|
|
match self.resolve_path(pat_id, path, ValueNS, false) {
|
2013-11-28 14:22:53 -06:00
|
|
|
Some(def @ (DefVariant(..), _)) |
|
|
|
|
Some(def @ (DefStruct(..), _)) |
|
2014-10-11 10:46:45 -05:00
|
|
|
Some(def @ (DefConst(..), _)) => {
|
2013-03-13 00:39:32 -05:00
|
|
|
self.record_def(pattern.id, def);
|
|
|
|
}
|
2014-10-11 10:46:45 -05:00
|
|
|
Some((DefStatic(..), _)) => {
|
|
|
|
self.resolve_error(path.span,
|
|
|
|
"static variables cannot be \
|
|
|
|
referenced in a pattern, \
|
|
|
|
use a `const` instead");
|
|
|
|
}
|
2013-03-13 00:39:32 -05:00
|
|
|
Some(_) => {
|
2014-02-13 23:07:09 -06:00
|
|
|
self.resolve_error(path.span,
|
2013-09-28 00:38:08 -05:00
|
|
|
format!("`{}` is not an enum variant, struct or const",
|
2014-05-16 12:45:16 -05:00
|
|
|
token::get_ident(
|
|
|
|
path.segments
|
|
|
|
.last()
|
|
|
|
.unwrap()
|
|
|
|
.identifier)).as_slice());
|
2013-03-13 00:39:32 -05:00
|
|
|
}
|
|
|
|
None => {
|
2013-08-13 19:54:14 -05:00
|
|
|
self.resolve_error(path.span,
|
2014-02-13 23:07:09 -06:00
|
|
|
format!("unresolved enum variant, struct or const `{}`",
|
2014-05-16 12:45:16 -05:00
|
|
|
token::get_ident(
|
|
|
|
path.segments
|
|
|
|
.last()
|
|
|
|
.unwrap()
|
|
|
|
.identifier)).as_slice());
|
2013-03-13 00:39:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the types in the path pattern.
|
2014-05-16 12:15:33 -05:00
|
|
|
for ty in path.segments
|
2013-08-07 11:47:28 -05:00
|
|
|
.iter()
|
2013-08-08 13:38:10 -05:00
|
|
|
.flat_map(|s| s.types.iter()) {
|
2014-05-16 12:15:33 -05:00
|
|
|
self.resolve_type(&**ty);
|
2013-03-13 00:39:32 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-16 12:15:33 -05:00
|
|
|
PatLit(ref expr) => {
|
|
|
|
self.resolve_expr(&**expr);
|
2012-07-10 14:29:30 -05:00
|
|
|
}
|
|
|
|
|
2014-05-16 12:15:33 -05:00
|
|
|
PatRange(ref first_expr, ref last_expr) => {
|
|
|
|
self.resolve_expr(&**first_expr);
|
|
|
|
self.resolve_expr(&**last_expr);
|
2012-07-10 14:29:30 -05:00
|
|
|
}
|
|
|
|
|
2013-09-01 20:45:37 -05:00
|
|
|
PatStruct(ref path, _, _) => {
|
2013-09-26 21:10:16 -05:00
|
|
|
match self.resolve_path(pat_id, path, TypeNS, false) {
|
2014-07-04 18:45:47 -05:00
|
|
|
Some(definition) => {
|
2012-08-07 21:12:58 -05:00
|
|
|
self.record_def(pattern.id, definition);
|
|
|
|
}
|
2012-12-10 14:37:50 -06:00
|
|
|
result => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving pattern) didn't find struct \
|
2014-10-15 01:25:34 -05:00
|
|
|
def: {}", result);
|
2013-09-28 00:38:08 -05:00
|
|
|
let msg = format!("`{}` does not name a structure",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.path_names_to_string(path));
|
2014-05-16 12:45:16 -05:00
|
|
|
self.resolve_error(path.span, msg.as_slice());
|
2012-08-06 19:01:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-31 21:25:24 -05:00
|
|
|
_ => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
}
|
2013-08-02 01:17:20 -05:00
|
|
|
true
|
2013-11-21 17:42:55 -06:00
|
|
|
});
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn resolve_bare_identifier_pattern(&mut self, name: Name, span: Span)
|
2014-04-14 03:30:59 -05:00
|
|
|
-> BareIdentifierPatternResolution {
|
|
|
|
let module = self.current_module.clone();
|
|
|
|
match self.resolve_item_in_lexical_scope(module,
|
2012-10-30 17:53:06 -05:00
|
|
|
name,
|
2014-05-16 17:44:14 -05:00
|
|
|
ValueNS) {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Success((target, _)) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolve bare identifier pattern) succeeded in \
|
2014-10-15 01:25:34 -05:00
|
|
|
finding {} at {}",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name),
|
2014-03-28 12:29:55 -05:00
|
|
|
target.bindings.value_def.borrow());
|
|
|
|
match *target.bindings.value_def.borrow() {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("resolved name in the value namespace to a \
|
2013-02-11 21:26:38 -06:00
|
|
|
set of name bindings with no def?!");
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(def) => {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
// For the two success cases, this lookup can be
|
|
|
|
// considered as not having a private component because
|
|
|
|
// the lookup happened only within the current module.
|
2012-08-17 19:55:34 -05:00
|
|
|
match def.def {
|
2013-11-28 14:22:53 -06:00
|
|
|
def @ DefVariant(..) | def @ DefStruct(..) => {
|
2014-02-11 13:19:18 -06:00
|
|
|
return FoundStructOrEnumVariant(def, LastMod(AllPublic));
|
2012-08-17 19:55:34 -05:00
|
|
|
}
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 10:17:01 -05:00
|
|
|
def @ DefConst(..) => {
|
2014-02-11 13:19:18 -06:00
|
|
|
return FoundConst(def, LastMod(AllPublic));
|
2012-08-17 19:55:34 -05:00
|
|
|
}
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 10:17:01 -05:00
|
|
|
DefStatic(..) => {
|
2014-07-13 08:12:47 -05:00
|
|
|
self.resolve_error(span,
|
rustc: Add `const` globals to the language
This change is an implementation of [RFC 69][rfc] which adds a third kind of
global to the language, `const`. This global is most similar to what the old
`static` was, and if you're unsure about what to use then you should use a
`const`.
The semantics of these three kinds of globals are:
* A `const` does not represent a memory location, but only a value. Constants
are translated as rvalues, which means that their values are directly inlined
at usage location (similar to a #define in C/C++). Constant values are, well,
constant, and can not be modified. Any "modification" is actually a
modification to a local value on the stack rather than the actual constant
itself.
Almost all values are allowed inside constants, whether they have interior
mutability or not. There are a few minor restrictions listed in the RFC, but
they should in general not come up too often.
* A `static` now always represents a memory location (unconditionally). Any
references to the same `static` are actually a reference to the same memory
location. Only values whose types ascribe to `Sync` are allowed in a `static`.
This restriction is in place because many threads may access a `static`
concurrently. Lifting this restriction (and allowing unsafe access) is a
future extension not implemented at this time.
* A `static mut` continues to always represent a memory location. All references
to a `static mut` continue to be `unsafe`.
This is a large breaking change, and many programs will need to be updated
accordingly. A summary of the breaking changes is:
* Statics may no longer be used in patterns. Statics now always represent a
memory location, which can sometimes be modified. To fix code, repurpose the
matched-on-`static` to a `const`.
static FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
change this code to:
const FOO: uint = 4;
match n {
FOO => { /* ... */ }
_ => { /* ... */ }
}
* Statics may no longer refer to other statics by value. Due to statics being
able to change at runtime, allowing them to reference one another could
possibly lead to confusing semantics. If you are in this situation, use a
constant initializer instead. Note, however, that statics may reference other
statics by address, however.
* Statics may no longer be used in constant expressions, such as array lengths.
This is due to the same restrictions as listed above. Use a `const` instead.
[breaking-change]
[rfc]: https://github.com/rust-lang/rfcs/pull/246
2014-10-06 10:17:01 -05:00
|
|
|
"static variables cannot be \
|
|
|
|
referenced in a pattern, \
|
|
|
|
use a `const` instead");
|
2014-07-13 08:12:47 -05:00
|
|
|
return BareIdentifierPatternUnresolved;
|
|
|
|
}
|
2012-08-17 19:55:34 -05:00
|
|
|
_ => {
|
2012-10-30 17:53:06 -05:00
|
|
|
return BareIdentifierPatternUnresolved;
|
2012-08-17 19:55:34 -05:00
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:04 -05:00
|
|
|
Indeterminate => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("unexpected indeterminate result");
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => {
|
|
|
|
match err {
|
|
|
|
Some((span, msg)) => {
|
|
|
|
self.resolve_error(span, format!("failed to resolve: {}",
|
|
|
|
msg));
|
|
|
|
}
|
|
|
|
None => ()
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolve bare identifier pattern) failed to find {}",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name));
|
2012-10-30 17:53:06 -05:00
|
|
|
return BareIdentifierPatternUnresolved;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
/// If `check_ribs` is true, checks the local definitions first; i.e.
|
|
|
|
/// doesn't skip straight to the containing module.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_path(&mut self,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
id: NodeId,
|
|
|
|
path: &Path,
|
|
|
|
namespace: Namespace,
|
|
|
|
check_ribs: bool) -> Option<(Def, LastPrivate)> {
|
2012-05-22 12:54:12 -05:00
|
|
|
// First, resolve the types.
|
2014-05-16 12:15:33 -05:00
|
|
|
for ty in path.segments.iter().flat_map(|s| s.types.iter()) {
|
|
|
|
self.resolve_type(&**ty);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if path.global {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
return self.resolve_crate_relative_path(path, namespace);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let unqualified_def =
|
|
|
|
self.resolve_identifier(path.segments
|
2013-12-23 08:08:23 -06:00
|
|
|
.last().unwrap()
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
.identifier,
|
|
|
|
namespace,
|
|
|
|
check_ribs,
|
|
|
|
path.span);
|
2013-07-08 10:34:28 -05:00
|
|
|
|
2013-08-07 11:47:28 -05:00
|
|
|
if path.segments.len() > 1 {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let def = self.resolve_module_relative_path(path, namespace);
|
2013-07-08 10:34:28 -05:00
|
|
|
match (def, unqualified_def) {
|
2014-09-07 12:09:06 -05:00
|
|
|
(Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
|
2014-05-09 20:45:36 -05:00
|
|
|
self.session
|
2014-10-14 13:37:16 -05:00
|
|
|
.add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
|
2014-05-09 20:45:36 -05:00
|
|
|
id,
|
|
|
|
path.span,
|
2014-05-25 05:17:19 -05:00
|
|
|
"unnecessary qualification".to_string());
|
2013-07-08 10:34:28 -05:00
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
}
|
2013-08-08 13:38:10 -05:00
|
|
|
|
2013-07-08 10:34:28 -05:00
|
|
|
return def;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-07-08 10:34:28 -05:00
|
|
|
return unqualified_def;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-05-30 19:46:25 -05:00
|
|
|
// resolve a single identifier (used as a varref)
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_identifier(&mut self,
|
2013-09-01 19:50:59 -05:00
|
|
|
identifier: Ident,
|
2013-05-31 17:17:22 -05:00
|
|
|
namespace: Namespace,
|
|
|
|
check_ribs: bool,
|
2013-08-31 11:13:04 -05:00
|
|
|
span: Span)
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
-> Option<(Def, LastPrivate)> {
|
2012-05-22 12:54:12 -05:00
|
|
|
if check_ribs {
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.resolve_identifier_in_local_ribs(identifier,
|
2012-07-06 21:06:58 -05:00
|
|
|
namespace,
|
|
|
|
span) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(def) => {
|
2014-02-11 13:19:18 -06:00
|
|
|
return Some((def, LastMod(AllPublic)));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Continue.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
return self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-02-14 20:37:25 -06:00
|
|
|
// FIXME #4952: Merge me with resolve_name_in_module?
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_definition_of_name_in_module(&mut self,
|
2014-04-14 03:30:59 -05:00
|
|
|
containing_module: Rc<Module>,
|
2014-05-08 16:35:09 -05:00
|
|
|
name: Name,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
namespace: Namespace)
|
2013-05-31 17:17:22 -05:00
|
|
|
-> NameDefinition {
|
2012-05-22 12:54:12 -05:00
|
|
|
// First, search children.
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&containing_module);
|
2013-12-21 17:32:44 -06:00
|
|
|
|
2014-05-08 16:35:09 -05:00
|
|
|
match containing_module.children.borrow().find(&name) {
|
2014-03-20 21:49:20 -05:00
|
|
|
Some(child_name_bindings) => {
|
|
|
|
match child_name_bindings.def_for_namespace(namespace) {
|
|
|
|
Some(def) => {
|
|
|
|
// Found it. Stop the search here.
|
|
|
|
let p = child_name_bindings.defined_in_public_namespace(
|
|
|
|
namespace);
|
|
|
|
let lp = if p {LastMod(AllPublic)} else {
|
2014-05-14 14:31:30 -05:00
|
|
|
LastMod(DependsOn(def.def_id()))
|
2014-03-20 21:49:20 -05:00
|
|
|
};
|
|
|
|
return ChildNameDefinition(def, lp);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-03-20 21:49:20 -05:00
|
|
|
None => {}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2014-03-20 21:49:20 -05:00
|
|
|
None => {}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Next, search import resolutions.
|
2014-05-08 16:35:09 -05:00
|
|
|
match containing_module.import_resolutions.borrow().find(&name) {
|
2014-04-14 03:30:59 -05:00
|
|
|
Some(import_resolution) if import_resolution.is_public => {
|
2012-08-06 14:34:08 -05:00
|
|
|
match (*import_resolution).target_for_namespace(namespace) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(target) => {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
match target.bindings.def_for_namespace(namespace) {
|
|
|
|
Some(def) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Found it.
|
2013-06-09 23:39:15 -05:00
|
|
|
let id = import_resolution.id(namespace);
|
2014-09-11 12:14:43 -05:00
|
|
|
// track imports and extern crates as well
|
2014-02-11 13:19:18 -06:00
|
|
|
self.used_imports.insert((id, namespace));
|
2014-09-11 12:14:43 -05:00
|
|
|
match target.target_module.def_id.get() {
|
|
|
|
Some(DefId{krate: kid, ..}) => {
|
|
|
|
self.used_crates.insert(kid);
|
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
}
|
2014-02-11 13:19:18 -06:00
|
|
|
return ImportNameDefinition(def, LastMod(AllPublic));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
None => {
|
2012-07-11 17:00:40 -05:00
|
|
|
// This can happen with external impls, due to
|
|
|
|
// the imperfect way we read the metadata.
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-03-26 21:53:33 -05:00
|
|
|
None => {}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-28 14:22:53 -06:00
|
|
|
Some(..) | None => {} // Continue.
|
2013-03-26 21:53:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, search through external children.
|
|
|
|
if namespace == TypeNS {
|
2014-03-20 21:49:20 -05:00
|
|
|
match containing_module.external_module_children.borrow()
|
2014-05-08 16:35:09 -05:00
|
|
|
.find_copy(&name) {
|
2013-03-26 21:53:33 -05:00
|
|
|
None => {}
|
|
|
|
Some(module) => {
|
2013-12-19 20:56:20 -06:00
|
|
|
match module.def_id.get() {
|
2013-03-26 21:53:33 -05:00
|
|
|
None => {} // Continue.
|
|
|
|
Some(def_id) => {
|
2014-09-11 12:14:43 -05:00
|
|
|
// track used crates
|
|
|
|
self.used_crates.insert(def_id.krate);
|
2014-02-11 13:19:18 -06:00
|
|
|
let lp = if module.is_public {LastMod(AllPublic)} else {
|
|
|
|
LastMod(DependsOn(def_id))
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
};
|
|
|
|
return ChildNameDefinition(DefMod(def_id), lp);
|
2013-03-26 21:53:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
2013-03-26 21:53:33 -05:00
|
|
|
|
|
|
|
return NoNameDefinition;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-06-26 13:16:09 -05:00
|
|
|
// resolve a "module-relative" path, e.g. a::b::c
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_module_relative_path(&mut self,
|
2013-07-05 05:15:21 -05:00
|
|
|
path: &Path,
|
2013-05-31 17:17:22 -05:00
|
|
|
namespace: Namespace)
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
-> Option<(Def, LastPrivate)> {
|
2014-09-30 19:11:34 -05:00
|
|
|
let module_path = path.segments.init().iter()
|
|
|
|
.map(|ps| ps.identifier.name)
|
|
|
|
.collect::<Vec<_>>();
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-04-12 00:15:30 -05:00
|
|
|
let containing_module;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let last_private;
|
2014-04-14 03:30:59 -05:00
|
|
|
let module = self.current_module.clone();
|
|
|
|
match self.resolve_module_path(module,
|
2014-09-30 19:11:34 -05:00
|
|
|
module_path.as_slice(),
|
2013-05-13 18:13:20 -05:00
|
|
|
UseLexicalScope,
|
|
|
|
path.span,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
PathSearch) {
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => {
|
|
|
|
let (span, msg) = match err {
|
|
|
|
Some((span, msg)) => (span, msg),
|
|
|
|
None => {
|
|
|
|
let msg = format!("Use of undeclared module `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.names_to_string(
|
|
|
|
module_path.as_slice()));
|
2014-06-05 16:37:52 -05:00
|
|
|
(path.span, msg)
|
|
|
|
}
|
|
|
|
};
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-06-05 16:37:52 -05:00
|
|
|
self.resolve_error(span, format!("failed to resolve. {}",
|
|
|
|
msg.as_slice()));
|
|
|
|
return None;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-10-09 14:17:22 -05:00
|
|
|
Indeterminate => panic!("indeterminate unexpected"),
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Success((resulting_module, resulting_last_private)) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
containing_module = resulting_module;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
last_private = resulting_last_private;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = path.segments.last().unwrap().identifier.name;
|
2014-04-14 03:30:59 -05:00
|
|
|
let def = match self.resolve_definition_of_name_in_module(containing_module.clone(),
|
2014-09-30 19:11:34 -05:00
|
|
|
name,
|
2014-10-14 19:33:20 -05:00
|
|
|
namespace) {
|
2012-08-03 21:59:04 -05:00
|
|
|
NoNameDefinition => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// We failed to resolve the name. Report an error.
|
2012-08-20 14:23:37 -05:00
|
|
|
return None;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
ChildNameDefinition(def, lp) | ImportNameDefinition(def, lp) => {
|
|
|
|
(def, last_private.or(lp))
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-06-03 06:31:43 -05:00
|
|
|
};
|
2014-09-11 12:14:43 -05:00
|
|
|
match containing_module.def_id.get() {
|
|
|
|
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
|
|
|
|
_ => {}
|
|
|
|
}
|
2013-06-03 06:31:43 -05:00
|
|
|
return Some(def);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-03-01 12:44:43 -06:00
|
|
|
/// Invariant: This must be called only during main resolution, not during
|
|
|
|
/// import resolution.
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_crate_relative_path(&mut self,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
path: &Path,
|
|
|
|
namespace: Namespace)
|
|
|
|
-> Option<(Def, LastPrivate)> {
|
2014-09-30 19:11:34 -05:00
|
|
|
let module_path = path.segments.init().iter()
|
|
|
|
.map(|ps| ps.identifier.name)
|
|
|
|
.collect::<Vec<_>>();
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-02-04 16:02:01 -06:00
|
|
|
let root_module = self.graph_root.get_module();
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-04-12 00:15:30 -05:00
|
|
|
let containing_module;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
let last_private;
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.resolve_module_path_from_root(root_module,
|
2014-09-30 19:11:34 -05:00
|
|
|
module_path.as_slice(),
|
2012-12-23 16:41:37 -06:00
|
|
|
0,
|
2013-03-01 12:44:43 -06:00
|
|
|
path.span,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
PathSearch,
|
2014-02-11 13:19:18 -06:00
|
|
|
LastMod(AllPublic)) {
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => {
|
|
|
|
let (span, msg) = match err {
|
|
|
|
Some((span, msg)) => (span, msg),
|
|
|
|
None => {
|
|
|
|
let msg = format!("Use of undeclared module `::{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.names_to_string(module_path.as_slice()));
|
2014-06-05 16:37:52 -05:00
|
|
|
(path.span, msg)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
self.resolve_error(span, format!("failed to resolve. {}",
|
|
|
|
msg.as_slice()));
|
2012-08-20 14:23:37 -05:00
|
|
|
return None;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:04 -05:00
|
|
|
Indeterminate => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("indeterminate unexpected");
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Success((resulting_module, resulting_last_private)) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
containing_module = resulting_module;
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
last_private = resulting_last_private;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-08 16:35:09 -05:00
|
|
|
let name = path.segments.last().unwrap().identifier.name;
|
2012-08-06 14:34:08 -05:00
|
|
|
match self.resolve_definition_of_name_in_module(containing_module,
|
2012-12-23 16:41:37 -06:00
|
|
|
name,
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
namespace) {
|
2012-08-03 21:59:04 -05:00
|
|
|
NoNameDefinition => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// We failed to resolve the name. Report an error.
|
2012-08-20 14:23:37 -05:00
|
|
|
return None;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
ChildNameDefinition(def, lp) | ImportNameDefinition(def, lp) => {
|
|
|
|
return Some((def, last_private.or(lp)));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn resolve_identifier_in_local_ribs(&mut self,
|
2013-09-01 19:50:59 -05:00
|
|
|
ident: Ident,
|
2013-05-31 17:17:22 -05:00
|
|
|
namespace: Namespace,
|
2013-08-31 11:13:04 -05:00
|
|
|
span: Span)
|
2013-09-01 20:45:37 -05:00
|
|
|
-> Option<Def> {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Check the local set of ribs.
|
2014-03-20 21:49:20 -05:00
|
|
|
let search_result = match namespace {
|
2012-08-03 21:59:04 -05:00
|
|
|
ValueNS => {
|
2014-02-24 14:47:19 -06:00
|
|
|
let renamed = mtwt::resolve(ident);
|
2014-09-29 18:06:13 -05:00
|
|
|
self.search_ribs(self.value_ribs.as_slice(),
|
2014-03-20 21:49:20 -05:00
|
|
|
renamed, span)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
TypeNS => {
|
2013-06-26 17:56:13 -05:00
|
|
|
let name = ident.name;
|
2014-09-29 18:06:13 -05:00
|
|
|
self.search_ribs(self.type_ribs.as_slice(), name, span)
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-03-20 21:49:20 -05:00
|
|
|
};
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-03-20 00:17:42 -05:00
|
|
|
match search_result {
|
2013-08-31 11:13:04 -05:00
|
|
|
Some(DlDef(def)) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving path in local ribs) resolved `{}` to \
|
2014-10-15 01:25:34 -05:00
|
|
|
local: {}",
|
2014-02-13 23:07:09 -06:00
|
|
|
token::get_ident(ident),
|
2012-08-22 19:24:52 -05:00
|
|
|
def);
|
2012-08-20 14:23:37 -05:00
|
|
|
return Some(def);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2013-08-31 11:13:04 -05:00
|
|
|
Some(DlField) | Some(DlImpl(_)) | None => {
|
2012-08-20 14:23:37 -05:00
|
|
|
return None;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn resolve_item_by_name_in_lexical_scope(&mut self,
|
|
|
|
name: Name,
|
|
|
|
namespace: Namespace)
|
|
|
|
-> Option<(Def, LastPrivate)> {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Check the items.
|
2014-04-14 03:30:59 -05:00
|
|
|
let module = self.current_module.clone();
|
|
|
|
match self.resolve_item_in_lexical_scope(module,
|
2014-09-30 19:11:34 -05:00
|
|
|
name,
|
2014-05-16 17:44:14 -05:00
|
|
|
namespace) {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
Success((target, _)) => {
|
2012-08-06 14:34:08 -05:00
|
|
|
match (*target.bindings).def_for_namespace(namespace) {
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2012-10-15 16:56:42 -05:00
|
|
|
// This can happen if we were looking for a type and
|
|
|
|
// found a module instead. Modules don't have defs.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item path by identifier in lexical \
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
scope) failed to resolve {} after success...",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name));
|
2012-10-15 16:56:42 -05:00
|
|
|
return None;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(def) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item path in lexical scope) \
|
2013-09-28 00:38:08 -05:00
|
|
|
resolved `{}` to item",
|
2014-09-30 19:11:34 -05:00
|
|
|
token::get_name(name));
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
// This lookup is "all public" because it only searched
|
|
|
|
// for one identifier in the current module (couldn't
|
|
|
|
// have passed through reexports or anything like that.
|
2014-02-11 13:19:18 -06:00
|
|
|
return Some((def, LastMod(AllPublic)));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
Indeterminate => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("unexpected indeterminate result");
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-06-05 16:37:52 -05:00
|
|
|
Failed(err) => {
|
|
|
|
match err {
|
|
|
|
Some((span, msg)) =>
|
|
|
|
self.resolve_error(span, format!("failed to resolve. {}", msg)),
|
|
|
|
None => ()
|
|
|
|
}
|
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving item path by identifier in lexical scope) \
|
2014-09-30 19:11:34 -05:00
|
|
|
failed to resolve {}", token::get_name(name));
|
2012-08-20 14:23:37 -05:00
|
|
|
return None;
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-19 15:22:03 -06:00
|
|
|
fn with_no_errors<T>(&mut self, f: |&mut Resolver| -> T) -> T {
|
2013-08-13 19:54:14 -05:00
|
|
|
self.emit_errors = false;
|
2013-09-26 21:10:16 -05:00
|
|
|
let rs = f(self);
|
2013-08-13 19:54:14 -05:00
|
|
|
self.emit_errors = true;
|
|
|
|
rs
|
|
|
|
}
|
|
|
|
|
2014-06-05 16:37:52 -05:00
|
|
|
fn resolve_error<T: Str>(&self, span: Span, s: T) {
|
2013-08-13 19:54:14 -05:00
|
|
|
if self.emit_errors {
|
2014-06-05 16:37:52 -05:00
|
|
|
self.session.span_err(span, s.as_slice());
|
2013-08-13 19:54:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-08 16:35:09 -05:00
|
|
|
fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
|
2014-05-29 19:45:07 -05:00
|
|
|
#[deriving(PartialEq)]
|
2014-05-19 16:27:03 -05:00
|
|
|
enum FallbackChecks {
|
|
|
|
Everything,
|
|
|
|
OnlyTraitAndStatics
|
|
|
|
}
|
|
|
|
|
|
|
|
fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks)
|
|
|
|
-> Option<(Path, NodeId, FallbackChecks)> {
|
|
|
|
match t.node {
|
|
|
|
TyPath(ref path, _, node_id) => Some((path.clone(), node_id, allow)),
|
2014-09-07 12:09:06 -05:00
|
|
|
TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
|
|
|
|
TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
|
2014-05-19 16:27:03 -05:00
|
|
|
// This doesn't handle the remaining `Ty` variants as they are not
|
|
|
|
// that commonly the self_type, it might be interesting to provide
|
|
|
|
// support for those in future.
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
|
2014-05-08 16:35:09 -05:00
|
|
|
-> Option<Rc<Module>> {
|
|
|
|
let root = this.current_module.clone();
|
2014-09-30 19:11:34 -05:00
|
|
|
let last_name = name_path.last().unwrap();
|
2014-05-08 16:35:09 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
if name_path.len() == 1 {
|
|
|
|
match this.primitive_type_table.primitive_types.find(last_name) {
|
2014-05-08 16:35:09 -05:00
|
|
|
Some(_) => None,
|
|
|
|
None => {
|
2014-09-30 19:11:34 -05:00
|
|
|
match this.current_module.children.borrow().find(last_name) {
|
2014-05-08 16:35:09 -05:00
|
|
|
Some(child) => child.get_module_if_available(),
|
|
|
|
None => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
match this.resolve_module_path(root,
|
2014-09-30 19:11:34 -05:00
|
|
|
name_path.as_slice(),
|
2014-05-08 16:35:09 -05:00
|
|
|
UseLexicalScope,
|
|
|
|
span,
|
|
|
|
PathSearch) {
|
|
|
|
Success((module, _)) => Some(module),
|
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-19 16:27:03 -05:00
|
|
|
let (path, node_id, allowed) = match self.current_self_type {
|
|
|
|
Some(ref ty) => match extract_path_and_node_id(ty, Everything) {
|
|
|
|
Some(x) => x,
|
|
|
|
None => return NoSuggestion,
|
2014-05-08 16:35:09 -05:00
|
|
|
},
|
|
|
|
None => return NoSuggestion,
|
|
|
|
};
|
|
|
|
|
2014-05-19 16:27:03 -05:00
|
|
|
if allowed == Everything {
|
|
|
|
// Look for a field with the same name in the current self_type.
|
|
|
|
match self.def_map.borrow().find(&node_id) {
|
2014-09-15 16:13:00 -05:00
|
|
|
Some(&DefTy(did, _))
|
2014-05-19 16:27:03 -05:00
|
|
|
| Some(&DefStruct(did))
|
|
|
|
| Some(&DefVariant(_, did, _)) => match self.structs.find(&did) {
|
|
|
|
None => {}
|
|
|
|
Some(fields) => {
|
|
|
|
if fields.iter().any(|&field_name| name == field_name) {
|
|
|
|
return Field;
|
|
|
|
}
|
2014-05-08 16:35:09 -05:00
|
|
|
}
|
2014-05-19 16:27:03 -05:00
|
|
|
},
|
|
|
|
_ => {} // Self type didn't resolve properly
|
|
|
|
}
|
2014-05-08 16:35:09 -05:00
|
|
|
}
|
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::<Vec<_>>();
|
2014-05-08 16:35:09 -05:00
|
|
|
|
|
|
|
// Look for a method in the current self type's impl module.
|
2014-09-30 19:11:34 -05:00
|
|
|
match get_module(self, path.span, name_path.as_slice()) {
|
2014-05-08 16:35:09 -05:00
|
|
|
Some(module) => match module.children.borrow().find(&name) {
|
|
|
|
Some(binding) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let p_str = self.path_names_to_string(&path);
|
2014-05-08 16:35:09 -05:00
|
|
|
match binding.def_for_namespace(ValueNS) {
|
2014-10-15 23:44:24 -05:00
|
|
|
Some(DefStaticMethod(_, provenance)) => {
|
2014-05-08 16:35:09 -05:00
|
|
|
match provenance {
|
|
|
|
FromImpl(_) => return StaticMethod(p_str),
|
|
|
|
FromTrait(_) => unreachable!()
|
|
|
|
}
|
|
|
|
}
|
2014-10-14 19:33:20 -05:00
|
|
|
Some(DefMethod(_, None, _)) if allowed == Everything => return Method,
|
|
|
|
Some(DefMethod(_, Some(_), _)) => return TraitItem,
|
2014-05-08 16:35:09 -05:00
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
},
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look for a method in the current trait.
|
|
|
|
match self.current_trait_ref {
|
|
|
|
Some((did, ref trait_ref)) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let path_str = self.path_names_to_string(&trait_ref.path);
|
2014-05-08 16:35:09 -05:00
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
match self.trait_item_map.find(&(name, did)) {
|
2014-10-14 19:33:20 -05:00
|
|
|
Some(&StaticMethodTraitItemKind) => {
|
|
|
|
return TraitMethod(path_str)
|
|
|
|
}
|
2014-08-04 15:56:56 -05:00
|
|
|
Some(_) => return TraitItem,
|
2014-05-08 16:35:09 -05:00
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
NoSuggestion
|
|
|
|
}
|
|
|
|
|
2013-11-19 15:22:03 -06:00
|
|
|
fn find_best_match_for_name(&mut self, name: &str, max_distance: uint)
|
2014-05-22 18:57:53 -05:00
|
|
|
-> Option<String> {
|
2013-03-16 13:11:31 -05:00
|
|
|
let this = &mut *self;
|
|
|
|
|
2014-03-04 12:02:49 -06:00
|
|
|
let mut maybes: Vec<token::InternedString> = Vec::new();
|
|
|
|
let mut values: Vec<uint> = Vec::new();
|
2013-02-23 02:22:51 -06:00
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
for rib in this.value_ribs.iter().rev() {
|
|
|
|
for (&k, _) in rib.bindings.iter() {
|
2014-02-13 23:07:09 -06:00
|
|
|
maybes.push(token::get_name(k));
|
2014-01-25 01:37:51 -06:00
|
|
|
values.push(uint::MAX);
|
2013-02-23 02:22:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut smallest = 0;
|
2014-01-31 14:25:11 -06:00
|
|
|
for (i, other) in maybes.iter().enumerate() {
|
2014-10-23 10:42:21 -05:00
|
|
|
values[i] = name.lev_distance(other.get());
|
2013-02-23 02:22:51 -06:00
|
|
|
|
2014-10-15 01:05:01 -05:00
|
|
|
if values[i] <= values[smallest] {
|
2013-02-23 02:22:51 -06:00
|
|
|
smallest = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-14 04:52:12 -05:00
|
|
|
if values.len() > 0 &&
|
2014-10-15 01:05:01 -05:00
|
|
|
values[smallest] != uint::MAX &&
|
|
|
|
values[smallest] < name.len() + 2 &&
|
|
|
|
values[smallest] <= max_distance &&
|
|
|
|
name != maybes[smallest].get() {
|
2013-02-23 02:22:51 -06:00
|
|
|
|
2014-10-15 01:05:01 -05:00
|
|
|
Some(maybes[smallest].get().to_string())
|
2013-02-23 02:22:51 -06:00
|
|
|
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
fn resolve_expr(&mut self, expr: &Expr) {
|
2012-08-17 18:53:07 -05:00
|
|
|
// First, record candidate traits for this expression if it could
|
|
|
|
// result in the invocation of a method call.
|
2012-07-11 17:00:40 -05:00
|
|
|
|
|
|
|
self.record_candidate_traits_for_expr_if_necessary(expr);
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
// Next, resolve the node.
|
2012-08-06 14:34:08 -05:00
|
|
|
match expr.node {
|
2012-05-22 12:54:12 -05:00
|
|
|
// The interpretation of paths depends on whether the path has
|
|
|
|
// multiple elements in it or not.
|
|
|
|
|
2013-09-01 20:45:37 -05:00
|
|
|
ExprPath(ref path) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// This is a local path in the value namespace. Walk through
|
|
|
|
// scopes looking for it.
|
|
|
|
|
2013-09-26 21:10:16 -05:00
|
|
|
match self.resolve_path(expr.id, path, ValueNS, true) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(def) => {
|
2012-05-22 12:54:12 -05:00
|
|
|
// Write the result into the def map.
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving expr) resolved `{}`",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.path_names_to_string(path));
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
self.record_def(expr.id, def);
|
|
|
|
}
|
2012-08-20 14:23:37 -05:00
|
|
|
None => {
|
2014-09-30 19:11:34 -05:00
|
|
|
let wrong_name = self.path_names_to_string(path);
|
2013-09-27 21:46:09 -05:00
|
|
|
// Be helpful if the name refers to a struct
|
|
|
|
// (The pattern matching def_tys where the id is in self.structs
|
|
|
|
// matches on regular structs while excluding tuple- and enum-like
|
|
|
|
// structs, which wouldn't result in this error.)
|
|
|
|
match self.with_no_errors(|this|
|
|
|
|
this.resolve_path(expr.id, path, TypeNS, false)) {
|
2014-09-15 16:13:00 -05:00
|
|
|
Some((DefTy(struct_id, _), _))
|
2014-05-28 11:24:28 -05:00
|
|
|
if self.structs.contains_key(&struct_id) => {
|
|
|
|
self.resolve_error(expr.span,
|
|
|
|
format!("`{}` is a structure name, but \
|
|
|
|
this expression \
|
|
|
|
uses it like a function name",
|
|
|
|
wrong_name).as_slice());
|
|
|
|
|
|
|
|
self.session.span_note(expr.span,
|
|
|
|
format!("Did you mean to write: \
|
|
|
|
`{} {{ /* fields */ }}`?",
|
|
|
|
wrong_name).as_slice());
|
|
|
|
|
2013-02-23 02:22:51 -06:00
|
|
|
}
|
2014-05-08 16:35:09 -05:00
|
|
|
_ => {
|
|
|
|
let mut method_scope = false;
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.iter().rev().all(|rib| {
|
2014-05-08 16:35:09 -05:00
|
|
|
let res = match *rib {
|
|
|
|
Rib { bindings: _, kind: MethodRibKind(_, _) } => true,
|
2014-05-31 00:54:04 -05:00
|
|
|
Rib { bindings: _, kind: ItemRibKind } => false,
|
2014-05-08 16:35:09 -05:00
|
|
|
_ => return true, // Keep advancing
|
|
|
|
};
|
|
|
|
|
|
|
|
method_scope = res;
|
|
|
|
false // Stop advancing
|
|
|
|
});
|
|
|
|
|
2014-07-06 18:02:48 -05:00
|
|
|
if method_scope && token::get_name(self.self_name).get()
|
|
|
|
== wrong_name.as_slice() {
|
2014-05-16 12:45:16 -05:00
|
|
|
self.resolve_error(
|
|
|
|
expr.span,
|
|
|
|
"`self` is not available \
|
|
|
|
in a static method. Maybe a \
|
|
|
|
`self` argument is missing?");
|
2014-05-08 16:35:09 -05:00
|
|
|
} else {
|
2014-06-30 20:02:14 -05:00
|
|
|
let last_name = path.segments.last().unwrap().identifier.name;
|
|
|
|
let mut msg = match self.find_fallback_in_self_type(last_name) {
|
2014-05-08 16:35:09 -05:00
|
|
|
NoSuggestion => {
|
|
|
|
// limit search to 5 to reduce the number
|
|
|
|
// of stupid suggestions
|
|
|
|
self.find_best_match_for_name(wrong_name.as_slice(), 5)
|
2014-05-25 05:17:19 -05:00
|
|
|
.map_or("".to_string(),
|
2014-05-08 16:35:09 -05:00
|
|
|
|x| format!("`{}`", x))
|
|
|
|
}
|
|
|
|
Field =>
|
|
|
|
format!("`self.{}`", wrong_name),
|
|
|
|
Method
|
2014-08-04 15:56:56 -05:00
|
|
|
| TraitItem =>
|
2014-05-08 16:35:09 -05:00
|
|
|
format!("to call `self.{}`", wrong_name),
|
2014-10-14 19:33:20 -05:00
|
|
|
TraitMethod(path_str)
|
2014-05-08 16:35:09 -05:00
|
|
|
| StaticMethod(path_str) =>
|
|
|
|
format!("to call `{}::{}`", path_str, wrong_name)
|
|
|
|
};
|
|
|
|
|
|
|
|
if msg.len() > 0 {
|
|
|
|
msg = format!(" Did you mean {}?", msg)
|
|
|
|
}
|
|
|
|
|
2014-05-16 12:45:16 -05:00
|
|
|
self.resolve_error(
|
|
|
|
expr.span,
|
|
|
|
format!("unresolved name `{}`.{}",
|
|
|
|
wrong_name,
|
|
|
|
msg).as_slice());
|
2014-05-08 16:35:09 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-22 13:40:42 -05:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_expr(self, expr);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2014-10-04 08:44:50 -05:00
|
|
|
ExprFnBlock(capture_clause, ref fn_decl, ref block) => {
|
|
|
|
self.capture_mode_map.insert(expr.id, capture_clause);
|
2014-09-17 21:45:21 -05:00
|
|
|
self.resolve_function(ClosureRibKind(expr.id, ast::DUMMY_NODE_ID),
|
|
|
|
Some(&**fn_decl), NoTypeParameters,
|
|
|
|
&**block);
|
|
|
|
}
|
|
|
|
ExprProc(ref fn_decl, ref block) => {
|
2014-09-29 18:06:13 -05:00
|
|
|
self.capture_mode_map.insert(expr.id, ast::CaptureByValue);
|
2014-09-17 21:45:21 -05:00
|
|
|
self.resolve_function(ClosureRibKind(expr.id, block.id),
|
2014-09-14 16:40:45 -05:00
|
|
|
Some(&**fn_decl), NoTypeParameters,
|
|
|
|
&**block);
|
|
|
|
}
|
2014-09-17 21:45:21 -05:00
|
|
|
ExprUnboxedFn(capture_clause, _, ref fn_decl, ref block) => {
|
2014-09-29 18:06:13 -05:00
|
|
|
self.capture_mode_map.insert(expr.id, capture_clause);
|
2014-09-17 21:45:21 -05:00
|
|
|
self.resolve_function(ClosureRibKind(expr.id, block.id),
|
2014-09-07 12:09:06 -05:00
|
|
|
Some(&**fn_decl), NoTypeParameters,
|
|
|
|
&**block);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-09-01 20:45:37 -05:00
|
|
|
ExprStruct(ref path, _, _) => {
|
2014-07-04 18:45:47 -05:00
|
|
|
// Resolve the path to the structure it goes to. We don't
|
|
|
|
// check to ensure that the path is actually a structure; that
|
|
|
|
// is checked later during typeck.
|
2013-09-26 21:10:16 -05:00
|
|
|
match self.resolve_path(expr.id, path, TypeNS, false) {
|
2014-07-04 18:45:47 -05:00
|
|
|
Some(definition) => self.record_def(expr.id, definition),
|
2013-08-06 23:50:23 -05:00
|
|
|
result => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(resolving expression) didn't find struct \
|
2014-10-15 01:25:34 -05:00
|
|
|
def: {}", result);
|
2013-09-28 00:38:08 -05:00
|
|
|
let msg = format!("`{}` does not name a structure",
|
2014-09-30 19:11:34 -05:00
|
|
|
self.path_names_to_string(path));
|
2014-05-16 12:45:16 -05:00
|
|
|
self.resolve_error(path.span, msg.as_slice());
|
2012-07-23 20:44:59 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_expr(self, expr);
|
2012-07-23 20:44:59 -05:00
|
|
|
}
|
|
|
|
|
2014-07-25 19:12:51 -05:00
|
|
|
ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => {
|
2013-11-21 17:42:55 -06:00
|
|
|
self.with_label_rib(|this| {
|
2013-09-26 21:10:16 -05:00
|
|
|
let def_like = DlDef(DefLabel(expr.id));
|
2014-03-20 21:49:20 -05:00
|
|
|
|
2013-12-21 15:58:11 -06:00
|
|
|
{
|
2014-09-29 18:06:13 -05:00
|
|
|
let rib = this.label_ribs.last_mut().unwrap();
|
2014-02-24 14:47:19 -06:00
|
|
|
let renamed = mtwt::resolve(label);
|
2014-09-29 18:06:13 -05:00
|
|
|
rib.bindings.insert(renamed, def_like);
|
2013-12-21 15:58:11 -06:00
|
|
|
}
|
2012-08-14 21:20:56 -05:00
|
|
|
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_expr(this, expr);
|
2013-11-21 17:42:55 -06:00
|
|
|
})
|
2012-08-14 21:20:56 -05:00
|
|
|
}
|
|
|
|
|
2014-07-21 22:54:28 -05:00
|
|
|
ExprForLoop(ref pattern, ref head, ref body, optional_label) => {
|
|
|
|
self.resolve_expr(&**head);
|
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.push(Rib::new(NormalRibKind));
|
2014-07-21 22:54:28 -05:00
|
|
|
|
|
|
|
self.resolve_pattern(&**pattern,
|
|
|
|
LocalIrrefutableMode,
|
|
|
|
&mut HashMap::new());
|
|
|
|
|
|
|
|
match optional_label {
|
|
|
|
None => {}
|
|
|
|
Some(label) => {
|
|
|
|
self.label_ribs
|
|
|
|
.push(Rib::new(NormalRibKind));
|
|
|
|
let def_like = DlDef(DefLabel(expr.id));
|
|
|
|
|
|
|
|
{
|
2014-09-29 18:06:13 -05:00
|
|
|
let rib = self.label_ribs.last_mut().unwrap();
|
2014-07-21 22:54:28 -05:00
|
|
|
let renamed = mtwt::resolve(label);
|
2014-09-29 18:06:13 -05:00
|
|
|
rib.bindings.insert(renamed, def_like);
|
2014-07-21 22:54:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.resolve_block(&**body);
|
|
|
|
|
|
|
|
if optional_label.is_some() {
|
2014-09-29 18:06:13 -05:00
|
|
|
drop(self.label_ribs.pop())
|
2014-07-21 22:54:28 -05:00
|
|
|
}
|
|
|
|
|
2014-09-29 18:06:13 -05:00
|
|
|
self.value_ribs.pop();
|
2014-07-21 22:54:28 -05:00
|
|
|
}
|
2013-07-29 19:25:00 -05:00
|
|
|
|
2013-09-01 20:45:37 -05:00
|
|
|
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
|
2014-02-24 14:47:19 -06:00
|
|
|
let renamed = mtwt::resolve(label);
|
2014-09-29 18:06:13 -05:00
|
|
|
match self.search_ribs(self.label_ribs.as_slice(),
|
2014-04-22 11:06:43 -05:00
|
|
|
renamed, expr.span) {
|
2014-05-16 12:45:16 -05:00
|
|
|
None => {
|
|
|
|
self.resolve_error(
|
|
|
|
expr.span,
|
|
|
|
format!("use of undeclared label `{}`",
|
|
|
|
token::get_ident(label)).as_slice())
|
|
|
|
}
|
2013-09-01 20:45:37 -05:00
|
|
|
Some(DlDef(def @ DefLabel(_))) => {
|
2014-02-11 13:19:18 -06:00
|
|
|
// Since this def is a label, it is never read.
|
|
|
|
self.record_def(expr.id, (def, LastMod(AllPublic)))
|
2013-05-10 17:15:06 -05:00
|
|
|
}
|
|
|
|
Some(_) => {
|
2012-08-14 21:20:56 -05:00
|
|
|
self.session.span_bug(expr.span,
|
2013-05-19 00:07:44 -05:00
|
|
|
"label wasn't mapped to a \
|
|
|
|
label def!")
|
2013-05-10 17:15:06 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => {
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_expr(self, expr);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-06 06:00:46 -06:00
|
|
|
fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
|
2012-08-06 14:34:08 -05:00
|
|
|
match expr.node {
|
2013-09-01 20:45:37 -05:00
|
|
|
ExprField(_, ident, _) => {
|
2013-06-01 17:31:56 -05:00
|
|
|
// FIXME(#6890): Even though you can't treat a method like a
|
|
|
|
// field, we need to add any trait methods we find that match
|
|
|
|
// the field name so that we can do some nice error reporting
|
|
|
|
// later on in typeck.
|
2014-06-13 16:56:42 -05:00
|
|
|
let traits = self.search_for_traits_containing_method(ident.node.name);
|
2014-02-24 02:36:24 -06:00
|
|
|
self.trait_map.insert(expr.id, traits);
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
2014-02-26 08:06:45 -06:00
|
|
|
ExprMethodCall(ident, _, _) => {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(recording candidate traits for expr) recording \
|
2013-09-28 00:38:08 -05:00
|
|
|
traits for {}",
|
2013-06-18 11:39:16 -05:00
|
|
|
expr.id);
|
2014-04-23 16:19:23 -05:00
|
|
|
let traits = self.search_for_traits_containing_method(ident.node.name);
|
2014-02-24 02:36:24 -06:00
|
|
|
self.trait_map.insert(expr.id, traits);
|
2012-11-30 13:18:25 -06:00
|
|
|
}
|
2012-07-27 21:32:42 -05:00
|
|
|
_ => {
|
2012-07-11 17:00:40 -05:00
|
|
|
// Nothing to do.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-22 11:06:43 -05:00
|
|
|
fn search_for_traits_containing_method(&mut self, name: Name) -> Vec<DefId> {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("(searching for traits containing method) looking for '{}'",
|
2014-04-22 11:06:43 -05:00
|
|
|
token::get_name(name));
|
|
|
|
|
|
|
|
fn add_trait_info(found_traits: &mut Vec<DefId>,
|
|
|
|
trait_def_id: DefId,
|
|
|
|
name: Name) {
|
|
|
|
debug!("(adding trait info) found trait {}:{} for method '{}'",
|
|
|
|
trait_def_id.krate,
|
|
|
|
trait_def_id.node,
|
|
|
|
token::get_name(name));
|
|
|
|
found_traits.push(trait_def_id);
|
|
|
|
}
|
2012-10-08 14:39:30 -05:00
|
|
|
|
2014-03-04 12:02:49 -06:00
|
|
|
let mut found_traits = Vec::new();
|
2014-04-14 03:30:59 -05:00
|
|
|
let mut search_module = self.current_module.clone();
|
2014-04-22 11:06:43 -05:00
|
|
|
loop {
|
|
|
|
// Look for the current trait.
|
2014-05-08 16:35:09 -05:00
|
|
|
match self.current_trait_ref {
|
|
|
|
Some((trait_def_id, _)) => {
|
2014-09-29 18:06:13 -05:00
|
|
|
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
2014-05-08 16:35:09 -05:00
|
|
|
add_trait_info(&mut found_traits, trait_def_id, name);
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
}
|
2014-05-08 16:35:09 -05:00
|
|
|
None => {} // Nothing to do.
|
2014-04-22 11:06:43 -05:00
|
|
|
}
|
2012-07-11 17:00:40 -05:00
|
|
|
|
2014-04-22 11:06:43 -05:00
|
|
|
// Look for trait children.
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&search_module);
|
2013-12-21 17:32:44 -06:00
|
|
|
|
2014-04-22 11:06:43 -05:00
|
|
|
{
|
2014-04-14 03:30:59 -05:00
|
|
|
for (_, child_names) in search_module.children.borrow().iter() {
|
2014-01-06 18:48:13 -06:00
|
|
|
let def = match child_names.def_for_namespace(TypeNS) {
|
|
|
|
Some(def) => def,
|
|
|
|
None => continue
|
|
|
|
};
|
|
|
|
let trait_def_id = match def {
|
|
|
|
DefTrait(trait_def_id) => trait_def_id,
|
|
|
|
_ => continue,
|
|
|
|
};
|
2014-09-29 18:06:13 -05:00
|
|
|
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
2014-04-22 11:06:43 -05:00
|
|
|
add_trait_info(&mut found_traits, trait_def_id, name);
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
}
|
2014-04-22 11:06:43 -05:00
|
|
|
}
|
2012-07-11 17:00:40 -05:00
|
|
|
|
2014-04-22 11:06:43 -05:00
|
|
|
// Look for imports.
|
2014-04-14 03:30:59 -05:00
|
|
|
for (_, import) in search_module.import_resolutions.borrow().iter() {
|
2014-04-22 11:06:43 -05:00
|
|
|
let target = match import.target_for_namespace(TypeNS) {
|
|
|
|
None => continue,
|
|
|
|
Some(target) => target,
|
|
|
|
};
|
|
|
|
let did = match target.bindings.def_for_namespace(TypeNS) {
|
|
|
|
Some(DefTrait(trait_def_id)) => trait_def_id,
|
|
|
|
Some(..) | None => continue,
|
|
|
|
};
|
2014-09-29 18:06:13 -05:00
|
|
|
if self.trait_item_map.contains_key(&(name, did)) {
|
2014-04-22 11:06:43 -05:00
|
|
|
add_trait_info(&mut found_traits, did, name);
|
2014-04-14 03:30:59 -05:00
|
|
|
self.used_imports.insert((import.type_id, TypeNS));
|
2014-09-11 12:14:43 -05:00
|
|
|
match target.target_module.def_id.get() {
|
|
|
|
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
|
|
|
|
_ => {}
|
|
|
|
}
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
2014-04-22 11:06:43 -05:00
|
|
|
}
|
2013-05-20 11:41:20 -05:00
|
|
|
|
2014-04-14 03:30:59 -05:00
|
|
|
match search_module.parent_link.clone() {
|
2014-04-22 11:06:43 -05:00
|
|
|
NoParentLink | ModuleParentLink(..) => break,
|
|
|
|
BlockParentLink(parent_module, _) => {
|
2014-04-14 03:30:59 -05:00
|
|
|
search_module = parent_module.upgrade().unwrap();
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
2014-04-22 11:06:43 -05:00
|
|
|
}
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
|
2014-04-22 11:06:43 -05:00
|
|
|
found_traits
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
|
2014-10-15 01:25:34 -05:00
|
|
|
debug!("(recording def) recording {} for {}, last private {}",
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
def, node_id, lp);
|
2014-02-11 13:19:18 -06:00
|
|
|
assert!(match lp {LastImport{..} => false, _ => true},
|
|
|
|
"Import should only be used for `use` directives");
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
self.last_private.insert(node_id, lp);
|
2014-09-18 16:05:52 -05:00
|
|
|
|
|
|
|
match self.def_map.borrow_mut().entry(node_id) {
|
2013-09-06 21:11:55 -05:00
|
|
|
// Resolve appears to "resolve" the same ID multiple
|
|
|
|
// times, so here is a sanity check it at least comes to
|
|
|
|
// the same conclusion! - nmatsakis
|
2014-09-18 16:05:52 -05:00
|
|
|
Occupied(entry) => if def != *entry.get() {
|
2014-05-16 12:45:16 -05:00
|
|
|
self.session
|
2014-10-15 01:25:34 -05:00
|
|
|
.bug(format!("node_id {} resolved first to {} and \
|
|
|
|
then {}",
|
2014-05-16 12:45:16 -05:00
|
|
|
node_id,
|
2014-09-18 16:05:52 -05:00
|
|
|
*entry.get(),
|
2014-05-16 12:45:16 -05:00
|
|
|
def).as_slice());
|
2014-09-18 16:05:52 -05:00
|
|
|
},
|
|
|
|
Vacant(entry) => { entry.set(def); },
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-10-02 07:33:01 -05:00
|
|
|
fn enforce_default_binding_mode(&mut self,
|
2013-09-30 12:37:17 -05:00
|
|
|
pat: &Pat,
|
2013-09-01 20:45:37 -05:00
|
|
|
pat_binding_mode: BindingMode,
|
2013-05-31 17:17:22 -05:00
|
|
|
descr: &str) {
|
2013-01-24 18:24:45 -06:00
|
|
|
match pat_binding_mode {
|
2013-10-20 07:31:23 -05:00
|
|
|
BindByValue(_) => {}
|
2013-11-28 14:22:53 -06:00
|
|
|
BindByRef(..) => {
|
2014-05-16 12:45:16 -05:00
|
|
|
self.resolve_error(pat.span,
|
|
|
|
format!("cannot use `ref` binding mode \
|
|
|
|
with {}",
|
|
|
|
descr).as_slice());
|
2013-01-24 18:24:45 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-06 21:06:58 -05:00
|
|
|
//
|
|
|
|
// Unused import checking
|
|
|
|
//
|
2014-02-11 13:19:18 -06:00
|
|
|
// Although this is mostly a lint pass, it lives in here because it depends on
|
|
|
|
// resolve data structures and because it finalises the privacy information for
|
|
|
|
// `use` directives.
|
2012-07-06 21:06:58 -05:00
|
|
|
//
|
|
|
|
|
2014-02-11 13:19:18 -06:00
|
|
|
fn check_for_unused_imports(&mut self, krate: &ast::Crate) {
|
2013-08-13 11:52:41 -05:00
|
|
|
let mut visitor = UnusedImportCheckVisitor{ resolver: self };
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_crate(&mut visitor, krate);
|
2013-02-25 11:12:22 -06:00
|
|
|
}
|
|
|
|
|
2014-02-11 13:19:18 -06:00
|
|
|
fn check_for_item_unused_imports(&mut self, vi: &ViewItem) {
|
Extract privacy checking from name resolution
This commit is the culmination of my recent effort to refine Rust's notion of
privacy and visibility among crates. The major goals of this commit were to
remove privacy checking from resolve for the sake of sane error messages, and to
attempt a much more rigid and well-tested implementation of visibility
throughout rust. The implemented rules for name visibility are:
1. Everything pub from the root namespace is visible to anyone
2. You may access any private item of your ancestors.
"Accessing a private item" depends on what the item is, so for a function this
means that you can call it, but for a module it means that you can look inside
of it. Once you look inside a private module, any accessed item must be "pub
from the root" where the new root is the private module that you looked into.
These rules required some more analysis results to get propagated from trans to
privacy in the form of a few hash tables.
I added a new test in which my goal was to showcase all of the privacy nuances
of the language, and I hope to place any new bugs into this file to prevent
regressions.
Overall, I was unable to completely remove the notion of privacy from resolve.
One use of privacy is for dealing with glob imports. Essentially a glob import
can only import *public* items from the destination, and because this must be
done at namespace resolution time, resolve must maintain the notion of "what
items are public in a module". There are some sad approximations of privacy, but
I unfortunately can't see clear methods to extract them outside.
The other use case of privacy in resolve now is one that must stick around
regardless of glob imports. When dealing with privacy, checking a private path
needs to know "what the last private thing was" when looking at a path. Resolve
is the only compiler pass which knows the answer to this question, so it
maintains the answer on a per-path resolution basis (works similarly to the
def_map generated).
Closes #8215
2013-10-05 16:37:39 -05:00
|
|
|
// Ignore is_public import statements because there's no way to be sure
|
2013-04-30 00:15:17 -05:00
|
|
|
// whether they're used or not. Also ignore imports with a dummy span
|
|
|
|
// because this means that they were generated in some fashion by the
|
|
|
|
// compiler and we don't need to consider them.
|
2014-01-09 07:05:33 -06:00
|
|
|
if vi.vis == Public { return }
|
2014-01-01 00:53:22 -06:00
|
|
|
if vi.span == DUMMY_SP { return }
|
2013-04-30 00:15:17 -05:00
|
|
|
|
|
|
|
match vi.node {
|
2014-09-11 12:14:43 -05:00
|
|
|
ViewItemExternCrate(_, _, id) => {
|
|
|
|
match self.session.cstore.find_extern_mod_stmt_cnum(id)
|
|
|
|
{
|
|
|
|
Some(crate_num) => if !self.used_crates.contains(&crate_num) {
|
2014-10-14 13:37:16 -05:00
|
|
|
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
|
2014-09-11 12:14:43 -05:00
|
|
|
id,
|
|
|
|
vi.span,
|
|
|
|
"unused extern crate".to_string());
|
|
|
|
},
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
},
|
2014-04-26 08:33:45 -05:00
|
|
|
ViewItemUse(ref p) => {
|
|
|
|
match p.node {
|
|
|
|
ViewPathSimple(_, _, id) => self.finalize_import(id, p.span),
|
2014-09-11 12:14:43 -05:00
|
|
|
|
2014-04-26 08:33:45 -05:00
|
|
|
ViewPathList(_, ref list, _) => {
|
|
|
|
for i in list.iter() {
|
2014-07-17 17:56:56 -05:00
|
|
|
self.finalize_import(i.node.id(), i.span);
|
2014-04-26 08:33:45 -05:00
|
|
|
}
|
|
|
|
},
|
|
|
|
ViewPathGlob(_, id) => {
|
|
|
|
if !self.used_imports.contains(&(id, TypeNS)) &&
|
|
|
|
!self.used_imports.contains(&(id, ValueNS)) {
|
2014-05-09 20:45:36 -05:00
|
|
|
self.session
|
2014-06-13 15:13:05 -05:00
|
|
|
.add_lint(lint::builtin::UNUSED_IMPORTS,
|
2014-05-09 20:45:36 -05:00
|
|
|
id,
|
|
|
|
p.span,
|
2014-05-25 05:17:19 -05:00
|
|
|
"unused import".to_string());
|
2014-04-26 08:33:45 -05:00
|
|
|
}
|
|
|
|
},
|
2012-07-06 21:06:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-11 13:19:18 -06:00
|
|
|
// We have information about whether `use` (import) directives are actually used now.
|
|
|
|
// If an import is not used at all, we signal a lint error. If an import is only used
|
|
|
|
// for a single namespace, we remove the other namespace from the recorded privacy
|
|
|
|
// information. That means in privacy.rs, we will only check imports and namespaces
|
|
|
|
// which are used. In particular, this means that if an import could name either a
|
|
|
|
// public or private item, we will check the correct thing, dependent on how the import
|
|
|
|
// is used.
|
|
|
|
fn finalize_import(&mut self, id: NodeId, span: Span) {
|
2014-05-09 20:45:36 -05:00
|
|
|
debug!("finalizing import uses for {}",
|
|
|
|
self.session.codemap().span_to_snippet(span));
|
2014-02-11 13:19:18 -06:00
|
|
|
|
|
|
|
if !self.used_imports.contains(&(id, TypeNS)) &&
|
|
|
|
!self.used_imports.contains(&(id, ValueNS)) {
|
2014-06-13 15:13:05 -05:00
|
|
|
self.session.add_lint(lint::builtin::UNUSED_IMPORTS,
|
2014-05-09 20:45:36 -05:00
|
|
|
id,
|
|
|
|
span,
|
2014-05-25 05:17:19 -05:00
|
|
|
"unused import".to_string());
|
2014-02-11 13:19:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
let (v_priv, t_priv) = match self.last_private.find(&id) {
|
2014-05-09 20:45:36 -05:00
|
|
|
Some(&LastImport {
|
|
|
|
value_priv: v,
|
|
|
|
value_used: _,
|
|
|
|
type_priv: t,
|
|
|
|
type_used: _
|
|
|
|
}) => (v, t),
|
|
|
|
Some(_) => {
|
2014-10-09 14:17:22 -05:00
|
|
|
panic!("we should only have LastImport for `use` directives")
|
2014-05-09 20:45:36 -05:00
|
|
|
}
|
2014-02-11 13:19:18 -06:00
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut v_used = if self.used_imports.contains(&(id, ValueNS)) {
|
|
|
|
Used
|
|
|
|
} else {
|
|
|
|
Unused
|
|
|
|
};
|
|
|
|
let t_used = if self.used_imports.contains(&(id, TypeNS)) {
|
|
|
|
Used
|
|
|
|
} else {
|
|
|
|
Unused
|
|
|
|
};
|
|
|
|
|
|
|
|
match (v_priv, t_priv) {
|
|
|
|
// Since some items may be both in the value _and_ type namespaces (e.g., structs)
|
|
|
|
// we might have two LastPrivates pointing at the same thing. There is no point
|
|
|
|
// checking both, so lets not check the value one.
|
|
|
|
(Some(DependsOn(def_v)), Some(DependsOn(def_t))) if def_v == def_t => v_used = Unused,
|
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
|
|
|
|
self.last_private.insert(id, LastImport{value_priv: v_priv,
|
|
|
|
value_used: v_used,
|
|
|
|
type_priv: t_priv,
|
|
|
|
type_used: t_used});
|
|
|
|
}
|
|
|
|
|
2012-05-22 12:54:12 -05:00
|
|
|
//
|
|
|
|
// Diagnostics
|
|
|
|
//
|
|
|
|
// Diagnostics are not particularly efficient, because they're rarely
|
|
|
|
// hit.
|
|
|
|
//
|
|
|
|
|
2012-12-29 12:25:09 -06:00
|
|
|
/// A somewhat inefficient routine to obtain the name of a module.
|
2014-06-21 05:39:03 -05:00
|
|
|
fn module_to_string(&self, module: &Module) -> String {
|
2014-09-30 19:11:34 -05:00
|
|
|
let mut names = Vec::new();
|
2014-04-14 03:30:59 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
fn collect_mod(names: &mut Vec<ast::Name>, module: &Module) {
|
2014-04-14 03:30:59 -05:00
|
|
|
match module.parent_link {
|
|
|
|
NoParentLink => {}
|
|
|
|
ModuleParentLink(ref module, name) => {
|
2014-09-30 19:11:34 -05:00
|
|
|
names.push(name);
|
|
|
|
collect_mod(names, &*module.upgrade().unwrap());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-04-14 03:30:59 -05:00
|
|
|
BlockParentLink(ref module, _) => {
|
2014-07-06 18:02:48 -05:00
|
|
|
// danger, shouldn't be ident?
|
2014-09-30 19:11:34 -05:00
|
|
|
names.push(special_idents::opaque.name);
|
|
|
|
collect_mod(names, &*module.upgrade().unwrap());
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-09-30 19:11:34 -05:00
|
|
|
collect_mod(&mut names, module);
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
if names.len() == 0 {
|
2014-05-25 05:17:19 -05:00
|
|
|
return "???".to_string();
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
2014-09-30 19:11:34 -05:00
|
|
|
self.names_to_string(names.into_iter().rev()
|
|
|
|
.collect::<Vec<ast::Name>>()
|
|
|
|
.as_slice())
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-12-08 01:55:28 -06:00
|
|
|
#[allow(dead_code)] // useful for debugging
|
2014-04-14 03:30:59 -05:00
|
|
|
fn dump_module(&mut self, module_: Rc<Module>) {
|
2014-06-21 05:39:03 -05:00
|
|
|
debug!("Dump of module `{}`:", self.module_to_string(&*module_));
|
2012-05-22 12:54:12 -05:00
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("Children:");
|
2014-04-14 03:30:59 -05:00
|
|
|
self.populate_module_if_necessary(&module_);
|
2014-03-20 21:49:20 -05:00
|
|
|
for (&name, _) in module_.children.borrow().iter() {
|
2014-02-13 23:07:09 -06:00
|
|
|
debug!("* {}", token::get_name(name));
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("Import resolutions:");
|
2013-12-21 17:15:54 -06:00
|
|
|
let import_resolutions = module_.import_resolutions.borrow();
|
2014-03-20 21:49:20 -05:00
|
|
|
for (&name, import_resolution) in import_resolutions.iter() {
|
2013-04-30 15:35:01 -05:00
|
|
|
let value_repr;
|
2013-03-21 03:10:57 -05:00
|
|
|
match import_resolution.target_for_namespace(ValueNS) {
|
2014-05-25 05:10:11 -05:00
|
|
|
None => { value_repr = "".to_string(); }
|
2012-08-26 14:12:05 -05:00
|
|
|
Some(_) => {
|
2014-05-25 05:10:11 -05:00
|
|
|
value_repr = " value:?".to_string();
|
2013-02-14 20:37:25 -06:00
|
|
|
// FIXME #4954
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-30 15:35:01 -05:00
|
|
|
let type_repr;
|
2013-03-21 03:10:57 -05:00
|
|
|
match import_resolution.target_for_namespace(TypeNS) {
|
2014-05-25 05:10:11 -05:00
|
|
|
None => { type_repr = "".to_string(); }
|
2012-08-26 14:12:05 -05:00
|
|
|
Some(_) => {
|
2014-05-25 05:10:11 -05:00
|
|
|
type_repr = " type:?".to_string();
|
2013-02-14 20:37:25 -06:00
|
|
|
// FIXME #4954
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-13 23:07:09 -06:00
|
|
|
debug!("* {}:{}{}", token::get_name(name), value_repr, type_repr);
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub struct CrateMap {
|
2014-03-28 12:05:27 -05:00
|
|
|
pub def_map: DefMap,
|
2014-09-17 21:45:21 -05:00
|
|
|
pub freevars: RefCell<FreevarMap>,
|
|
|
|
pub capture_mode_map: RefCell<CaptureModeMap>,
|
2014-03-28 12:05:27 -05:00
|
|
|
pub exp_map2: ExportMap2,
|
|
|
|
pub trait_map: TraitMap,
|
|
|
|
pub external_exports: ExternalExports,
|
|
|
|
pub last_private_map: LastPrivateMap,
|
2013-02-19 01:40:42 -06:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Entry point to crate resolution.
|
2014-03-05 08:36:01 -06:00
|
|
|
pub fn resolve_crate(session: &Session,
|
2014-06-06 08:51:42 -05:00
|
|
|
_: &LanguageItems,
|
2014-02-05 15:15:24 -06:00
|
|
|
krate: &Crate)
|
2013-02-19 01:40:42 -06:00
|
|
|
-> CrateMap {
|
2014-06-06 08:51:42 -05:00
|
|
|
let mut resolver = Resolver::new(session, krate.span);
|
2014-02-05 15:15:24 -06:00
|
|
|
resolver.resolve(krate);
|
2013-02-19 01:40:42 -06:00
|
|
|
CrateMap {
|
2014-09-17 21:45:21 -05:00
|
|
|
def_map: resolver.def_map,
|
|
|
|
freevars: resolver.freevars,
|
2014-09-29 18:06:13 -05:00
|
|
|
capture_mode_map: RefCell::new(resolver.capture_mode_map),
|
2014-09-17 21:45:21 -05:00
|
|
|
exp_map2: resolver.export_map2,
|
|
|
|
trait_map: resolver.trait_map,
|
|
|
|
external_exports: resolver.external_exports,
|
|
|
|
last_private_map: resolver.last_private,
|
2013-02-19 01:40:42 -06:00
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|