rustc: combine partial_def_map and last_private_map into def_map.

This commit is contained in:
Eduard Burtescu 2015-02-17 06:44:23 +02:00
parent 06f362aeb3
commit 5a6a9ed792
38 changed files with 442 additions and 447 deletions

View file

@ -406,7 +406,7 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
fn check_def(&mut self, sp: Span, id: ast::NodeId) { fn check_def(&mut self, sp: Span, id: ast::NodeId) {
match self.cx.tcx.def_map.borrow()[id].clone() { match self.cx.tcx.def_map.borrow()[id].full_def() {
def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => { def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => {
self.cx.span_lint(IMPROPER_CTYPES, sp, self.cx.span_lint(IMPROPER_CTYPES, sp,
"found rust type `isize` in foreign module, while \ "found rust type `isize` in foreign module, while \
@ -1000,7 +1000,8 @@ impl LintPass for NonSnakeCase {
fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
if let &ast::PatIdent(_, ref path1, _) = &p.node { if let &ast::PatIdent(_, ref path1, _) = &p.node {
if let Some(&def::DefLocal(_)) = cx.tcx.def_map.borrow().get(&p.id) { let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
if let Some(def::DefLocal(_)) = def {
self.check_snake_case(cx, "variable", path1.node, p.span); self.check_snake_case(cx, "variable", path1.node, p.span);
} }
} }
@ -1065,8 +1066,8 @@ impl LintPass for NonUpperCaseGlobals {
fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
// Lint for constants that look like binding identifiers (#7526) // Lint for constants that look like binding identifiers (#7526)
match (&p.node, cx.tcx.def_map.borrow().get(&p.id)) { match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
(&ast::PatIdent(_, ref path1, _), Some(&def::DefConst(..))) => { (&ast::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => {
NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern", NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
path1.node, p.span); path1.node, p.span);
} }
@ -1226,10 +1227,13 @@ impl LintPass for NonShorthandFieldPatterns {
fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) { fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
let def_map = cx.tcx.def_map.borrow(); let def_map = cx.tcx.def_map.borrow();
if let ast::PatStruct(_, ref v, _) = pat.node { if let ast::PatStruct(_, ref v, _) = pat.node {
for fieldpat in v.iter() let field_pats = v.iter()
.filter(|fieldpat| !fieldpat.node.is_shorthand) .filter(|fieldpat| !fieldpat.node.is_shorthand)
.filter(|fieldpat| def_map.get(&fieldpat.node.pat.id) .filter(|fieldpat| {
== Some(&def::DefLocal(fieldpat.node.pat.id))) { let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
def == Some(def::DefLocal(fieldpat.node.pat.id))
});
for fieldpat in field_pats {
if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node { if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node {
if ident.node.as_str() == fieldpat.node.ident.as_str() { if ident.node.as_str() == fieldpat.node.ident.as_str() {
cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
@ -1908,10 +1912,7 @@ impl LintPass for UnconditionalRecursion {
_: ast::Ident, _: ast::Ident,
id: ast::NodeId) -> bool { id: ast::NodeId) -> bool {
tcx.def_map.borrow().get(&id) tcx.def_map.borrow().get(&id)
.map_or(false, |def| { .map_or(false, |def| def.def_id() == ast_util::local_def(fn_id))
let did = def.def_id();
ast_util::is_local(did) && did.node == fn_id
})
} }
// check if the method call `id` refers to method `method_id` // check if the method call `id` refers to method `method_id`

View file

@ -1870,9 +1870,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> { impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
fn visit_item(&mut self, item: &ast::Item) { fn visit_item(&mut self, item: &ast::Item) {
if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node { if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
let def_map = &self.ecx.tcx.def_map; let def_id = self.ecx.tcx.def_map.borrow()[trait_ref.ref_id].def_id();
let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
let def_id = trait_def.def_id();
// Load eagerly if this is an implementation of the Drop trait // Load eagerly if this is an implementation of the Drop trait
// or if the trait is not defined in this crate. // or if the trait is not defined in this crate.

View file

@ -65,7 +65,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
tcx.sess.span_bug(ast_ty.span, tcx.sess.span_bug(ast_ty.span,
&format!("unbound path {}", path.repr(tcx))) &format!("unbound path {}", path.repr(tcx)))
} }
Some(&d) => d Some(d) => d.full_def()
}; };
if let def::DefPrimTy(nty) = def { if let def::DefPrimTy(nty) = def {
Some(prim_ty_to_ty(tcx, &path.segments[], nty)) Some(prim_ty_to_ty(tcx, &path.segments[], nty))

View file

@ -25,6 +25,7 @@ use metadata::tydecode::{RegionParameter, ClosureSource};
use metadata::tyencode; use metadata::tyencode;
use middle::check_const::ConstQualif; use middle::check_const::ConstQualif;
use middle::mem_categorization::Typer; use middle::mem_categorization::Typer;
use middle::privacy::{AllPublic, LastMod};
use middle::subst; use middle::subst;
use middle::subst::VecPerParamSpace; use middle::subst::VecPerParamSpace;
use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin}; use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin};
@ -1148,10 +1149,10 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
debug!("Encoding side tables for id {}", id); debug!("Encoding side tables for id {}", id);
if let Some(def) = tcx.def_map.borrow().get(&id) { if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
rbml_w.tag(c::tag_table_def, |rbml_w| { rbml_w.tag(c::tag_table_def, |rbml_w| {
rbml_w.id(id); rbml_w.id(id);
rbml_w.tag(c::tag_table_val, |rbml_w| (*def).encode(rbml_w).unwrap()); rbml_w.tag(c::tag_table_val, |rbml_w| def.encode(rbml_w).unwrap());
}) })
} }
@ -1851,7 +1852,12 @@ fn decode_side_tables(dcx: &DecodeContext,
match value { match value {
c::tag_table_def => { c::tag_table_def => {
let def = decode_def(dcx, val_doc); let def = decode_def(dcx, val_doc);
dcx.tcx.def_map.borrow_mut().insert(id, def); dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution {
base_def: def,
// This doesn't matter cross-crate.
last_private: LastMod(AllPublic),
depth: 0
});
} }
c::tag_table_node_type => { c::tag_table_node_type => {
let ty = val_dsr.read_ty(dcx); let ty = val_dsr.read_ty(dcx);

View file

@ -610,32 +610,24 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn find_scope(&self, fn find_scope(&self,
expr: &ast::Expr, expr: &ast::Expr,
label: Option<ast::Ident>) -> LoopScope { label: Option<ast::Ident>) -> LoopScope {
match label { if label.is_none() {
None => { return *self.loop_scopes.last().unwrap();
return *self.loop_scopes.last().unwrap(); }
}
Some(_) => { match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
match self.tcx.def_map.borrow().get(&expr.id) { Some(def::DefLabel(loop_id)) => {
Some(&def::DefLabel(loop_id)) => { for l in &self.loop_scopes {
for l in &self.loop_scopes { if l.loop_id == loop_id {
if l.loop_id == loop_id { return *l;
return *l;
}
}
self.tcx.sess.span_bug(
expr.span,
&format!("no loop scope for id {}",
loop_id));
}
r => {
self.tcx.sess.span_bug(
expr.span,
&format!("bad entry `{:?}` in def_map for label",
r));
} }
} }
self.tcx.sess.span_bug(expr.span,
&format!("no loop scope for id {}", loop_id));
}
r => {
self.tcx.sess.span_bug(expr.span,
&format!("bad entry `{:?}` in def_map for label", r));
} }
} }
} }

View file

@ -440,7 +440,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
} }
} }
ast::ExprPath(_) | ast::ExprQPath(_) => { ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = v.tcx.def_map.borrow().get(&e.id).cloned(); let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
match def { match def {
Some(def::DefVariant(_, _, _)) => { Some(def::DefVariant(_, _, _)) => {
// Count the discriminator or function pointer. // Count the discriminator or function pointer.
@ -499,7 +499,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
_ => break _ => break
}; };
} }
let def = v.tcx.def_map.borrow().get(&callee.id).cloned(); let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
match def { match def {
Some(def::DefStruct(..)) => {} Some(def::DefStruct(..)) => {}
Some(def::DefVariant(..)) => { Some(def::DefVariant(..)) => {

View file

@ -242,7 +242,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => { ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
let pat_ty = ty::pat_ty(cx.tcx, p); let pat_ty = ty::pat_ty(cx.tcx, p);
if let ty::ty_enum(def_id, _) = pat_ty.sty { if let ty::ty_enum(def_id, _) = pat_ty.sty {
let def = cx.tcx.def_map.borrow().get(&p.id).cloned(); let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
if let Some(DefLocal(_)) = def { if let Some(DefLocal(_)) = def {
if ty::enum_variants(cx.tcx, def_id).iter().any(|variant| if ty::enum_variants(cx.tcx, def_id).iter().any(|variant|
token::get_name(variant.name) == token::get_name(ident.node.name) token::get_name(variant.name) == token::get_name(ident.node.name)
@ -434,7 +434,7 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> { fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
return match pat.node { return match pat.node {
ast::PatIdent(..) | ast::PatEnum(..) => { ast::PatIdent(..) | ast::PatEnum(..) => {
let def = self.tcx.def_map.borrow().get(&pat.id).cloned(); let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
match def { match def {
Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) { Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) {
Some(const_expr) => { Some(const_expr) => {
@ -733,28 +733,28 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
let pat = raw_pat(p); let pat = raw_pat(p);
match pat.node { match pat.node {
ast::PatIdent(..) => ast::PatIdent(..) =>
match cx.tcx.def_map.borrow().get(&pat.id) { match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(&DefConst(..)) => Some(DefConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \ cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"), been rewritten"),
Some(&DefStruct(_)) => vec!(Single), Some(DefStruct(_)) => vec!(Single),
Some(&DefVariant(_, id, _)) => vec!(Variant(id)), Some(DefVariant(_, id, _)) => vec!(Variant(id)),
_ => vec!() _ => vec!()
}, },
ast::PatEnum(..) => ast::PatEnum(..) =>
match cx.tcx.def_map.borrow().get(&pat.id) { match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(&DefConst(..)) => Some(DefConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \ cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"), been rewritten"),
Some(&DefVariant(_, id, _)) => vec!(Variant(id)), Some(DefVariant(_, id, _)) => vec!(Variant(id)),
_ => vec!(Single) _ => vec!(Single)
}, },
ast::PatStruct(..) => ast::PatStruct(..) =>
match cx.tcx.def_map.borrow().get(&pat.id) { match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(&DefConst(..)) => Some(DefConst(..)) =>
cx.tcx.sess.span_bug(pat.span, "const pattern should've \ cx.tcx.sess.span_bug(pat.span, "const pattern should've \
been rewritten"), been rewritten"),
Some(&DefVariant(_, id, _)) => vec!(Variant(id)), Some(DefVariant(_, id, _)) => vec!(Variant(id)),
_ => vec!(Single) _ => vec!(Single)
}, },
ast::PatLit(ref expr) => ast::PatLit(ref expr) =>
@ -847,7 +847,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
Some(repeat(DUMMY_WILD_PAT).take(arity).collect()), Some(repeat(DUMMY_WILD_PAT).take(arity).collect()),
ast::PatIdent(_, _, _) => { ast::PatIdent(_, _, _) => {
let opt_def = cx.tcx.def_map.borrow().get(&pat_id).cloned(); let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
match opt_def { match opt_def {
Some(DefConst(..)) => Some(DefConst(..)) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \ cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@ -862,7 +862,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
} }
ast::PatEnum(_, ref args) => { ast::PatEnum(_, ref args) => {
let def = cx.tcx.def_map.borrow()[pat_id].clone(); let def = cx.tcx.def_map.borrow()[pat_id].full_def();
match def { match def {
DefConst(..) => DefConst(..) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \ cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@ -880,7 +880,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
ast::PatStruct(_, ref pattern_fields, _) => { ast::PatStruct(_, ref pattern_fields, _) => {
// Is this a struct or an enum variant? // Is this a struct or an enum variant?
let def = cx.tcx.def_map.borrow()[pat_id].clone(); let def = cx.tcx.def_map.borrow()[pat_id].full_def();
let class_id = match def { let class_id = match def {
DefConst(..) => DefConst(..) =>
cx.tcx.sess.span_bug(pat_span, "const pattern should've \ cx.tcx.sess.span_bug(pat_span, "const pattern should've \

View file

@ -94,9 +94,9 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
fn visit_expr(&mut self, e: &ast::Expr) { fn visit_expr(&mut self, e: &ast::Expr) {
match e.node { match e.node {
ast::ExprPath(_) | ast::ExprQPath(_) => { ast::ExprPath(_) | ast::ExprQPath(_) => {
match self.def_map.borrow().get(&e.id) { match self.def_map.borrow().get(&e.id).map(|d| d.full_def()) {
Some(&DefStatic(def_id, _)) | Some(DefStatic(def_id, _)) |
Some(&DefConst(def_id)) if Some(DefConst(def_id)) if
ast_util::is_local(def_id) => { ast_util::is_local(def_id) => {
match self.ast_map.get(def_id.node) { match self.ast_map.get(def_id.node) {
ast_map::NodeItem(item) => ast_map::NodeItem(item) =>

View file

@ -31,7 +31,7 @@ use std::{i8, i16, i32, i64};
use std::rc::Rc; use std::rc::Rc;
fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> { fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
let opt_def = tcx.def_map.borrow().get(&e.id).cloned(); let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
match opt_def { match opt_def {
Some(def::DefConst(def_id)) => { Some(def::DefConst(def_id)) => {
lookup_const_by_id(tcx, def_id) lookup_const_by_id(tcx, def_id)
@ -148,11 +148,11 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()), ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()),
ast::ExprCall(ref callee, ref args) => { ast::ExprCall(ref callee, ref args) => {
let def = tcx.def_map.borrow()[callee.id].clone(); let def = tcx.def_map.borrow()[callee.id];
if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) { if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
entry.insert(def); entry.insert(def);
} }
let path = match def { let path = match def.full_def() {
def::DefStruct(def_id) => def_to_path(tcx, def_id), def::DefStruct(def_id) => def_to_path(tcx, def_id),
def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did), def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
_ => unreachable!() _ => unreachable!()
@ -179,7 +179,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
} }
ast::ExprPath(ref path) => { ast::ExprPath(ref path) => {
let opt_def = tcx.def_map.borrow().get(&expr.id).cloned(); let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
match opt_def { match opt_def {
Some(def::DefStruct(..)) => Some(def::DefStruct(..)) =>
ast::PatStruct(path.clone(), vec![], false), ast::PatStruct(path.clone(), vec![], false),
@ -389,7 +389,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
cast_const(val, ety) cast_const(val, ety)
} }
ast::ExprPath(_) | ast::ExprQPath(_) => { ast::ExprPath(_) | ast::ExprQPath(_) => {
let opt_def = tcx.def_map.borrow().get(&e.id).cloned(); let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
let (const_expr, const_ty) = match opt_def { let (const_expr, const_ty) = match opt_def {
Some(def::DefConst(def_id)) => { Some(def::DefConst(def_id)) => {
if ast_util::is_local(def_id) { if ast_util::is_local(def_id) {

View file

@ -71,13 +71,13 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) { fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) {
self.tcx.def_map.borrow().get(id).map(|def| { self.tcx.def_map.borrow().get(id).map(|def| {
match def { match def.full_def() {
&def::DefConst(_) => { def::DefConst(_) => {
self.check_def_id(def.def_id()) self.check_def_id(def.def_id())
} }
_ if self.ignore_non_const_paths => (), _ if self.ignore_non_const_paths => (),
&def::DefPrimTy(_) => (), def::DefPrimTy(_) => (),
&def::DefVariant(enum_id, variant_id, _) => { def::DefVariant(enum_id, variant_id, _) => {
self.check_def_id(enum_id); self.check_def_id(enum_id);
self.check_def_id(variant_id); self.check_def_id(variant_id);
} }
@ -158,7 +158,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn handle_field_pattern_match(&mut self, lhs: &ast::Pat, fn handle_field_pattern_match(&mut self, lhs: &ast::Pat,
pats: &[codemap::Spanned<ast::FieldPat>]) { pats: &[codemap::Spanned<ast::FieldPat>]) {
let id = match (*self.tcx.def_map.borrow())[lhs.id] { let id = match self.tcx.def_map.borrow()[lhs.id].full_def() {
def::DefVariant(_, id, _) => id, def::DefVariant(_, id, _) => id,
_ => { _ => {
match ty::ty_to_def_id(ty::node_id_to_type(self.tcx, match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,

View file

@ -11,6 +11,7 @@
pub use self::Def::*; pub use self::Def::*;
pub use self::MethodProvenance::*; pub use self::MethodProvenance::*;
use middle::privacy::LastPrivate;
use middle::subst::ParamSpace; use middle::subst::ParamSpace;
use util::nodemap::NodeMap; use util::nodemap::NodeMap;
use syntax::ast; use syntax::ast;
@ -51,24 +52,43 @@ pub enum Def {
DefMethod(ast::DefId /* method */, MethodProvenance), DefMethod(ast::DefId /* method */, MethodProvenance),
} }
/// The result of resolving the prefix of a path to a type: /// The result of resolving a path.
/// Before type checking completes, `depth` represents the number of
/// trailing segments which are yet unresolved. Afterwards, if there
/// were no errors, all paths should be fully resolved, with `depth`
/// set to `0` and `base_def` representing the final resolution.
/// ///
/// module::Type::AssocA::AssocB::AssocC::MethodOrAssocType /// module::Type::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~ /// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/// base_type extra_associated_types /// base_def depth = 3
/// ///
/// <T as Trait>::AssocA::AssocB::AssocC::MethodOrAssocType /// <T as Trait>::AssocX::AssocY::MethodOrAssocType
/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~ /// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~
/// base_type extra_associated_types /// base_def depth = 2
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] #[derive(Copy, Debug)]
pub struct PartialDef { pub struct PathResolution {
pub base_type: Def, pub base_def: Def,
pub extra_associated_types: u32, pub last_private: LastPrivate,
pub depth: usize
}
impl PathResolution {
/// Get the definition, if fully resolved, otherwise panic.
pub fn full_def(&self) -> Def {
if self.depth != 0 {
panic!("path not fully resolved: {:?}", self);
}
self.base_def
}
/// Get the DefId, if fully resolved, otherwise panic.
pub fn def_id(&self) -> ast::DefId {
self.full_def().def_id()
}
} }
// Definition mapping // Definition mapping
pub type DefMap = RefCell<NodeMap<Def>>; pub type DefMap = RefCell<NodeMap<PathResolution>>;
pub type PartialDefMap = RefCell<NodeMap<PartialDef>>;
// This is the replacement export map. It maps a module to all of the exports // This is the replacement export map. It maps a module to all of the exports
// within. // within.
pub type ExportMap = NodeMap<Vec<Export>>; pub type ExportMap = NodeMap<Vec<Export>>;
@ -119,7 +139,7 @@ impl Def {
local_def(id) local_def(id)
} }
DefPrimTy(_) => panic!() DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy")
} }
} }

View file

@ -1017,7 +1017,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
// Each match binding is effectively an assignment to the // Each match binding is effectively an assignment to the
// binding being produced. // binding being produced.
let def = def_map.borrow()[pat.id].clone(); let def = def_map.borrow()[pat.id].full_def();
match mc.cat_def(pat.id, pat.span, pat_ty, def) { match mc.cat_def(pat.id, pat.span, pat_ty, def) {
Ok(binding_cmt) => { Ok(binding_cmt) => {
delegate.mutate(pat.id, pat.span, binding_cmt, Init); delegate.mutate(pat.id, pat.span, binding_cmt, Init);
@ -1097,13 +1097,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
match pat.node { match pat.node {
ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => { ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => {
match def_map.get(&pat.id) { match def_map.get(&pat.id).map(|d| d.full_def()) {
None => { None => {
// no definition found: pat is not a // no definition found: pat is not a
// struct or enum pattern. // struct or enum pattern.
} }
Some(&def::DefVariant(enum_did, variant_did, _is_struct)) => { Some(def::DefVariant(enum_did, variant_did, _is_struct)) => {
let downcast_cmt = let downcast_cmt =
if ty::enum_is_univariant(tcx, enum_did) { if ty::enum_is_univariant(tcx, enum_did) {
cmt_pat cmt_pat
@ -1119,7 +1119,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
delegate.matched_pat(pat, downcast_cmt, match_mode); delegate.matched_pat(pat, downcast_cmt, match_mode);
} }
Some(&def::DefStruct(..)) | Some(&def::DefTy(_, false)) => { Some(def::DefStruct(..)) | Some(def::DefTy(_, false)) => {
// A struct (in either the value or type // A struct (in either the value or type
// namespace; we encounter the former on // namespace; we encounter the former on
// e.g. patterns for unit structs). // e.g. patterns for unit structs).
@ -1131,14 +1131,14 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
delegate.matched_pat(pat, cmt_pat, match_mode); delegate.matched_pat(pat, cmt_pat, match_mode);
} }
Some(&def::DefConst(..)) | Some(def::DefConst(..)) |
Some(&def::DefLocal(..)) => { Some(def::DefLocal(..)) => {
// This is a leaf (i.e. identifier binding // This is a leaf (i.e. identifier binding
// or constant value to match); thus no // or constant value to match); thus no
// `matched_pat` call. // `matched_pat` call.
} }
Some(def @ &def::DefTy(_, true)) => { Some(def @ def::DefTy(_, true)) => {
// An enum's type -- should never be in a // An enum's type -- should never be in a
// pattern. // pattern.

View file

@ -1242,7 +1242,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
"unbound path {}", "unbound path {}",
pprust::path_to_string(path))) pprust::path_to_string(path)))
} }
Some(&d) => d Some(d) => d.full_def()
}; };
match a_def { match a_def {
def::DefTy(did, _) | def::DefStruct(did) => { def::DefTy(did, _) | def::DefStruct(did) => {

View file

@ -446,7 +446,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
match expr.node { match expr.node {
// live nodes required for uses or definitions of variables: // live nodes required for uses or definitions of variables:
ast::ExprPath(_) | ast::ExprQPath(_) => { ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = ir.tcx.def_map.borrow()[expr.id].clone(); let def = ir.tcx.def_map.borrow()[expr.id].full_def();
debug!("expr {}: path that leads to {:?}", expr.id, def); debug!("expr {}: path that leads to {:?}", expr.id, def);
if let DefLocal(..) = def { if let DefLocal(..) = def {
ir.add_live_node_for_node(expr.id, ExprNode(expr.span)); ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
@ -705,8 +705,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
Some(_) => { Some(_) => {
// Refers to a labeled loop. Use the results of resolve // Refers to a labeled loop. Use the results of resolve
// to find with one // to find with one
match self.ir.tcx.def_map.borrow().get(&id) { match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
Some(&DefLabel(loop_id)) => loop_id, Some(DefLabel(loop_id)) => loop_id,
_ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \ _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \
doesn't refer to a loop") doesn't refer to a loop")
} }
@ -1300,7 +1300,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint) fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
-> LiveNode { -> LiveNode {
match self.ir.tcx.def_map.borrow()[expr.id].clone() { match self.ir.tcx.def_map.borrow()[expr.id].full_def() {
DefLocal(nid) => { DefLocal(nid) => {
let ln = self.live_node(expr.id, expr.span); let ln = self.live_node(expr.id, expr.span);
if acc != 0 { if acc != 0 {
@ -1562,7 +1562,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn check_lvalue(&mut self, expr: &Expr) { fn check_lvalue(&mut self, expr: &Expr) {
match expr.node { match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => { ast::ExprPath(_) | ast::ExprQPath(_) => {
if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() { if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].full_def() {
// Assignment to an immutable variable or argument: only legal // Assignment to an immutable variable or argument: only legal
// if there is no later assignment. If this local is actually // if there is no later assignment. If this local is actually
// mutable, then check for a reassignment to flag the mutability // mutable, then check for a reassignment to flag the mutability

View file

@ -530,7 +530,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
} }
ast::ExprPath(_) | ast::ExprQPath(_) => { ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = (*self.tcx().def_map.borrow())[expr.id]; let def = self.tcx().def_map.borrow()[expr.id].full_def();
self.cat_def(expr.id, expr.span, expr_ty, def) self.cat_def(expr.id, expr.span, expr_ty, def)
} }
@ -1199,14 +1199,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
(*op)(self, cmt.clone(), pat); (*op)(self, cmt.clone(), pat);
let def_map = self.tcx().def_map.borrow(); let opt_def = self.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
let opt_def = def_map.get(&pat.id);
// Note: This goes up here (rather than within the PatEnum arm // Note: This goes up here (rather than within the PatEnum arm
// alone) because struct patterns can refer to struct types or // alone) because struct patterns can refer to struct types or
// to struct variants within enums. // to struct variants within enums.
let cmt = match opt_def { let cmt = match opt_def {
Some(&def::DefVariant(enum_did, variant_did, _)) Some(def::DefVariant(enum_did, variant_did, _))
// univariant enums do not need downcasts // univariant enums do not need downcasts
if !ty::enum_is_univariant(self.tcx(), enum_did) => { if !ty::enum_is_univariant(self.tcx(), enum_did) => {
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did) self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
@ -1224,7 +1223,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
} }
ast::PatEnum(_, Some(ref subpats)) => { ast::PatEnum(_, Some(ref subpats)) => {
match opt_def { match opt_def {
Some(&def::DefVariant(..)) => { Some(def::DefVariant(..)) => {
// variant(x, y, z) // variant(x, y, z)
for (i, subpat) in subpats.iter().enumerate() { for (i, subpat) in subpats.iter().enumerate() {
let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
@ -1237,7 +1236,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
try!(self.cat_pattern_(subcmt, &**subpat, op)); try!(self.cat_pattern_(subcmt, &**subpat, op));
} }
} }
Some(&def::DefStruct(..)) => { Some(def::DefStruct(..)) => {
for (i, subpat) in subpats.iter().enumerate() { for (i, subpat) in subpats.iter().enumerate() {
let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2) let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
let cmt_field = let cmt_field =
@ -1247,7 +1246,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
try!(self.cat_pattern_(cmt_field, &**subpat, op)); try!(self.cat_pattern_(cmt_field, &**subpat, op));
} }
} }
Some(&def::DefConst(..)) => { Some(def::DefConst(..)) => {
for subpat in subpats { for subpat in subpats {
try!(self.cat_pattern_(cmt.clone(), &**subpat, op)); try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
} }

View file

@ -34,8 +34,8 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool {
ast::PatEnum(_, _) | ast::PatEnum(_, _) |
ast::PatIdent(_, _, None) | ast::PatIdent(_, _, None) |
ast::PatStruct(..) => { ast::PatStruct(..) => {
match dm.borrow().get(&pat.id) { match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(&DefVariant(..)) => true, Some(DefVariant(..)) => true,
_ => false _ => false
} }
} }
@ -49,8 +49,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
ast::PatEnum(_, _) | ast::PatEnum(_, _) |
ast::PatIdent(_, _, None) | ast::PatIdent(_, _, None) |
ast::PatStruct(..) => { ast::PatStruct(..) => {
match dm.borrow().get(&pat.id) { match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(&DefVariant(..)) | Some(&DefStruct(..)) => true, Some(DefVariant(..)) | Some(DefStruct(..)) => true,
_ => false _ => false
} }
} }
@ -61,8 +61,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool { pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool {
match pat.node { match pat.node {
ast::PatIdent(_, _, None) | ast::PatEnum(..) => { ast::PatIdent(_, _, None) | ast::PatEnum(..) => {
match dm.borrow().get(&pat.id) { match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(&DefConst(..)) => true, Some(DefConst(..)) => true,
_ => false _ => false
} }
} }

View file

@ -16,7 +16,7 @@ pub use self::PrivateDep::*;
pub use self::ImportUse::*; pub use self::ImportUse::*;
pub use self::LastPrivate::*; pub use self::LastPrivate::*;
use util::nodemap::{DefIdSet, NodeMap, NodeSet}; use util::nodemap::{DefIdSet, NodeSet};
use syntax::ast; use syntax::ast;
@ -32,9 +32,6 @@ pub type ExternalExports = DefIdSet;
/// reexporting a public struct doesn't inline the doc). /// reexporting a public struct doesn't inline the doc).
pub type PublicItems = NodeSet; pub type PublicItems = NodeSet;
// FIXME: dox
pub type LastPrivateMap = NodeMap<LastPrivate>;
#[derive(Copy, Debug)] #[derive(Copy, Debug)]
pub enum LastPrivate { pub enum LastPrivate {
LastMod(PrivateDep), LastMod(PrivateDep),

View file

@ -96,7 +96,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
match expr.node { match expr.node {
ast::ExprPath(_) | ast::ExprQPath(_) => { ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = match self.tcx.def_map.borrow().get(&expr.id) { let def = match self.tcx.def_map.borrow().get(&expr.id) {
Some(&def) => def, Some(d) => d.full_def(),
None => { None => {
self.tcx.sess.span_bug(expr.span, self.tcx.sess.span_bug(expr.span,
"def ID not in def map?!") "def ID not in def map?!")

View file

@ -168,8 +168,8 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
ast::TyPath(ref path) => { ast::TyPath(ref path) => {
// if this path references a trait, then this will resolve to // if this path references a trait, then this will resolve to
// a trait ref, which introduces a binding scope. // a trait ref, which introduces a binding scope.
match self.def_map.borrow().get(&ty.id) { match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) {
Some(&def::DefTrait(..)) => { Some((def::DefTrait(..), 0)) => {
self.with(LateScope(&Vec::new(), self.scope), |_, this| { self.with(LateScope(&Vec::new(), self.scope), |_, this| {
this.visit_path(path, ty.id); this.visit_path(path, ty.id);
}); });

View file

@ -393,12 +393,14 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId, pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) { cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
let did = match tcx.def_map.borrow().get(&id) { match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
Some(&def::DefPrimTy(..)) => return, Some(def::DefPrimTy(..)) => {}
Some(def) => def.def_id(), Some(def) => {
None => return maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
}; }
maybe_do_stability_check(tcx, did, path.span, cb) None => {}
}
} }
fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span, fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,

View file

@ -46,12 +46,11 @@ use metadata::csearch;
use middle; use middle;
use middle::check_const; use middle::check_const;
use middle::const_eval; use middle::const_eval;
use middle::def::{self, DefMap, ExportMap, PartialDefMap}; use middle::def::{self, DefMap, ExportMap};
use middle::dependency_format; use middle::dependency_format;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem}; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem}; use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
use middle::mem_categorization as mc; use middle::mem_categorization as mc;
use middle::privacy::LastPrivateMap;
use middle::region; use middle::region;
use middle::resolve_lifetime; use middle::resolve_lifetime;
use middle::infer; use middle::infer;
@ -683,8 +682,6 @@ pub struct ctxt<'tcx> {
pub sess: Session, pub sess: Session,
pub def_map: DefMap, pub def_map: DefMap,
pub partial_def_map: PartialDefMap,
pub last_private_map: RefCell<LastPrivateMap>,
pub named_region_map: resolve_lifetime::NamedRegionMap, pub named_region_map: resolve_lifetime::NamedRegionMap,
@ -2427,8 +2424,6 @@ impl<'tcx> CommonTypes<'tcx> {
pub fn mk_ctxt<'tcx>(s: Session, pub fn mk_ctxt<'tcx>(s: Session,
arenas: &'tcx CtxtArenas<'tcx>, arenas: &'tcx CtxtArenas<'tcx>,
def_map: DefMap, def_map: DefMap,
partial_def_map: PartialDefMap,
last_private_map: LastPrivateMap,
named_region_map: resolve_lifetime::NamedRegionMap, named_region_map: resolve_lifetime::NamedRegionMap,
map: ast_map::Map<'tcx>, map: ast_map::Map<'tcx>,
freevars: RefCell<FreevarMap>, freevars: RefCell<FreevarMap>,
@ -2451,8 +2446,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
variance_computed: Cell::new(false), variance_computed: Cell::new(false),
sess: s, sess: s,
def_map: def_map, def_map: def_map,
partial_def_map: partial_def_map,
last_private_map: RefCell::new(last_private_map),
region_maps: region_maps, region_maps: region_maps,
node_types: RefCell::new(FnvHashMap()), node_types: RefCell::new(FnvHashMap()),
item_substs: RefCell::new(NodeMap()), item_substs: RefCell::new(NodeMap()),
@ -4509,7 +4502,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def { pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
match tcx.def_map.borrow().get(&expr.id) { match tcx.def_map.borrow().get(&expr.id) {
Some(&def) => def, Some(def) => def.full_def(),
None => { None => {
tcx.sess.span_bug(expr.span, &format!( tcx.sess.span_bug(expr.span, &format!(
"no def-map entry for expr {}", expr.id)); "no def-map entry for expr {}", expr.id));
@ -4692,11 +4685,10 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
ast::ExprBox(Some(ref place), _) => { ast::ExprBox(Some(ref place), _) => {
// Special case `Box<T>` for now: // Special case `Box<T>` for now:
let definition = match tcx.def_map.borrow().get(&place.id) { let def_id = match tcx.def_map.borrow().get(&place.id) {
Some(&def) => def, Some(def) => def.def_id(),
None => panic!("no def for place"), None => panic!("no def for place"),
}; };
let def_id = definition.def_id();
if tcx.lang_items.exchange_heap() == Some(def_id) { if tcx.lang_items.exchange_heap() == Some(def_id) {
RvalueDatumExpr RvalueDatumExpr
} else { } else {
@ -5144,10 +5136,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
} }
pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId { pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
let def = *tcx.def_map.borrow() tcx.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id()
.get(&tr.ref_id)
.expect("no def-map entry for trait");
def.def_id()
} }
pub fn try_add_builtin_trait( pub fn try_add_builtin_trait(

View file

@ -567,12 +567,10 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
let resolve::CrateMap { let resolve::CrateMap {
def_map, def_map,
partial_def_map,
freevars, freevars,
export_map, export_map,
trait_map, trait_map,
external_exports, external_exports,
last_private_map,
glob_map, glob_map,
} = } =
time(time_passes, "resolution", (), time(time_passes, "resolution", (),
@ -608,8 +606,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
let ty_cx = ty::mk_ctxt(sess, let ty_cx = ty::mk_ctxt(sess,
arenas, arenas,
def_map, def_map,
partial_def_map,
last_private_map,
named_region_map, named_region_map,
ast_map, ast_map,
freevars, freevars,

View file

@ -259,7 +259,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => { ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
let public_ty = match ty.node { let public_ty = match ty.node {
ast::TyPath(_) => { ast::TyPath(_) => {
match self.tcx.def_map.borrow()[ty.id].clone() { match self.tcx.def_map.borrow()[ty.id].full_def() {
def::DefPrimTy(..) => true, def::DefPrimTy(..) => true,
def => { def => {
let did = def.def_id(); let did = def.def_id();
@ -326,7 +326,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
ast::ItemTy(ref ty, _) if public_first => { ast::ItemTy(ref ty, _) if public_first => {
if let ast::TyPath(_) = ty.node { if let ast::TyPath(_) = ty.node {
match self.tcx.def_map.borrow()[ty.id].clone() { match self.tcx.def_map.borrow()[ty.id].full_def() {
def::DefPrimTy(..) | def::DefTyParam(..) => {}, def::DefPrimTy(..) | def::DefTyParam(..) => {},
def => { def => {
let did = def.def_id(); let did = def.def_id();
@ -630,7 +630,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
ast::TyPath(_) => {} ast::TyPath(_) => {}
_ => return Some((err_span, err_msg, None)), _ => return Some((err_span, err_msg, None)),
}; };
let def = self.tcx.def_map.borrow()[ty.id].clone(); let def = self.tcx.def_map.borrow()[ty.id].full_def();
let did = def.def_id(); let did = def.def_id();
assert!(is_local(did)); assert!(is_local(did));
match self.tcx.map.get(did.node) { match self.tcx.map.get(did.node) {
@ -716,19 +716,19 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
// Checks that a path is in scope. // Checks that a path is in scope.
fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) { fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) {
debug!("privacy - path {}", self.nodestr(path_id)); debug!("privacy - path {}", self.nodestr(path_id));
let orig_def = self.tcx.def_map.borrow()[path_id].clone(); let path_res = self.tcx.def_map.borrow()[path_id];
let ck = |tyname: &str| { let ck = |tyname: &str| {
let ck_public = |def: ast::DefId| { let ck_public = |def: ast::DefId| {
debug!("privacy - ck_public {:?}", def); debug!("privacy - ck_public {:?}", def);
let name = token::get_ident(last); let name = token::get_ident(last);
let origdid = orig_def.def_id(); let origdid = path_res.def_id();
self.ensure_public(span, self.ensure_public(span,
def, def,
Some(origdid), Some(origdid),
&format!("{} `{}`", tyname, name)) &format!("{} `{}`", tyname, name))
}; };
match self.tcx.last_private_map.borrow()[path_id] { match path_res.last_private {
LastMod(AllPublic) => {}, LastMod(AllPublic) => {},
LastMod(DependsOn(def)) => { LastMod(DependsOn(def)) => {
self.report_error(ck_public(def)); self.report_error(ck_public(def));
@ -792,7 +792,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
// def map is not. Therefore the names we work out below will not always // def map is not. Therefore the names we work out below will not always
// be accurate and we can get slightly wonky error messages (but type // be accurate and we can get slightly wonky error messages (but type
// checking is always correct). // checking is always correct).
match self.tcx.def_map.borrow()[path_id].clone() { match path_res.full_def() {
def::DefFn(..) => ck("function"), def::DefFn(..) => ck("function"),
def::DefStatic(..) => ck("static"), def::DefStatic(..) => ck("static"),
def::DefConst(..) => ck("const"), def::DefConst(..) => ck("const"),
@ -889,7 +889,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
} }
} }
ty::ty_enum(_, _) => { ty::ty_enum(_, _) => {
match self.tcx.def_map.borrow()[expr.id].clone() { match self.tcx.def_map.borrow()[expr.id].full_def() {
def::DefVariant(_, variant_id, _) => { def::DefVariant(_, variant_id, _) => {
for field in fields { for field in fields {
self.check_field(expr.span, variant_id, self.check_field(expr.span, variant_id,
@ -922,8 +922,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
with private fields"); with private fields");
} }
}; };
match self.tcx.def_map.borrow().get(&expr.id) { match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
Some(&def::DefStruct(did)) => { Some(def::DefStruct(did)) => {
guard(if is_local(did) { guard(if is_local(did) {
local_def(self.tcx.map.get_parent(did.node)) local_def(self.tcx.map.get_parent(did.node))
} else { } else {
@ -962,8 +962,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
} }
} }
ty::ty_enum(_, _) => { ty::ty_enum(_, _) => {
match self.tcx.def_map.borrow().get(&pattern.id) { match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) {
Some(&def::DefVariant(_, variant_id, _)) => { Some(def::DefVariant(_, variant_id, _)) => {
for field in fields { for field in fields {
self.check_field(pattern.span, variant_id, self.check_field(pattern.span, variant_id,
NamedField(field.node.ident.name)); NamedField(field.node.ident.name));
@ -1214,7 +1214,7 @@ struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> { impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
fn path_is_private_type(&self, path_id: ast::NodeId) -> bool { fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
let did = match self.tcx.def_map.borrow().get(&path_id).cloned() { let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
// `int` etc. (None doesn't seem to occur.) // `int` etc. (None doesn't seem to occur.)
None | Some(def::DefPrimTy(..)) => return false, None | Some(def::DefPrimTy(..)) => return false,
Some(def) => def.def_id() Some(def) => def.def_id()

View file

@ -68,17 +68,17 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
"unused import".to_string()); "unused import".to_string());
} }
let (v_priv, t_priv) = match self.last_private.get(&id) { let mut def_map = self.def_map.borrow_mut();
Some(&LastImport { let path_res = if let Some(r) = def_map.get_mut(&id) {
value_priv: v, r
value_used: _, } else {
type_priv: t, return;
type_used: _ };
}) => (v, t), let (v_priv, t_priv) = match path_res.last_private {
Some(_) => { LastImport { value_priv, type_priv, .. } => (value_priv, type_priv),
_ => {
panic!("we should only have LastImport for `use` directives") panic!("we should only have LastImport for `use` directives")
} }
_ => return,
}; };
let mut v_used = if self.used_imports.contains(&(id, ValueNS)) { let mut v_used = if self.used_imports.contains(&(id, ValueNS)) {
@ -100,10 +100,12 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
_ => {}, _ => {},
} }
self.last_private.insert(id, LastImport{value_priv: v_priv, path_res.last_private = LastImport {
value_used: v_used, value_priv: v_priv,
type_priv: t_priv, value_used: v_used,
type_used: t_used}); type_priv: t_priv,
type_used: t_used
};
} }
} }

View file

@ -934,13 +934,11 @@ struct Resolver<'a, 'tcx:'a> {
primitive_type_table: PrimitiveTypeTable, primitive_type_table: PrimitiveTypeTable,
def_map: DefMap, def_map: DefMap,
partial_def_map: PartialDefMap,
freevars: RefCell<FreevarMap>, freevars: RefCell<FreevarMap>,
freevars_seen: RefCell<NodeMap<NodeSet>>, freevars_seen: RefCell<NodeMap<NodeSet>>,
export_map: ExportMap, export_map: ExportMap,
trait_map: TraitMap, trait_map: TraitMap,
external_exports: ExternalExports, external_exports: ExternalExports,
last_private: LastPrivateMap,
// Whether or not to print error messages. Can be set to true // Whether or not to print error messages. Can be set to true
// when getting additional info for error message suggestions, // when getting additional info for error message suggestions,
@ -1008,7 +1006,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
primitive_type_table: PrimitiveTypeTable::new(), primitive_type_table: PrimitiveTypeTable::new(),
def_map: RefCell::new(NodeMap()), def_map: RefCell::new(NodeMap()),
partial_def_map: RefCell::new(NodeMap()),
freevars: RefCell::new(NodeMap()), freevars: RefCell::new(NodeMap()),
freevars_seen: RefCell::new(NodeMap()), freevars_seen: RefCell::new(NodeMap()),
export_map: NodeMap(), export_map: NodeMap(),
@ -1016,7 +1013,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
used_imports: HashSet::new(), used_imports: HashSet::new(),
used_crates: HashSet::new(), used_crates: HashSet::new(),
external_exports: DefIdSet(), external_exports: DefIdSet(),
last_private: NodeMap(),
emit_errors: true, emit_errors: true,
make_glob_map: make_glob_map == MakeGlobMap::Yes, make_glob_map: make_glob_map == MakeGlobMap::Yes,
@ -1574,31 +1570,36 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// record what this import resolves to for later uses in documentation, // record what this import resolves to for later uses in documentation,
// this may resolve to either a value or a type, but for 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. // purposes it's good enough to just favor one over the other.
let value_private = match import_resolution.value_target { let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| {
Some(ref target) => { let def = target.bindings.def_for_namespace(ValueNS).unwrap();
let def = target.bindings.def_for_namespace(ValueNS).unwrap(); (def, if value_used_public { lp } else { DependsOn(def.def_id()) })
self.def_map.borrow_mut().insert(directive.id, def); });
let did = def.def_id(); let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| {
if value_used_public {Some(lp)} else {Some(DependsOn(did))} let def = target.bindings.def_for_namespace(TypeNS).unwrap();
}, (def, if type_used_public { lp } else { DependsOn(def.def_id()) })
// AllPublic here and below is a dummy value, it should never be used because });
// _exists is false.
None => None, let import_lp = LastImport {
}; value_priv: value_def_and_priv.map(|(_, p)| p),
let type_private = match import_resolution.type_target { value_used: Used,
Some(ref target) => { type_priv: type_def_and_priv.map(|(_, p)| p),
let def = target.bindings.def_for_namespace(TypeNS).unwrap(); type_used: Used
self.def_map.borrow_mut().insert(directive.id, def);
let did = def.def_id();
if type_used_public {Some(lp)} else {Some(DependsOn(did))}
},
None => None,
}; };
self.last_private.insert(directive.id, LastImport{value_priv: value_private, if let Some((def, _)) = value_def_and_priv {
value_used: Used, self.def_map.borrow_mut().insert(directive.id, PathResolution {
type_priv: type_private, base_def: def,
type_used: Used}); last_private: import_lp,
depth: 0
});
}
if let Some((def, _)) = type_def_and_priv {
self.def_map.borrow_mut().insert(directive.id, PathResolution {
base_def: def,
last_private: import_lp,
depth: 0
});
}
debug!("(resolving single import) successfully resolved import"); debug!("(resolving single import) successfully resolved import");
return Success(()); return Success(());
@ -1716,12 +1717,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
// Record the destination of this import // Record the destination of this import
match containing_module.def_id.get() { if let Some(did) = containing_module.def_id.get() {
Some(did) => { self.def_map.borrow_mut().insert(id, PathResolution {
self.def_map.borrow_mut().insert(id, DefMod(did)); base_def: DefMod(did),
self.last_private.insert(id, lp); last_private: lp,
} depth: 0
None => {} });
} }
debug!("(resolving glob import) successfully resolved import"); debug!("(resolving glob import) successfully resolved import");
@ -2846,8 +2847,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ItemUse(ref view_path) => { ItemUse(ref view_path) => {
// check for imports shadowing primitive types // check for imports shadowing primitive types
if let ast::ViewPathSimple(ident, _) = view_path.node { if let ast::ViewPathSimple(ident, _) = view_path.node {
match self.def_map.borrow().get(&item.id) { match self.def_map.borrow().get(&item.id).map(|d| d.full_def()) {
Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefTrait(..)) | None => { Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
self.check_if_primitive_type_name(ident.name, item.span); self.check_if_primitive_type_name(ident.name, item.span);
} }
_ => {} _ => {}
@ -2959,30 +2960,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
id: NodeId, id: NodeId,
trait_path: &Path, trait_path: &Path,
path_depth: usize) path_depth: usize)
-> Result<(Def, LastPrivate, usize), ()> { -> Result<PathResolution, ()> {
match self.resolve_path(id, trait_path, path_depth, TypeNS, true) { if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
Some(def @ (DefTrait(_), _, _)) => { if let DefTrait(_) = path_res.base_def {
debug!("(resolving trait) found trait def: {:?}", def); debug!("(resolving trait) found trait def: {:?}", path_res);
Ok(def) Ok(path_res)
} } else {
Some((def, _, _)) => {
self.resolve_error(trait_path.span, self.resolve_error(trait_path.span,
&format!("`{}` is not a trait", &format!("`{}` is not a trait",
self.path_names_to_string(trait_path, path_depth))); self.path_names_to_string(trait_path, path_depth)));
// If it's a typedef, give a note // If it's a typedef, give a note
if let DefTy(..) = def { if let DefTy(..) = path_res.base_def {
self.session.span_note(trait_path.span, self.session.span_note(trait_path.span,
"`type` aliases cannot be used for traits"); "`type` aliases cannot be used for traits");
} }
Err(()) Err(())
} }
None => { } else {
let msg = format!("use of undeclared trait name `{}`", let msg = format!("use of undeclared trait name `{}`",
self.path_names_to_string(trait_path, path_depth)); self.path_names_to_string(trait_path, path_depth));
self.resolve_error(trait_path.span, &msg[]); self.resolve_error(trait_path.span, &msg[]);
Err(()) Err(())
}
} }
} }
@ -2995,14 +2994,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&ast::WherePredicate::BoundPredicate(_) | &ast::WherePredicate::BoundPredicate(_) |
&ast::WherePredicate::RegionPredicate(_) => {} &ast::WherePredicate::RegionPredicate(_) => {}
&ast::WherePredicate::EqPredicate(ref eq_pred) => { &ast::WherePredicate::EqPredicate(ref eq_pred) => {
match self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true) { let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true);
Some(def @ (DefTyParam(..), _, _)) => { if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res {
self.record_def(eq_pred.id, def); self.record_def(eq_pred.id, path_res.unwrap());
} } else {
_ => { self.resolve_error(eq_pred.path.span, "undeclared associated type");
self.resolve_error(eq_pred.path.span,
"undeclared associated type");
}
} }
} }
} }
@ -3028,9 +3024,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let mut new_val = None; let mut new_val = None;
if let Some(ref trait_ref) = *opt_trait_ref { if let Some(ref trait_ref) = *opt_trait_ref {
match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) { match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) {
Ok(def) => { Ok(path_res) => {
self.record_def(trait_ref.ref_id, def); self.record_def(trait_ref.ref_id, path_res);
new_val = Some((def.0.def_id(), trait_ref.clone())); new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
} }
Err(_) => { /* error was already reported */ } Err(_) => { /* error was already reported */ }
} }
@ -3259,23 +3255,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
path.segments.len() path.segments.len()
}; };
let mut result = None; let mut resolution = None;
for depth in 0..max_assoc_types { for depth in 0..max_assoc_types {
self.with_no_errors(|this| { self.with_no_errors(|this| {
result = this.resolve_path(ty.id, path, depth, TypeNS, true); resolution = this.resolve_path(ty.id, path, depth, TypeNS, true);
}); });
if result.is_some() { if resolution.is_some() {
break; break;
} }
} }
if let Some((DefMod(_), _, _)) = result { if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
// A module is not a valid type. // A module is not a valid type.
result = None; resolution = None;
} }
// This is a path in the type namespace. Walk through scopes // This is a path in the type namespace. Walk through scopes
// looking for it. // looking for it.
match result { match resolution {
Some(def) => { Some(def) => {
// Write the result into the def map. // Write the result into the def map.
debug!("(resolving type) writing resolution for `{}` \ debug!("(resolving type) writing resolution for `{}` \
@ -3338,7 +3334,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
pattern, pattern,
binding_mode, binding_mode,
"an enum variant"); "an enum variant");
self.record_def(pattern.id, (def, lp, 0)); self.record_def(pattern.id, PathResolution {
base_def: def,
last_private: lp,
depth: 0
});
} }
FoundStructOrEnumVariant(..) => { FoundStructOrEnumVariant(..) => {
self.resolve_error( self.resolve_error(
@ -3357,7 +3357,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
pattern, pattern,
binding_mode, binding_mode,
"a constant"); "a constant");
self.record_def(pattern.id, (def, lp, 0)); self.record_def(pattern.id, PathResolution {
base_def: def,
last_private: lp,
depth: 0
});
} }
FoundConst(..) => { FoundConst(..) => {
self.resolve_error(pattern.span, self.resolve_error(pattern.span,
@ -3374,7 +3378,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// will be able to distinguish variants from // will be able to distinguish variants from
// locals in patterns. // locals in patterns.
self.record_def(pattern.id, (def, LastMod(AllPublic), 0)); self.record_def(pattern.id, PathResolution {
base_def: def,
last_private: LastMod(AllPublic),
depth: 0
});
// Add the binding to the local ribs, if it // Add the binding to the local ribs, if it
// doesn't already exist in the bindings list. (We // doesn't already exist in the bindings list. (We
@ -3417,29 +3425,28 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
PatEnum(ref path, _) => { PatEnum(ref path, _) => {
// This must be an enum variant, struct or const. // This must be an enum variant, struct or const.
match self.resolve_path(pat_id, path, 0, ValueNS, false) { if let Some(path_res) = self.resolve_path(pat_id, path, 0, ValueNS, false) {
Some(def @ (DefVariant(..), _, _)) | match path_res.base_def {
Some(def @ (DefStruct(..), _, _)) | DefVariant(..) | DefStruct(..) | DefConst(..) => {
Some(def @ (DefConst(..), _, _)) => { self.record_def(pattern.id, path_res);
self.record_def(pattern.id, def); }
} DefStatic(..) => {
Some((DefStatic(..), _, _)) => { self.resolve_error(path.span,
self.resolve_error(path.span, "static variables cannot be \
"static variables cannot be \ referenced in a pattern, \
referenced in a pattern, \ use a `const` instead");
use a `const` instead"); }
} _ => {
Some(_) => { self.resolve_error(path.span,
self.resolve_error(path.span, &format!("`{}` is not an enum variant, struct or const",
&format!("`{}` is not an enum variant, struct or const", token::get_ident(
token::get_ident( path.segments.last().unwrap().identifier)));
path.segments.last().unwrap().identifier))); }
}
None => {
self.resolve_error(path.span,
&format!("unresolved enum variant, struct or const `{}`",
token::get_ident(path.segments.last().unwrap().identifier)));
} }
} else {
self.resolve_error(path.span,
&format!("unresolved enum variant, struct or const `{}`",
token::get_ident(path.segments.last().unwrap().identifier)));
} }
visit::walk_path(self, path); visit::walk_path(self, path);
} }
@ -3535,18 +3542,26 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// If `check_ribs` is true, checks the local definitions first; i.e. /// If `check_ribs` is true, checks the local definitions first; i.e.
/// doesn't skip straight to the containing module. /// doesn't skip straight to the containing module.
/// Skips `path_depth` trailing segments, which is also reflected in the
/// returned value. See `middle::def::PathResolution` for more info.
fn resolve_path(&mut self, fn resolve_path(&mut self,
id: NodeId, id: NodeId,
path: &Path, path: &Path,
path_depth: usize, path_depth: usize,
namespace: Namespace, namespace: Namespace,
check_ribs: bool) -> Option<(Def, LastPrivate, usize)> { check_ribs: bool) -> Option<PathResolution> {
let span = path.span; let span = path.span;
let segments = &path.segments[..path.segments.len()-path_depth]; let segments = &path.segments[..path.segments.len()-path_depth];
let mk_res = |(def, lp)| PathResolution {
base_def: def,
last_private: lp,
depth: path_depth
};
if path.global { if path.global {
let def = self.resolve_crate_relative_path(span, segments, namespace); let def = self.resolve_crate_relative_path(span, segments, namespace);
return def.map(|(def, lp)| (def, lp, path_depth)); return def.map(mk_res);
} }
// Try to find a path to an item in a module. // Try to find a path to an item in a module.
@ -3568,9 +3583,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
_ => () _ => ()
} }
def.map(|(def, lp)| (def, lp, path_depth)) def.map(mk_res)
} else { } else {
unqualified_def.map(|(def, lp)| (def, lp, path_depth)) unqualified_def.map(mk_res)
} }
} }
@ -3957,10 +3972,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if allowed == Everything { if allowed == Everything {
// Look for a field with the same name in the current self_type. // Look for a field with the same name in the current self_type.
match self.def_map.borrow().get(&node_id) { match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
Some(&DefTy(did, _)) Some(DefTy(did, _)) |
| Some(&DefStruct(did)) Some(DefStruct(did)) |
| Some(&DefVariant(_, did, _)) => match self.structs.get(&did) { Some(DefVariant(_, did, _)) => match self.structs.get(&did) {
None => {} None => {}
Some(fields) => { Some(fields) => {
if fields.iter().any(|&field_name| name == field_name) { if fields.iter().any(|&field_name| name == field_name) {
@ -4060,27 +4075,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
path.segments.len() path.segments.len()
}; };
let mut result = self.with_no_errors(|this| { let mut resolution = self.with_no_errors(|this| {
this.resolve_path(expr.id, path, 0, ValueNS, true) this.resolve_path(expr.id, path, 0, ValueNS, true)
}); });
for depth in 1..max_assoc_types { for depth in 1..max_assoc_types {
if result.is_some() { if resolution.is_some() {
break; break;
} }
self.with_no_errors(|this| { self.with_no_errors(|this| {
result = this.resolve_path(expr.id, path, depth, TypeNS, true); resolution = this.resolve_path(expr.id, path, depth, TypeNS, true);
}); });
} }
if let Some((DefMod(_), _, _)) = result { if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
// A module is not a valid type or value. // A module is not a valid type or value.
result = None; resolution = None;
} }
// This is a local path in the value namespace. Walk through // This is a local path in the value namespace. Walk through
// scopes looking for it. // scopes looking for it.
match result { if let Some(path_res) = resolution {
// Check if struct variant // Check if struct variant
Some((DefVariant(_, _, true), _, 0)) => { if let DefVariant(_, _, true) = path_res.base_def {
let path_name = self.path_names_to_string(path, 0); let path_name = self.path_names_to_string(path, 0);
self.resolve_error(expr.span, self.resolve_error(expr.span,
&format!("`{}` is a struct variant name, but \ &format!("`{}` is a struct variant name, but \
@ -4092,95 +4107,93 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&format!("Did you mean to write: \ &format!("Did you mean to write: \
`{} {{ /* fields */ }}`?", `{} {{ /* fields */ }}`?",
path_name)); path_name));
} } else {
Some(def) => {
// Write the result into the def map. // Write the result into the def map.
debug!("(resolving expr) resolved `{}`", debug!("(resolving expr) resolved `{}`",
self.path_names_to_string(path, 0)); self.path_names_to_string(path, 0));
// Partial resolutions will need the set of traits in scope, // Partial resolutions will need the set of traits in scope,
// so they can be completed during typeck. // so they can be completed during typeck.
if def.2 != 0 { if path_res.depth != 0 {
let method_name = path.segments.last().unwrap().identifier.name; let method_name = path.segments.last().unwrap().identifier.name;
let traits = self.search_for_traits_containing_method(method_name); let traits = self.search_for_traits_containing_method(method_name);
self.trait_map.insert(expr.id, traits); self.trait_map.insert(expr.id, traits);
} }
self.record_def(expr.id, def); self.record_def(expr.id, path_res);
} }
None => { } else {
// Be helpful if the name refers to a struct // Be helpful if the name refers to a struct
// (The pattern matching def_tys where the id is in self.structs // (The pattern matching def_tys where the id is in self.structs
// matches on regular structs while excluding tuple- and enum-like // matches on regular structs while excluding tuple- and enum-like
// structs, which wouldn't result in this error.) // structs, which wouldn't result in this error.)
let path_name = self.path_names_to_string(path, 0); let path_name = self.path_names_to_string(path, 0);
match self.with_no_errors(|this| let type_res = self.with_no_errors(|this| {
this.resolve_path(expr.id, path, 0, TypeNS, false)) { this.resolve_path(expr.id, path, 0, TypeNS, false)
Some((DefTy(struct_id, _), _, 0)) });
if self.structs.contains_key(&struct_id) => { match type_res.map(|r| r.base_def) {
self.resolve_error(expr.span, Some(DefTy(struct_id, _))
&format!("`{}` is a structure name, but \ if self.structs.contains_key(&struct_id) => {
this expression \ self.resolve_error(expr.span,
uses it like a function name", &format!("`{}` is a structure name, but \
path_name)); this expression \
uses it like a function name",
path_name));
self.session.span_help(expr.span, self.session.span_help(expr.span,
&format!("Did you mean to write: \ &format!("Did you mean to write: \
`{} {{ /* fields */ }}`?", `{} {{ /* fields */ }}`?",
path_name)); path_name));
} }
_ => { _ => {
// Keep reporting some errors even if they're ignored above. // Keep reporting some errors even if they're ignored above.
self.resolve_path(expr.id, path, 0, ValueNS, true); self.resolve_path(expr.id, path, 0, ValueNS, true);
let mut method_scope = false; let mut method_scope = false;
self.value_ribs.iter().rev().all(|rib| { self.value_ribs.iter().rev().all(|rib| {
method_scope = match rib.kind { method_scope = match rib.kind {
MethodRibKind => true, MethodRibKind => true,
ItemRibKind | ConstantItemRibKind => false, ItemRibKind | ConstantItemRibKind => false,
_ => return true, // Keep advancing _ => return true, // Keep advancing
}; };
false // Stop advancing false // Stop advancing
}); });
if method_scope && &token::get_name(self.self_name)[..]
== path_name {
self.resolve_error(
expr.span,
"`self` is not available \
in a static method. Maybe a \
`self` argument is missing?");
} else {
let last_name = path.segments.last().unwrap().identifier.name;
let mut msg = match self.find_fallback_in_self_type(last_name) {
NoSuggestion => {
// limit search to 5 to reduce the number
// of stupid suggestions
self.find_best_match_for_name(&path_name, 5)
.map_or("".to_string(),
|x| format!("`{}`", x))
}
Field =>
format!("`self.{}`", path_name),
Method
| TraitItem =>
format!("to call `self.{}`", path_name),
TraitMethod(path_str)
| StaticMethod(path_str) =>
format!("to call `{}::{}`", path_str, path_name)
};
if msg.len() > 0 {
msg = format!(". Did you mean {}?", msg)
}
if method_scope && &token::get_name(self.self_name)[..]
== path_name {
self.resolve_error( self.resolve_error(
expr.span, expr.span,
&format!("unresolved name `{}`{}", "`self` is not available \
path_name, in a static method. Maybe a \
msg)); `self` argument is missing?");
} else {
let last_name = path.segments.last().unwrap().identifier.name;
let mut msg = match self.find_fallback_in_self_type(last_name) {
NoSuggestion => {
// limit search to 5 to reduce the number
// of stupid suggestions
self.find_best_match_for_name(&path_name, 5)
.map_or("".to_string(),
|x| format!("`{}`", x))
}
Field => format!("`self.{}`", path_name),
Method |
TraitItem =>
format!("to call `self.{}`", path_name),
TraitMethod(path_str) |
StaticMethod(path_str) =>
format!("to call `{}::{}`", path_str, path_name)
};
if msg.len() > 0 {
msg = format!(". Did you mean {}?", msg)
} }
self.resolve_error(
expr.span,
&format!("unresolved name `{}`{}",
path_name, msg));
} }
} }
} }
@ -4231,7 +4244,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
Some(DlDef(def @ DefLabel(_))) => { Some(DlDef(def @ DefLabel(_))) => {
// Since this def is a label, it is never read. // Since this def is a label, it is never read.
self.record_def(expr.id, (def, LastMod(AllPublic), 0)) self.record_def(expr.id, PathResolution {
base_def: def,
last_private: LastMod(AllPublic),
depth: 0
})
} }
Some(_) => { Some(_) => {
self.session.span_bug(expr.span, self.session.span_bug(expr.span,
@ -4349,33 +4366,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
found_traits found_traits
} }
fn record_def(&mut self, fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
node_id: NodeId, debug!("(recording def) recording {:?} for {}", resolution, node_id);
(def, lp, depth): (Def, LastPrivate, usize)) { assert!(match resolution.last_private {LastImport{..} => false, _ => true},
debug!("(recording def) recording {:?} for {}, last private {:?}",
def, node_id, lp);
assert!(match lp {LastImport{..} => false, _ => true},
"Import should only be used for `use` directives"); "Import should only be used for `use` directives");
self.last_private.insert(node_id, lp);
if depth == 0 { if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) {
if let Some(prev_def) = self.def_map.borrow_mut().insert(node_id, def) { let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); self.session.span_bug(span, &format!("path resolved multiple times \
self.session.span_bug(span, &format!("path resolved multiple times \ ({:?} before, {:?} now)",
({:?} before, {:?} now)", prev_res, resolution));
prev_def, def));
}
} else {
let def = PartialDef {
base_type: def,
extra_associated_types: (depth - 1) as u32
};
if let Some(prev_def) = self.partial_def_map.borrow_mut().insert(node_id, def) {
let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
self.session.span_bug(span, &format!("path resolved multiple times \
({:?} before, {:?} now)",
prev_def, def));
}
} }
} }
@ -4466,12 +4466,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
pub struct CrateMap { pub struct CrateMap {
pub def_map: DefMap, pub def_map: DefMap,
pub partial_def_map: PartialDefMap,
pub freevars: RefCell<FreevarMap>, pub freevars: RefCell<FreevarMap>,
pub export_map: ExportMap, pub export_map: ExportMap,
pub trait_map: TraitMap, pub trait_map: TraitMap,
pub external_exports: ExternalExports, pub external_exports: ExternalExports,
pub last_private_map: LastPrivateMap,
pub glob_map: Option<GlobMap> pub glob_map: Option<GlobMap>
} }
@ -4506,12 +4504,10 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
CrateMap { CrateMap {
def_map: resolver.def_map, def_map: resolver.def_map,
partial_def_map: resolver.partial_def_map,
freevars: resolver.freevars, freevars: resolver.freevars,
export_map: resolver.export_map, export_map: resolver.export_map,
trait_map: resolver.trait_map, trait_map: resolver.trait_map,
external_exports: resolver.external_exports, external_exports: resolver.external_exports,
last_private_map: resolver.last_private,
glob_map: if resolver.make_glob_map { glob_map: if resolver.make_glob_map {
Some(resolver.glob_map) Some(resolver.glob_map)
} else { } else {

View file

@ -218,7 +218,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref", self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
ref_id)); ref_id));
} }
let def = (*self.analysis.ty_cx.def_map.borrow())[ref_id]; let def = self.analysis.ty_cx.def_map.borrow()[ref_id].full_def();
match def { match def {
def::DefPrimTy(_) => None, def::DefPrimTy(_) => None,
_ => Some(def.def_id()), _ => Some(def.def_id()),
@ -231,7 +231,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind", self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind",
ref_id)); ref_id));
} }
let def = (*def_map)[ref_id]; let def = def_map[ref_id].full_def();
match def { match def {
def::DefMod(_) | def::DefMod(_) |
def::DefForeignMod(_) => Some(recorder::ModRef), def::DefForeignMod(_) => Some(recorder::ModRef),
@ -792,9 +792,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
self.sess.span_bug(span, self.sess.span_bug(span,
&format!("def_map has no key for {} in visit_expr", id)); &format!("def_map has no key for {} in visit_expr", id));
} }
let def = &(*def_map)[id]; let def = def_map[id].full_def();
let sub_span = self.span.span_for_last_ident(span); let sub_span = self.span.span_for_last_ident(span);
match *def { match def {
def::DefUpvar(..) | def::DefUpvar(..) |
def::DefLocal(..) | def::DefLocal(..) |
def::DefStatic(..) | def::DefStatic(..) |
@ -866,10 +866,10 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
&format!("Unexpected def kind while looking \ &format!("Unexpected def kind while looking \
up path in `{}`: `{:?}`", up path in `{}`: `{:?}`",
self.span.snippet(span), self.span.snippet(span),
*def)), def)),
} }
// modules or types in the path prefix // modules or types in the path prefix
match *def { match def {
def::DefMethod(did, _) => { def::DefMethod(did, _) => {
let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did); let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did);
if let ty::MethodTraitItem(m) = ti { if let ty::MethodTraitItem(m) = ti {
@ -1456,8 +1456,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
&format!("def_map has no key for {} in visit_arm", &format!("def_map has no key for {} in visit_arm",
id)); id));
} }
let def = &(*def_map)[id]; let def = def_map[id].full_def();
match *def { match def {
def::DefLocal(id) => { def::DefLocal(id) => {
let value = if *immut { let value = if *immut {
self.span.snippet(p.span).to_string() self.span.snippet(p.span).to_string()
@ -1480,7 +1480,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
def::DefStatic(_, _) => {} def::DefStatic(_, _) => {}
def::DefConst(..) => {} def::DefConst(..) => {}
_ => error!("unexpected definition kind when processing collected paths: {:?}", _ => error!("unexpected definition kind when processing collected paths: {:?}",
*def) def)
} }
} }
for &(id, ref path, ref_kind) in &paths_to_process { for &(id, ref path, ref_kind) in &paths_to_process {

View file

@ -598,7 +598,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
} }
ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => { ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => {
// This is either an enum variant or a variable binding. // This is either an enum variant or a variable binding.
let opt_def = tcx.def_map.borrow().get(&cur.id).cloned(); let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
match opt_def { match opt_def {
Some(def::DefVariant(enum_id, var_id, _)) => { Some(def::DefVariant(enum_id, var_id, _)) => {
let variant = ty::enum_variant_with_id(tcx, enum_id, var_id); let variant = ty::enum_variant_with_id(tcx, enum_id, var_id);
@ -725,14 +725,14 @@ fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool {
match pat.node { match pat.node {
ast::PatTup(_) => true, ast::PatTup(_) => true,
ast::PatStruct(..) => { ast::PatStruct(..) => {
match tcx.def_map.borrow().get(&pat.id) { match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(&def::DefVariant(..)) => false, Some(def::DefVariant(..)) => false,
_ => true, _ => true,
} }
} }
ast::PatEnum(..) | ast::PatIdent(_, _, None) => { ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
match tcx.def_map.borrow().get(&pat.id) { match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
Some(&def::DefStruct(..)) => true, Some(def::DefStruct(..)) => true,
_ => false _ => false
} }
} }
@ -1282,15 +1282,15 @@ fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool
_ => return false _ => return false
}, },
ast::ExprField(ref base, field) => { ast::ExprField(ref base, field) => {
let vid = match bcx.tcx().def_map.borrow().get(&base.id) { let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid, Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
_ => return false _ => return false
}; };
(vid, Some(mc::NamedField(field.node.name))) (vid, Some(mc::NamedField(field.node.name)))
}, },
ast::ExprTupField(ref base, field) => { ast::ExprTupField(ref base, field) => {
let vid = match bcx.tcx().def_map.borrow().get(&base.id) { let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid, Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
_ => return false _ => return false
}; };
(vid, Some(mc::PositionalField(field.node))) (vid, Some(mc::PositionalField(field.node)))
@ -1689,7 +1689,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
} }
} }
ast::PatEnum(_, ref sub_pats) => { ast::PatEnum(_, ref sub_pats) => {
let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).cloned(); let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
match opt_def { match opt_def {
Some(def::DefVariant(enum_id, var_id, _)) => { Some(def::DefVariant(enum_id, var_id, _)) => {
let repr = adt::represent_node(bcx, pat.id); let repr = adt::represent_node(bcx, pat.id);

View file

@ -603,7 +603,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
pub fn def(&self, nid: ast::NodeId) -> def::Def { pub fn def(&self, nid: ast::NodeId) -> def::Def {
match self.tcx().def_map.borrow().get(&nid) { match self.tcx().def_map.borrow().get(&nid) {
Some(v) => v.clone(), Some(v) => v.full_def(),
None => { None => {
self.tcx().sess.bug(&format!( self.tcx().sess.bug(&format!(
"no def associated with node id {}", nid)); "no def associated with node id {}", nid));

View file

@ -194,7 +194,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// Special-case constants to cache a common global for all uses. // Special-case constants to cache a common global for all uses.
match expr.node { match expr.node {
ast::ExprPath(_) => { ast::ExprPath(_) => {
let def = ccx.tcx().def_map.borrow()[expr.id]; let def = ccx.tcx().def_map.borrow()[expr.id].full_def();
match def { match def {
def::DefConst(def_id) => { def::DefConst(def_id) => {
if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) { if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
@ -582,7 +582,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
_ => break, _ => break,
} }
} }
let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned(); let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def());
if let Some(def::DefStatic(def_id, _)) = opt_def { if let Some(def::DefStatic(def_id, _)) = opt_def {
return get_static_val(cx, def_id, ety); return get_static_val(cx, def_id, ety);
} }
@ -664,7 +664,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
} }
} }
ast::ExprPath(_) | ast::ExprQPath(_) => { ast::ExprPath(_) | ast::ExprQPath(_) => {
let def = cx.tcx().def_map.borrow()[e.id]; let def = cx.tcx().def_map.borrow()[e.id].full_def();
match def { match def {
def::DefFn(..) | def::DefMethod(..) => { def::DefFn(..) | def::DefMethod(..) => {
expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
@ -701,7 +701,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
} }
} }
ast::ExprCall(ref callee, ref args) => { ast::ExprCall(ref callee, ref args) => {
let opt_def = cx.tcx().def_map.borrow().get(&callee.id).cloned(); let opt_def = cx.tcx().def_map.borrow().get(&callee.id).map(|d| d.full_def());
let arg_vals = map_list(&args[..]); let arg_vals = map_list(&args[..]);
match opt_def { match opt_def {
Some(def::DefStruct(_)) => { Some(def::DefStruct(_)) => {

View file

@ -306,11 +306,10 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let loop_id = match opt_label { let loop_id = match opt_label {
None => fcx.top_loop_scope(), None => fcx.top_loop_scope(),
Some(_) => { Some(_) => {
match bcx.tcx().def_map.borrow().get(&expr.id) { match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
Some(&def::DefLabel(loop_id)) => loop_id, Some(def::DefLabel(loop_id)) => loop_id,
ref r => { r => {
bcx.tcx().sess.bug(&format!("{:?} in def-map for label", bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r))
r))
} }
} }
} }

View file

@ -1363,7 +1363,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
ty.repr(tcx))); ty.repr(tcx)));
} }
Some(node_id) => { Some(node_id) => {
let def = tcx.def_map.borrow()[node_id].clone(); let def = tcx.def_map.borrow()[node_id].full_def();
match def { match def {
def::DefVariant(enum_id, variant_id, _) => { def::DefVariant(enum_id, variant_id, _) => {
let variant_info = ty::enum_variant_with_id( let variant_info = ty::enum_variant_with_id(

View file

@ -898,7 +898,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
match ty.node { match ty.node {
ast::TyPath(ref path) => { ast::TyPath(ref path) => {
let def = this.tcx().def_map.borrow().get(&ty.id).cloned(); let def = this.tcx().def_map.borrow().get(&ty.id).map(|d| d.full_def());
match def { match def {
Some(def::DefTrait(trait_def_id)) => { Some(def::DefTrait(trait_def_id)) => {
let mut projection_bounds = Vec::new(); let mut projection_bounds = Vec::new();
@ -1303,16 +1303,14 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds) conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
} }
ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => { ast::TyPath(ref path) | ast::TyQPath(ast::QPath { ref path, .. }) => {
let result = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
(d, 0) d
} else if let Some(d) = tcx.partial_def_map.borrow().get(&ast_ty.id) {
(d.base_type, (d.extra_associated_types + 1) as usize)
} else { } else {
tcx.sess.span_bug(ast_ty.span, tcx.sess.span_bug(ast_ty.span,
&format!("unbound path {}", ast_ty.repr(tcx))) &format!("unbound path {}", ast_ty.repr(tcx)))
}; };
let (mut def, max_depth) = result; let mut def = path_res.base_def;
let base_ty_end = path.segments.len() - max_depth; let base_ty_end = path.segments.len() - path_res.depth;
let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node { let opt_self_ty = if let ast::TyQPath(ref qpath) = ast_ty.node {
Some(ast_ty_to_ty(this, rscope, &*qpath.self_type)) Some(ast_ty_to_ty(this, rscope, &*qpath.self_type))
} else { } else {
@ -1324,9 +1322,13 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
&path.segments[..base_ty_end], &path.segments[..base_ty_end],
&path.segments[base_ty_end..]); &path.segments[base_ty_end..]);
if max_depth != 0 && ty.sty != ty::ty_err { if path_res.depth != 0 && ty.sty != ty::ty_err {
// Write back the new resolution. // Write back the new resolution.
tcx.def_map.borrow_mut().insert(ast_ty.id, def); tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution {
base_def: def,
last_private: path_res.last_private,
depth: 0
});
} }
ty ty

View file

@ -103,7 +103,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
demand::eqtype(fcx, pat.span, expected, lhs_ty); demand::eqtype(fcx, pat.span, expected, lhs_ty);
} }
ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => { ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
let const_did = tcx.def_map.borrow()[pat.id].clone().def_id(); let const_did = tcx.def_map.borrow()[pat.id].def_id();
let const_scheme = ty::lookup_item_type(tcx, const_did); let const_scheme = ty::lookup_item_type(tcx, const_did);
assert!(const_scheme.generics.is_empty()); assert!(const_scheme.generics.is_empty());
let const_ty = pcx.fcx.instantiate_type_scheme(pat.span, let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
@ -433,7 +433,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
let fcx = pcx.fcx; let fcx = pcx.fcx;
let tcx = pcx.fcx.ccx.tcx; let tcx = pcx.fcx.ccx.tcx;
let def = tcx.def_map.borrow()[pat.id].clone(); let def = tcx.def_map.borrow()[pat.id].full_def();
let (enum_def_id, variant_def_id) = match def { let (enum_def_id, variant_def_id) = match def {
def::DefTrait(_) => { def::DefTrait(_) => {
let name = pprust::path_to_string(path); let name = pprust::path_to_string(path);
@ -502,7 +502,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
let fcx = pcx.fcx; let fcx = pcx.fcx;
let tcx = pcx.fcx.ccx.tcx; let tcx = pcx.fcx.ccx.tcx;
let def = tcx.def_map.borrow()[pat.id].clone(); let def = tcx.def_map.borrow()[pat.id].full_def();
let enum_def = def.variant_def_ids() let enum_def = def.variant_def_ids()
.map_or_else(|| def.def_id(), |(enum_def, _)| enum_def); .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);

View file

@ -91,7 +91,6 @@ use middle::infer;
use middle::mem_categorization as mc; use middle::mem_categorization as mc;
use middle::mem_categorization::McResult; use middle::mem_categorization::McResult;
use middle::pat_util::{self, pat_id_map}; use middle::pat_util::{self, pat_id_map};
use middle::privacy::{AllPublic, LastMod};
use middle::region::{self, CodeExtent}; use middle::region::{self, CodeExtent};
use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace}; use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
use middle::traits; use middle::traits;
@ -3598,21 +3597,23 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
None None
}; };
// Helpers to avoid keeping the RefCell borrow for too long. let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
let get_def = || tcx.def_map.borrow().get(&id).cloned(); d
let get_partial_def = || tcx.partial_def_map.borrow().get(&id).cloned(); } else {
tcx.sess.span_bug(expr.span,
&format!("unbound path {}", expr.repr(tcx))[])
};
if let Some(def) = get_def() { let mut def = path_res.base_def;
if path_res.depth == 0 {
let (scheme, predicates) = let (scheme, predicates) =
type_scheme_and_predicates_for_def(fcx, expr.span, def); type_scheme_and_predicates_for_def(fcx, expr.span, def);
instantiate_path(fcx, &path.segments, instantiate_path(fcx, &path.segments,
scheme, &predicates, scheme, &predicates,
None, def, expr.span, id); opt_self_ty, def, expr.span, id);
} else if let Some(partial) = get_partial_def() { } else {
let mut def = partial.base_type;
let ty_segments = path.segments.init(); let ty_segments = path.segments.init();
let ty_assoc_num = partial.extra_associated_types as usize; let base_ty_end = path.segments.len() - path_res.depth;
let base_ty_end = ty_segments.len() - ty_assoc_num;
let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span, let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span,
PathParamMode::Optional, PathParamMode::Optional,
&mut def, &mut def,
@ -3624,13 +3625,11 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) { match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
Ok((def, lp)) => { Ok((def, lp)) => {
// Write back the new resolution. // Write back the new resolution.
tcx.def_map.borrow_mut().insert(id, def); tcx.def_map.borrow_mut().insert(id, def::PathResolution {
base_def: def,
if let LastMod(AllPublic) = lp { last_private: path_res.last_private.or(lp),
// Public method, don't change the last private entry. depth: 0
} else { });
tcx.last_private_map.borrow_mut().insert(id, lp);
}
let (scheme, predicates) = let (scheme, predicates) =
type_scheme_and_predicates_for_def(fcx, expr.span, def); type_scheme_and_predicates_for_def(fcx, expr.span, def);
@ -3644,9 +3643,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
fcx.write_error(id); fcx.write_error(id);
} }
} }
} else {
tcx.sess.span_bug(expr.span,
&format!("unbound path {}", expr.repr(tcx))[])
} }
// We always require that the type provided as the value for // We always require that the type provided as the value for
@ -3882,7 +3878,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
} }
ast::ExprStruct(ref path, ref fields, ref base_expr) => { ast::ExprStruct(ref path, ref fields, ref base_expr) => {
// Resolve the path. // Resolve the path.
let def = tcx.def_map.borrow().get(&id).cloned(); let def = tcx.def_map.borrow().get(&id).map(|d| d.full_def());
let struct_id = match def { let struct_id = match def {
Some(def::DefVariant(enum_id, variant_id, true)) => { Some(def::DefVariant(enum_id, variant_id, true)) => {
check_struct_enum_variant(fcx, id, expr.span, enum_id, check_struct_enum_variant(fcx, id, expr.span, enum_id,
@ -5174,8 +5170,8 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
(block_query(b, |e| { (block_query(b, |e| {
match e.node { match e.node {
ast::ExprBreak(Some(_)) => { ast::ExprBreak(Some(_)) => {
match cx.def_map.borrow().get(&e.id) { match cx.def_map.borrow().get(&e.id).map(|d| d.full_def()) {
Some(&def::DefLabel(loop_id)) if id == loop_id => true, Some(def::DefLabel(loop_id)) if id == loop_id => true,
_ => false, _ => false,
} }
} }

View file

@ -165,7 +165,7 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
} }
fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def { fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
match tcx.def_map.borrow().get(&id) { match tcx.def_map.borrow().get(&id) {
Some(x) => x.clone(), Some(x) => x.full_def(),
_ => { _ => {
span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition") span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
} }

View file

@ -46,7 +46,7 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Ident>)
None => return None, None => return None,
}; };
let def = match tcx.def_map.borrow().get(&id) { let def = match tcx.def_map.borrow().get(&id) {
Some(def) => *def, Some(d) => d.full_def(),
None => return None, None => return None,
}; };
let did = def.def_id(); let did = def.def_id();

View file

@ -2388,7 +2388,7 @@ fn resolve_type(cx: &DocContext,
}; };
debug!("searching for {} in defmap", id); debug!("searching for {} in defmap", id);
let def = match tcx.def_map.borrow().get(&id) { let def = match tcx.def_map.borrow().get(&id) {
Some(&k) => k, Some(k) => k.full_def(),
None => panic!("unresolved id not in defmap") None => panic!("unresolved id not in defmap")
}; };
@ -2454,7 +2454,7 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<ast::DefId> { fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<ast::DefId> {
cx.tcx_opt().and_then(|tcx| { cx.tcx_opt().and_then(|tcx| {
tcx.def_map.borrow().get(&id).map(|&def| register_def(cx, def)) tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def()))
}) })
} }

View file

@ -196,7 +196,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
Some(tcx) => tcx, Some(tcx) => tcx,
None => return false None => return false
}; };
let def = (*tcx.def_map.borrow())[id].def_id(); let def = tcx.def_map.borrow()[id].def_id();
if !ast_util::is_local(def) { return false } if !ast_util::is_local(def) { return false }
let analysis = match self.analysis { let analysis = match self.analysis {
Some(analysis) => analysis, None => return false Some(analysis) => analysis, None => return false