Auto merge of #34095 - petrochenkov:pathir2, r=jseyfried

Improvements to pattern resolution + some refactoring

Continuation of https://github.com/rust-lang/rust/pull/33929
First commit is a careful rewrite of `resolve_pattern`, pattern path resolution and new binding creation logic is factored out in separate functions, some minor bugs are fixed. Also, `resolve_possibly_assoc_item` doesn't swallow modules now.
Later commits are refactorings, see the comment descriptions.

I intend to continue this work later with better support for `Def::Err` in patterns in post-resolve stages and cleanup of pattern resolution code in type checker.

Fixes https://github.com/rust-lang/rust/issues/32086
Fixes https://github.com/rust-lang/rust/issues/34047 ([breaking-change])
Fixes https://github.com/rust-lang/rust/issues/34074

cc @jseyfried
r? @eddyb
This commit is contained in:
bors 2016-06-09 15:48:37 -07:00 committed by GitHub
commit 7d2f75a953
73 changed files with 697 additions and 1218 deletions

View File

@ -574,8 +574,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
return *self.loop_scopes.last().unwrap(); return *self.loop_scopes.last().unwrap();
} }
match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) { match self.tcx.expect_def(expr.id) {
Some(Def::Label(loop_id)) => { Def::Label(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;

View File

@ -67,6 +67,10 @@ pub struct PathResolution {
} }
impl PathResolution { impl PathResolution {
pub fn new(def: Def) -> PathResolution {
PathResolution { base_def: def, depth: 0 }
}
/// Get the definition, if fully resolved, otherwise panic. /// Get the definition, if fully resolved, otherwise panic.
pub fn full_def(&self) -> Def { pub fn full_def(&self) -> Def {
if self.depth != 0 { if self.depth != 0 {
@ -75,17 +79,11 @@ impl PathResolution {
self.base_def self.base_def
} }
/// Get the DefId, if fully resolved, otherwise panic. pub fn kind_name(&self) -> &'static str {
pub fn def_id(&self) -> DefId { if self.depth != 0 {
self.full_def().def_id() "associated item"
} } else {
self.base_def.kind_name()
pub fn new(base_def: Def,
depth: usize)
-> PathResolution {
PathResolution {
base_def: base_def,
depth: depth,
} }
} }
} }
@ -161,8 +159,8 @@ impl Def {
Def::Struct(..) => "struct", Def::Struct(..) => "struct",
Def::Trait(..) => "trait", Def::Trait(..) => "trait",
Def::Method(..) => "method", Def::Method(..) => "method",
Def::Const(..) => "const", Def::Const(..) => "constant",
Def::AssociatedConst(..) => "associated const", Def::AssociatedConst(..) => "associated constant",
Def::TyParam(..) => "type parameter", Def::TyParam(..) => "type parameter",
Def::PrimTy(..) => "builtin type", Def::PrimTy(..) => "builtin type",
Def::Local(..) => "local variable", Def::Local(..) => "local variable",

View File

@ -866,7 +866,7 @@ impl<'a> LoweringContext<'a> {
PatKind::Wild => hir::PatKind::Wild, PatKind::Wild => hir::PatKind::Wild,
PatKind::Ident(ref binding_mode, pth1, ref sub) => { PatKind::Ident(ref binding_mode, pth1, ref sub) => {
self.with_parent_def(p.id, |this| { self.with_parent_def(p.id, |this| {
match this.resolver.get_resolution(p.id).map(|d| d.full_def()) { match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
// `None` can occur in body-less function signatures // `None` can occur in body-less function signatures
None | Some(Def::Local(..)) => { None | Some(Def::Local(..)) => {
hir::PatKind::Binding(this.lower_binding_mode(binding_mode), hir::PatKind::Binding(this.lower_binding_mode(binding_mode),
@ -1238,14 +1238,10 @@ impl<'a> LoweringContext<'a> {
position: position, position: position,
} }
}); });
let rename = if path.segments.len() == 1 { // Only local variables are renamed
// Only local variables are renamed let rename = match self.resolver.get_resolution(e.id).map(|d| d.base_def) {
match self.resolver.get_resolution(e.id).map(|d| d.full_def()) { Some(Def::Local(..)) | Some(Def::Upvar(..)) => true,
Some(Def::Local(..)) | Some(Def::Upvar(..)) => true, _ => false,
_ => false,
}
} else {
false
}; };
hir::ExprPath(hir_qself, self.lower_path_full(path, rename)) hir::ExprPath(hir_qself, self.lower_path_full(path, rename))
} }

View File

@ -53,16 +53,6 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
} }
} }
// This is used because same-named variables in alternative patterns need to
// use the NodeId of their namesake in the first pattern.
pub fn pat_id_map(pat: &hir::Pat) -> PatIdMap {
let mut map = FnvHashMap();
pat_bindings(pat, |_bm, p_id, _s, path1| {
map.insert(path1.node, p_id);
});
map
}
pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool { pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node { match pat.node {
PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::QPath(..) => true, PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::QPath(..) => true,

View File

@ -1357,17 +1357,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
ty_queue.push(&mut_ty.ty); ty_queue.push(&mut_ty.ty);
} }
hir::TyPath(ref maybe_qself, ref path) => { hir::TyPath(ref maybe_qself, ref path) => {
let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) { match self.tcx.expect_def(cur_ty.id) {
None => {
self.tcx
.sess
.fatal(&format!(
"unbound path {}",
pprust::path_to_string(path)))
}
Some(d) => d.full_def()
};
match a_def {
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => { Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
let generics = self.tcx.lookup_item_type(did).generics; let generics = self.tcx.lookup_item_type(did).generics;

View File

@ -65,13 +65,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// to it. /// to it.
pub fn ast_ty_to_prim_ty(self, ast_ty: &ast::Ty) -> Option<Ty<'tcx>> { pub fn ast_ty_to_prim_ty(self, ast_ty: &ast::Ty) -> Option<Ty<'tcx>> {
if let ast::TyPath(None, ref path) = ast_ty.node { if let ast::TyPath(None, ref path) = ast_ty.node {
let def = match self.def_map.borrow().get(&ast_ty.id) { if let Def::PrimTy(nty) = self.expect_def(ast_ty.id) {
None => {
span_bug!(ast_ty.span, "unbound path {:?}", path)
}
Some(d) => d.full_def()
};
if let Def::PrimTy(nty) = def {
Some(self.prim_ty_to_ty(&path.segments, nty)) Some(self.prim_ty_to_ty(&path.segments, nty))
} else { } else {
None None

View File

@ -84,36 +84,35 @@ 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) {
use ty::TypeVariants::{TyEnum, TyStruct}; use ty::TypeVariants::{TyEnum, TyStruct};
// If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar` // If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar`
self.tcx.tables.borrow().item_substs.get(id) self.tcx.tables.borrow().item_substs.get(&id)
.and_then(|substs| substs.substs.self_ty()) .and_then(|substs| substs.substs.self_ty())
.map(|ty| match ty.sty { .map(|ty| match ty.sty {
TyEnum(tyid, _) | TyStruct(tyid, _) => self.check_def_id(tyid.did), TyEnum(tyid, _) | TyStruct(tyid, _) => self.check_def_id(tyid.did),
_ => (), _ => (),
}); });
self.tcx.def_map.borrow().get(id).map(|def| { let def = self.tcx.expect_def(id);
match def.full_def() { match def {
Def::Const(_) | Def::AssociatedConst(..) => { Def::Const(_) | Def::AssociatedConst(..) => {
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::PrimTy(_) => (), Def::PrimTy(_) => (),
Def::SelfTy(..) => (), Def::SelfTy(..) => (),
Def::Variant(enum_id, variant_id) => { Def::Variant(enum_id, variant_id) => {
self.check_def_id(enum_id); self.check_def_id(enum_id);
if !self.ignore_variant_stack.contains(&variant_id) { if !self.ignore_variant_stack.contains(&variant_id) {
self.check_def_id(variant_id); self.check_def_id(variant_id);
}
}
_ => {
self.check_def_id(def.def_id());
} }
} }
}); _ => {
self.check_def_id(def.def_id());
}
}
} }
fn lookup_and_handle_method(&mut self, id: ast::NodeId) { fn lookup_and_handle_method(&mut self, id: ast::NodeId) {
@ -138,10 +137,10 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, fn handle_field_pattern_match(&mut self, lhs: &hir::Pat,
pats: &[codemap::Spanned<hir::FieldPat>]) { pats: &[codemap::Spanned<hir::FieldPat>]) {
let def = self.tcx.def_map.borrow().get(&lhs.id).unwrap().full_def(); let variant = match self.tcx.node_id_to_type(lhs.id).sty {
let pat_ty = self.tcx.node_id_to_type(lhs.id); ty::TyStruct(adt, _) | ty::TyEnum(adt, _) => {
let variant = match pat_ty.sty { adt.variant_of_def(self.tcx.expect_def(lhs.id))
ty::TyStruct(adt, _) | ty::TyEnum(adt, _) => adt.variant_of_def(def), }
_ => span_bug!(lhs.span, "non-ADT in struct pattern") _ => span_bug!(lhs.span, "non-ADT in struct pattern")
}; };
for pat in pats { for pat in pats {
@ -272,7 +271,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
} }
_ if pat_util::pat_is_const(&def_map.borrow(), pat) => { _ if pat_util::pat_is_const(&def_map.borrow(), pat) => {
// it might be the only use of a const // it might be the only use of a const
self.lookup_and_handle_definition(&pat.id) self.lookup_and_handle_definition(pat.id)
} }
_ => () _ => ()
} }
@ -283,12 +282,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
} }
fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) { fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
self.lookup_and_handle_definition(&id); self.lookup_and_handle_definition(id);
intravisit::walk_path(self, path); intravisit::walk_path(self, path);
} }
fn visit_path_list_item(&mut self, path: &hir::Path, item: &hir::PathListItem) { fn visit_path_list_item(&mut self, path: &hir::Path, item: &hir::PathListItem) {
self.lookup_and_handle_definition(&item.node.id()); self.lookup_and_handle_definition(item.node.id());
intravisit::walk_path_list_item(self, path, item); intravisit::walk_path_list_item(self, path, item);
} }
} }

View File

@ -172,7 +172,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
self.require_unsafe(expr.span, "use of inline assembly"); self.require_unsafe(expr.span, "use of inline assembly");
} }
hir::ExprPath(..) => { hir::ExprPath(..) => {
if let Def::Static(_, true) = self.tcx.resolve_expr(expr) { if let Def::Static(_, true) = self.tcx.expect_def(expr.id) {
self.require_unsafe(expr.span, "use of mutable static"); self.require_unsafe(expr.span, "use of mutable static");
} }
} }

View File

@ -955,9 +955,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr,
pat); pat);
let tcx = &self.tcx();
let mc = &self.mc; let mc = &self.mc;
let infcx = self.mc.infcx; let infcx = self.mc.infcx;
let def_map = &self.tcx().def_map;
let delegate = &mut self.delegate; let delegate = &mut self.delegate;
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
match pat.node { match pat.node {
@ -972,8 +972,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// 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().get(&pat.id).unwrap().full_def(); if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) { tcx.expect_def(pat.id)) {
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init); delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
} }
@ -1002,14 +1002,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// to the above loop's visit of than the bindings that form // to the above loop's visit of than the bindings that form
// the leaves of the pattern tree structure. // the leaves of the pattern tree structure.
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| { return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
let def_map = def_map.borrow();
let tcx = infcx.tcx;
match pat.node { match pat.node {
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Struct(..) | PatKind::TupleStruct(..) |
PatKind::Path(..) | PatKind::QPath(..) => { PatKind::Path(..) | PatKind::QPath(..) => {
match def_map.get(&pat.id).map(|d| d.full_def()) { match tcx.expect_def(pat.id) {
Some(Def::Variant(enum_did, variant_did)) => { Def::Variant(enum_did, variant_did) => {
let downcast_cmt = let downcast_cmt =
if tcx.lookup_adt_def(enum_did).is_univariant() { if tcx.lookup_adt_def(enum_did).is_univariant() {
cmt_pat cmt_pat
@ -1025,7 +1022,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
delegate.matched_pat(pat, downcast_cmt, match_mode); delegate.matched_pat(pat, downcast_cmt, match_mode);
} }
Some(Def::Struct(..)) | Some(Def::TyAlias(..)) => { Def::Struct(..) | Def::TyAlias(..) => {
// 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).
@ -1037,8 +1034,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
delegate.matched_pat(pat, cmt_pat, match_mode); delegate.matched_pat(pat, cmt_pat, match_mode);
} }
Some(Def::Const(..)) | Def::Const(..) | Def::AssociatedConst(..) => {
Some(Def::AssociatedConst(..)) => {
// 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.

View File

@ -156,7 +156,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> {
fn visit_expr(&mut self, expr: &hir::Expr) { fn visit_expr(&mut self, expr: &hir::Expr) {
if let hir::ExprPath(..) = expr.node { if let hir::ExprPath(..) = expr.node {
match self.infcx.tcx.resolve_expr(expr) { match self.infcx.tcx.expect_def(expr.id) {
Def::Fn(did) if self.def_id_is_transmute(did) => { Def::Fn(did) if self.def_id_is_transmute(did) => {
let typ = self.infcx.tcx.node_id_to_type(expr.id); let typ = self.infcx.tcx.node_id_to_type(expr.id);
match typ.sty { match typ.sty {

View File

@ -445,7 +445,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:
hir::ExprPath(..) => { hir::ExprPath(..) => {
let def = ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def(); let def = ir.tcx.expect_def(expr.id);
debug!("expr {}: path that leads to {:?}", expr.id, def); debug!("expr {}: path that leads to {:?}", expr.id, def);
if let Def::Local(..) = def { if let Def::Local(..) = def {
ir.add_live_node_for_node(expr.id, ExprNode(expr.span)); ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
@ -695,8 +695,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).map(|d| d.full_def()) { match self.ir.tcx.expect_def(id) {
Some(Def::Label(loop_id)) => loop_id, Def::Label(loop_id) => loop_id,
_ => span_bug!(sp, "label on break/loop \ _ => span_bug!(sp, "label on break/loop \
doesn't refer to a loop") doesn't refer to a loop")
} }
@ -1269,7 +1269,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32) fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
-> LiveNode { -> LiveNode {
match self.ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() { match self.ir.tcx.expect_def(expr.id) {
Def::Local(_, nid) => { Def::Local(_, 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 {
@ -1534,9 +1534,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 {
hir::ExprPath(..) => { hir::ExprPath(..) => {
if let Def::Local(_, nid) = self.ir.tcx.def_map.borrow().get(&expr.id) if let Def::Local(_, nid) = self.ir.tcx.expect_def(expr.id) {
.unwrap()
.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

@ -517,8 +517,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
} }
hir::ExprPath(..) => { hir::ExprPath(..) => {
let def = self.tcx().def_map.borrow().get(&expr.id).unwrap().full_def(); self.cat_def(expr.id, expr.span, expr_ty, self.tcx().expect_def(expr.id))
self.cat_def(expr.id, expr.span, expr_ty, def)
} }
hir::ExprType(ref e, _) => { hir::ExprType(ref e, _) => {
@ -1106,18 +1105,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
(*op)(self, cmt.clone(), pat); (*op)(self, cmt.clone(), pat);
let opt_def = if let Some(path_res) = self.tcx().def_map.borrow().get(&pat.id) { let opt_def = self.tcx().expect_def_or_none(pat.id);
if path_res.depth != 0 || path_res.base_def == Def::Err { if opt_def == Some(Def::Err) {
// Since patterns can be associated constants return Err(());
// which are resolved during typeck, we might have }
// some unresolved patterns reaching this stage
// without aborting
return Err(());
}
Some(path_res.full_def())
} else {
None
};
// Note: This goes up here (rather than within the PatKind::TupleStruct arm // Note: This goes up here (rather than within the PatKind::TupleStruct arm
// alone) because struct patterns can refer to struct types or // alone) because struct patterns can refer to struct types or

View File

@ -92,13 +92,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
fn visit_expr(&mut self, expr: &hir::Expr) { fn visit_expr(&mut self, expr: &hir::Expr) {
match expr.node { match expr.node {
hir::ExprPath(..) => { hir::ExprPath(..) => {
let def = match self.tcx.def_map.borrow().get(&expr.id) { let def = self.tcx.expect_def(expr.id);
Some(d) => d.full_def(),
None => {
span_bug!(expr.span, "def ID not in def map?!")
}
};
let def_id = def.def_id(); let def_id = def.def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
if self.def_id_represents_local_inlined_item(def_id) { if self.def_id_represents_local_inlined_item(def_id) {

View File

@ -494,7 +494,7 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// individually as it's possible to have a stable trait with unstable // individually as it's possible to have a stable trait with unstable
// items. // items.
hir::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => { hir::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => {
let trait_did = tcx.def_map.borrow().get(&t.ref_id).unwrap().def_id(); let trait_did = tcx.expect_def(t.ref_id).def_id();
let trait_items = tcx.trait_items(trait_did); let trait_items = tcx.trait_items(trait_did);
for impl_item in impl_items { for impl_item in impl_items {
@ -580,7 +580,8 @@ pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cb: &mut FnMut(DefId, Span, cb: &mut FnMut(DefId, Span,
&Option<&Stability>, &Option<&Stability>,
&Option<Deprecation>)) { &Option<Deprecation>)) {
match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) { // Paths in import prefixes may have no resolution.
match tcx.expect_def_or_none(id) {
Some(Def::PrimTy(..)) => {} Some(Def::PrimTy(..)) => {}
Some(Def::SelfTy(..)) => {} Some(Def::SelfTy(..)) => {}
Some(def) => { Some(def) => {
@ -595,12 +596,11 @@ pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cb: &mut FnMut(DefId, Span, cb: &mut FnMut(DefId, Span,
&Option<&Stability>, &Option<&Stability>,
&Option<Deprecation>)) { &Option<Deprecation>)) {
match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) { match tcx.expect_def(item.node.id()) {
Some(Def::PrimTy(..)) => {} Def::PrimTy(..) => {}
Some(def) => { def => {
maybe_do_stability_check(tcx, def.def_id(), item.span, cb); maybe_do_stability_check(tcx, def.def_id(), item.span, cb);
} }
None => {}
} }
} }

View File

@ -22,7 +22,7 @@ use dep_graph::{self, DepNode};
use hir::map as ast_map; use hir::map as ast_map;
use middle; use middle;
use middle::cstore::{self, LOCAL_CRATE}; use middle::cstore::{self, LOCAL_CRATE};
use hir::def::{self, Def, ExportMap}; use hir::def::{Def, PathResolution, ExportMap};
use hir::def_id::DefId; use hir::def_id::DefId;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::region::{CodeExtent, ROOT_CODE_EXTENT}; use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
@ -308,13 +308,11 @@ impl Visibility {
match *visibility { match *visibility {
hir::Public => Visibility::Public, hir::Public => Visibility::Public,
hir::Visibility::Crate => Visibility::Restricted(ast::CRATE_NODE_ID), hir::Visibility::Crate => Visibility::Restricted(ast::CRATE_NODE_ID),
hir::Visibility::Restricted { id, .. } => match tcx.def_map.borrow().get(&id) { hir::Visibility::Restricted { id, .. } => match tcx.expect_def(id) {
Some(resolution) => Visibility::Restricted({
tcx.map.as_local_node_id(resolution.base_def.def_id()).unwrap()
}),
// If there is no resolution, `resolve` will have already reported an error, so // If there is no resolution, `resolve` will have already reported an error, so
// assume that the visibility is public to avoid reporting more privacy errors. // assume that the visibility is public to avoid reporting more privacy errors.
None => Visibility::Public, Def::Err => Visibility::Public,
def => Visibility::Restricted(tcx.map.as_local_node_id(def.def_id()).unwrap()),
}, },
hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)), hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
} }
@ -2249,34 +2247,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub fn resolve_expr(self, expr: &hir::Expr) -> Def {
match self.def_map.borrow().get(&expr.id) {
Some(def) => def.full_def(),
None => {
span_bug!(expr.span, "no def-map entry for expr {}", expr.id);
}
}
}
pub fn expr_is_lval(self, expr: &hir::Expr) -> bool { pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
match expr.node { match expr.node {
hir::ExprPath(..) => { hir::ExprPath(..) => {
// We can't use resolve_expr here, as this needs to run on broken // This function can be used during type checking when not all paths are
// programs. We don't need to through - associated items are all // fully resolved. Partially resolved paths in expressions can only legally
// rvalues. // refer to associated items which are always rvalues.
match self.def_map.borrow().get(&expr.id) { match self.expect_resolution(expr.id).base_def {
Some(&def::PathResolution { Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
base_def: Def::Static(..), .. _ => false,
}) | Some(&def::PathResolution {
base_def: Def::Upvar(..), ..
}) | Some(&def::PathResolution {
base_def: Def::Local(..), ..
}) => {
true
}
Some(&def::PathResolution { base_def: Def::Err, .. })=> true,
Some(..) => false,
None => span_bug!(expr.span, "no def for path {}", expr.id)
} }
} }
@ -2459,8 +2438,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
} }
} }
pub fn trait_ref_to_def_id(self, tr: &hir::TraitRef) -> DefId { /// Returns a path resolution for node id if it exists, panics otherwise.
self.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id() pub fn expect_resolution(self, id: NodeId) -> PathResolution {
*self.def_map.borrow().get(&id).expect("no def-map entry for node id")
}
/// Returns a fully resolved definition for node id if it exists, panics otherwise.
pub fn expect_def(self, id: NodeId) -> Def {
self.expect_resolution(id).full_def()
}
/// Returns a fully resolved definition for node id if it exists, or none if no
/// definition exists, panics on partial resolutions to catch errors.
pub fn expect_def_or_none(self, id: NodeId) -> Option<Def> {
self.def_map.borrow().get(&id).map(|resolution| resolution.full_def())
} }
pub fn def_key(self, id: DefId) -> ast_map::DefKey { pub fn def_key(self, id: DefId) -> ast_map::DefKey {

View File

@ -245,8 +245,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), name, None) = p.node { if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), name, None) = p.node {
let pat_ty = cx.tcx.pat_ty(p); let pat_ty = cx.tcx.pat_ty(p);
if let ty::TyEnum(edef, _) = pat_ty.sty { if let ty::TyEnum(edef, _) = pat_ty.sty {
let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); if let Def::Local(..) = cx.tcx.expect_def(p.id) {
if let Some(Def::Local(..)) = def {
if edef.variants.iter().any(|variant| if edef.variants.iter().any(|variant|
variant.name == name.node.unhygienize() variant.name == name.node.unhygienize()
&& variant.kind() == VariantKind::Unit && variant.kind() == VariantKind::Unit
@ -492,9 +491,8 @@ 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 {
PatKind::Path(..) | PatKind::QPath(..) => { PatKind::Path(..) | PatKind::QPath(..) => {
let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()); match self.tcx.expect_def(pat.id) {
match def { Def::AssociatedConst(did) | Def::Const(did) => {
Some(Def::AssociatedConst(did)) | Some(Def::Const(did)) => {
let substs = Some(self.tcx.node_id_item_substs(pat.id).substs); let substs = Some(self.tcx.node_id_item_substs(pat.id).substs);
if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) { if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) {
match const_expr_to_pat(self.tcx, const_expr, pat.id, pat.span) { match const_expr_to_pat(self.tcx, const_expr, pat.id, pat.span) {
@ -788,7 +786,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
let pat = raw_pat(p); let pat = raw_pat(p);
match pat.node { match pat.node {
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) =>
match cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def() { match cx.tcx.expect_def(pat.id) {
Def::Const(..) | Def::AssociatedConst(..) => Def::Const(..) | Def::AssociatedConst(..) =>
span_bug!(pat.span, "const pattern should've \ span_bug!(pat.span, "const pattern should've \
been rewritten"), been rewritten"),
@ -903,21 +901,19 @@ pub fn specialize<'a, 'b, 'tcx>(
Some(vec![dummy_pat; arity]), Some(vec![dummy_pat; arity]),
PatKind::Path(..) => { PatKind::Path(..) => {
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def(); match cx.tcx.expect_def(pat_id) {
match def {
Def::Const(..) | Def::AssociatedConst(..) => Def::Const(..) | Def::AssociatedConst(..) =>
span_bug!(pat_span, "const pattern should've \ span_bug!(pat_span, "const pattern should've \
been rewritten"), been rewritten"),
Def::Variant(_, id) if *constructor != Variant(id) => None, Def::Variant(_, id) if *constructor != Variant(id) => None,
Def::Variant(..) | Def::Struct(..) => Some(Vec::new()), Def::Variant(..) | Def::Struct(..) => Some(Vec::new()),
_ => span_bug!(pat_span, "specialize: unexpected \ def => span_bug!(pat_span, "specialize: unexpected \
definition {:?}", def), definition {:?}", def),
} }
} }
PatKind::TupleStruct(_, ref args, ddpos) => { PatKind::TupleStruct(_, ref args, ddpos) => {
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def(); match cx.tcx.expect_def(pat_id) {
match def {
Def::Const(..) | Def::AssociatedConst(..) => Def::Const(..) | Def::AssociatedConst(..) =>
span_bug!(pat_span, "const pattern should've \ span_bug!(pat_span, "const pattern should've \
been rewritten"), been rewritten"),
@ -944,10 +940,9 @@ pub fn specialize<'a, 'b, 'tcx>(
} }
PatKind::Struct(_, ref pattern_fields, _) => { PatKind::Struct(_, ref pattern_fields, _) => {
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap(); let adt = cx.tcx.node_id_to_type(pat_id).ty_adt_def().unwrap();
let variant = constructor.variant_for_adt(adt); let variant = constructor.variant_for_adt(adt);
let def_variant = adt.variant_of_def(def); let def_variant = adt.variant_of_def(cx.tcx.expect_def(pat_id));
if variant.did == def_variant.did { if variant.did == def_variant.did {
Some(variant.fields.iter().map(|sf| { Some(variant.fields.iter().map(|sf| {
match pattern_fields.iter().find(|f| f.node.name == sf.name) { match pattern_fields.iter().find(|f| f.node.name == sf.name) {

View File

@ -19,7 +19,7 @@ use rustc::hir::map as ast_map;
use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::blocks::FnLikeNode;
use rustc::middle::cstore::{self, InlinedItem}; use rustc::middle::cstore::{self, InlinedItem};
use rustc::traits; use rustc::traits;
use rustc::hir::def::Def; use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::hir::pat_util::def_to_path; use rustc::hir::pat_util::def_to_path;
use rustc::ty::{self, Ty, TyCtxt, subst}; use rustc::ty::{self, Ty, TyCtxt, subst};
@ -276,11 +276,11 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.collect()), None), .collect()), None),
hir::ExprCall(ref callee, ref args) => { hir::ExprCall(ref callee, ref args) => {
let def = *tcx.def_map.borrow().get(&callee.id).unwrap(); let def = tcx.expect_def(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(PathResolution::new(def));
} }
let path = match def.full_def() { let path = match def {
Def::Struct(def_id) => def_to_path(tcx, def_id), Def::Struct(def_id) => def_to_path(tcx, def_id),
Def::Variant(_, variant_did) => def_to_path(tcx, variant_did), Def::Variant(_, variant_did) => def_to_path(tcx, variant_did),
Def::Fn(..) | Def::Method(..) => return Ok(P(hir::Pat { Def::Fn(..) | Def::Method(..) => return Ok(P(hir::Pat {
@ -322,12 +322,9 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
hir::ExprPath(_, ref path) => { hir::ExprPath(_, ref path) => {
let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()); match tcx.expect_def(expr.id) {
match opt_def { Def::Struct(..) | Def::Variant(..) => PatKind::Path(path.clone()),
Some(Def::Struct(..)) | Some(Def::Variant(..)) => Def::Const(def_id) | Def::AssociatedConst(def_id) => {
PatKind::Path(path.clone()),
Some(Def::Const(def_id)) |
Some(Def::AssociatedConst(def_id)) => {
let substs = Some(tcx.node_id_item_substs(expr.id).substs); let substs = Some(tcx.node_id_item_substs(expr.id).substs);
let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap(); let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap();
return const_expr_to_pat(tcx, expr, pat_id, span); return const_expr_to_pat(tcx, expr, pat_id, span);
@ -714,21 +711,13 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
} }
hir::ExprPath(..) => { hir::ExprPath(..) => {
let opt_def = if let Some(def) = tcx.def_map.borrow().get(&e.id) { // This function can be used before type checking when not all paths are fully resolved.
// After type-checking, def_map contains definition of the // FIXME: There's probably a better way to make sure we don't panic here.
// item referred to by the path. During type-checking, it let resolution = tcx.expect_resolution(e.id);
// can contain the raw output of path resolution, which if resolution.depth != 0 {
// might be a partially resolved path. signal!(e, UnresolvedPath);
// FIXME: There's probably a better way to make sure we don't }
// panic here. match resolution.base_def {
if def.depth != 0 {
signal!(e, UnresolvedPath);
}
def.full_def()
} else {
signal!(e, NonConstPath);
};
match opt_def {
Def::Const(def_id) | Def::Const(def_id) |
Def::AssociatedConst(def_id) => { Def::AssociatedConst(def_id) => {
let substs = if let ExprTypeChecked = ty_hint { let substs = if let ExprTypeChecked = ty_hint {

View File

@ -276,7 +276,7 @@ impl LateLintPass for NonSnakeCase {
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
if let &PatKind::Binding(_, ref path1, _) = &p.node { if let &PatKind::Binding(_, ref path1, _) = &p.node {
// Exclude parameter names from foreign functions (they have no `Def`) // Exclude parameter names from foreign functions (they have no `Def`)
if cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()).is_some() { if cx.tcx.expect_def_or_none(p.id).is_some() {
self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span)); self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span));
} }
} }
@ -362,8 +362,7 @@ impl LateLintPass for NonUpperCaseGlobals {
// Lint for constants that look like binding identifiers (#7526) // Lint for constants that look like binding identifiers (#7526)
if let PatKind::Path(ref path) = p.node { if let PatKind::Path(ref path) = p.node {
if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() { if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
if let Some(Def::Const(..)) = cx.tcx.def_map.borrow().get(&p.id) if let Def::Const(..) = cx.tcx.expect_def(p.id) {
.map(|d| d.full_def()) {
NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern", NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
path.segments[0].name, path.span); path.segments[0].name, path.span);
} }

View File

@ -157,20 +157,11 @@ impl LintPass for NonShorthandFieldPatterns {
impl LateLintPass for NonShorthandFieldPatterns { impl LateLintPass for NonShorthandFieldPatterns {
fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) { fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
let def_map = cx.tcx.def_map.borrow(); if let PatKind::Struct(_, ref field_pats, _) = pat.node {
if let PatKind::Struct(_, ref v, _) = pat.node {
let field_pats = v.iter().filter(|fieldpat| {
if fieldpat.node.is_shorthand {
return false;
}
let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
if let Some(def_id) = cx.tcx.map.opt_local_def_id(fieldpat.node.pat.id) {
def == Some(Def::Local(def_id, fieldpat.node.pat.id))
} else {
false
}
});
for fieldpat in field_pats { for fieldpat in field_pats {
if fieldpat.node.is_shorthand {
continue;
}
if let PatKind::Binding(_, ident, None) = fieldpat.node.pat.node { if let PatKind::Binding(_, ident, None) = fieldpat.node.pat.node {
if ident.node.unhygienize() == fieldpat.node.name { if ident.node.unhygienize() == fieldpat.node.name {
cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
@ -377,7 +368,7 @@ impl LateLintPass for MissingDoc {
hir::ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) => { hir::ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) => {
// If the trait is private, add the impl items to private_traits so they don't get // If the trait is private, add the impl items to private_traits so they don't get
// reported for missing docs. // reported for missing docs.
let real_trait = cx.tcx.trait_ref_to_def_id(trait_ref); let real_trait = cx.tcx.expect_def(trait_ref.ref_id).def_id();
if let Some(node_id) = cx.tcx.map.as_local_node_id(real_trait) { if let Some(node_id) = cx.tcx.map.as_local_node_id(real_trait) {
match cx.tcx.map.find(node_id) { match cx.tcx.map.find(node_id) {
Some(hir_map::NodeItem(item)) => if item.vis == hir::Visibility::Inherited { Some(hir_map::NodeItem(item)) => if item.vis == hir::Visibility::Inherited {
@ -780,11 +771,9 @@ impl LateLintPass for UnconditionalRecursion {
id: ast::NodeId) -> bool { id: ast::NodeId) -> bool {
match tcx.map.get(id) { match tcx.map.get(id) {
hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
tcx.def_map tcx.expect_def_or_none(callee.id).map_or(false, |def| {
.borrow() def.def_id() == tcx.map.local_def_id(fn_id)
.get(&callee.id) })
.map_or(false,
|def| def.def_id() == tcx.map.local_def_id(fn_id))
} }
_ => false _ => false
} }
@ -820,7 +809,9 @@ impl LateLintPass for UnconditionalRecursion {
// Check for calls to methods via explicit paths (e.g. `T::method()`). // Check for calls to methods via explicit paths (e.g. `T::method()`).
match tcx.map.get(id) { match tcx.map.get(id) {
hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
match tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()) { // The callee is an arbitrary expression,
// it doesn't necessarily have a definition.
match tcx.expect_def_or_none(callee.id) {
Some(Def::Method(def_id)) => { Some(Def::Method(def_id)) => {
let item_substs = tcx.node_id_item_substs(callee.id); let item_substs = tcx.node_id_item_substs(callee.id);
method_call_refers_to_method( method_call_refers_to_method(
@ -1057,7 +1048,7 @@ impl LateLintPass for MutableTransmutes {
hir::ExprPath(..) => (), hir::ExprPath(..) => (),
_ => return None _ => return None
} }
if let Def::Fn(did) = cx.tcx.resolve_expr(expr) { if let Def::Fn(did) = cx.tcx.expect_def(expr.id) {
if !def_id_is_transmute(cx, did) { if !def_id_is_transmute(cx, did) {
return None; return None;
} }

View File

@ -719,7 +719,7 @@ 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).map(|d| d.full_def()) { if let Some(def) = tcx.expect_def_or_none(id) {
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);
def.encode(rbml_w).unwrap(); def.encode(rbml_w).unwrap();
@ -1133,10 +1133,7 @@ fn decode_side_tables(dcx: &DecodeContext,
match value { match value {
c::tag_table_def => { c::tag_table_def => {
let def = decode_def(dcx, val_dsr); let def = decode_def(dcx, val_dsr);
dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution { dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution::new(def));
base_def: def,
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

@ -9,7 +9,6 @@
// except according to those terms. // except according to those terms.
use hair::*; use hair::*;
use rustc_data_structures::fnv::FnvHashMap;
use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::Idx;
use rustc_const_math::ConstInt; use rustc_const_math::ConstInt;
use hair::cx::Cx; use hair::cx::Cx;
@ -20,7 +19,6 @@ use rustc::hir::def::Def;
use rustc::middle::const_val::ConstVal; use rustc::middle::const_val::ConstVal;
use rustc_const_eval as const_eval; use rustc_const_eval as const_eval;
use rustc::middle::region::CodeExtent; use rustc::middle::region::CodeExtent;
use rustc::hir::pat_util;
use rustc::ty::{self, VariantDef, Ty}; use rustc::ty::{self, VariantDef, Ty};
use rustc::ty::cast::CastKind as TyCastKind; use rustc::ty::cast::CastKind as TyCastKind;
use rustc::mir::repr::*; use rustc::mir::repr::*;
@ -264,7 +262,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let adt_data = if let hir::ExprPath(..) = fun.node { let adt_data = if let hir::ExprPath(..) = fun.node {
// Tuple-like ADTs are represented as ExprCall. We convert them here. // Tuple-like ADTs are represented as ExprCall. We convert them here.
expr_ty.ty_adt_def().and_then(|adt_def|{ expr_ty.ty_adt_def().and_then(|adt_def|{
match cx.tcx.def_map.borrow()[&fun.id].full_def() { match cx.tcx.expect_def(fun.id) {
Def::Variant(_, variant_id) => { Def::Variant(_, variant_id) => {
Some((adt_def, adt_def.variant_index_with_id(variant_id))) Some((adt_def, adt_def.variant_index_with_id(variant_id)))
}, },
@ -472,7 +470,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
} }
} }
ty::TyEnum(adt, substs) => { ty::TyEnum(adt, substs) => {
match cx.tcx.def_map.borrow()[&expr.id].full_def() { match cx.tcx.expect_def(expr.id) {
Def::Variant(enum_id, variant_id) => { Def::Variant(enum_id, variant_id) => {
debug_assert!(adt.did == enum_id); debug_assert!(adt.did == enum_id);
assert!(base.is_none()); assert!(base.is_none());
@ -652,19 +650,8 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
arm: &'tcx hir::Arm) -> Arm<'tcx> { arm: &'tcx hir::Arm) -> Arm<'tcx> {
let mut map;
let opt_map = if arm.pats.len() == 1 {
None
} else {
map = FnvHashMap();
pat_util::pat_bindings(&arm.pats[0], |_, p_id, _, path| {
map.insert(path.node, p_id);
});
Some(&map)
};
Arm { Arm {
patterns: arm.pats.iter().map(|p| cx.refutable_pat(opt_map, p)).collect(), patterns: arm.pats.iter().map(|p| cx.refutable_pat(p)).collect(),
guard: arm.guard.to_ref(), guard: arm.guard.to_ref(),
body: arm.body.to_ref(), body: arm.body.to_ref(),
} }
@ -675,7 +662,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
-> ExprKind<'tcx> { -> ExprKind<'tcx> {
let substs = cx.tcx.node_id_item_substs(expr.id).substs; let substs = cx.tcx.node_id_item_substs(expr.id).substs;
// Otherwise there may be def_map borrow conflicts // Otherwise there may be def_map borrow conflicts
let def = cx.tcx.def_map.borrow()[&expr.id].full_def(); let def = cx.tcx.expect_def(expr.id);
let def_id = match def { let def_id = match def {
// A regular function. // A regular function.
Def::Fn(def_id) | Def::Method(def_id) => def_id, Def::Fn(def_id) | Def::Method(def_id) => def_id,
@ -731,14 +718,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
id: node_id, id: node_id,
}, },
def @ Def::Local(..) | Def::Local(..) | Def::Upvar(..) => return convert_var(cx, expr, def),
def @ Def::Upvar(..) => return convert_var(cx, expr, def),
def => _ => span_bug!(expr.span, "def `{:?}` not yet implemented", def),
span_bug!(
expr.span,
"def `{:?}` not yet implemented",
def),
}; };
ExprKind::Literal { ExprKind::Literal {
literal: Literal::Item { def_id: def_id, substs: substs } literal: Literal::Item { def_id: def_id, substs: substs }
@ -1039,11 +1021,9 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
fn loop_label<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, fn loop_label<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr) -> CodeExtent { expr: &'tcx hir::Expr) -> CodeExtent {
match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) { match cx.tcx.expect_def(expr.id) {
Some(Def::Label(loop_id)) => cx.tcx.region_maps.node_extent(loop_id), Def::Label(loop_id) => cx.tcx.region_maps.node_extent(loop_id),
d => { d => span_bug!(expr.span, "loop scope resolved to {:?}", d),
span_bug!(expr.span, "loop scope resolved to {:?}", d);
}
} }
} }

View File

@ -10,7 +10,6 @@
use hair::*; use hair::*;
use hair::cx::Cx; use hair::cx::Cx;
use rustc_data_structures::fnv::FnvHashMap;
use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::Idx;
use rustc_const_eval as const_eval; use rustc_const_eval as const_eval;
use rustc::hir::def::Def; use rustc::hir::def::Def;
@ -18,7 +17,6 @@ use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::mir::repr::*; use rustc::mir::repr::*;
use rustc::hir::{self, PatKind}; use rustc::hir::{self, PatKind};
use syntax::ast;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ptr::P; use syntax::ptr::P;
@ -37,29 +35,25 @@ use syntax::ptr::P;
/// ``` /// ```
struct PatCx<'patcx, 'cx: 'patcx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { struct PatCx<'patcx, 'cx: 'patcx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>, cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>,
binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>,
} }
impl<'cx, 'gcx, 'tcx> Cx<'cx, 'gcx, 'tcx> { impl<'cx, 'gcx, 'tcx> Cx<'cx, 'gcx, 'tcx> {
pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
PatCx::new(self, None).to_pattern(pat) PatCx::new(self).to_pattern(pat)
} }
pub fn refutable_pat(&mut self, pub fn refutable_pat(&mut self,
binding_map: Option<&FnvHashMap<ast::Name, ast::NodeId>>,
pat: &hir::Pat) pat: &hir::Pat)
-> Pattern<'tcx> { -> Pattern<'tcx> {
PatCx::new(self, binding_map).to_pattern(pat) PatCx::new(self).to_pattern(pat)
} }
} }
impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> { impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>, fn new(cx: &'patcx mut Cx<'cx, 'gcx, 'tcx>)
binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>)
-> PatCx<'patcx, 'cx, 'gcx, 'tcx> { -> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
PatCx { PatCx {
cx: cx, cx: cx,
binding_map: binding_map,
} }
} }
@ -85,8 +79,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
PatKind::Path(..) | PatKind::QPath(..) PatKind::Path(..) | PatKind::QPath(..)
if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) => if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) =>
{ {
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); match self.cx.tcx.expect_def(pat.id) {
match def {
Def::Const(def_id) | Def::AssociatedConst(def_id) => { Def::Const(def_id) | Def::AssociatedConst(def_id) => {
let tcx = self.cx.tcx.global_tcx(); let tcx = self.cx.tcx.global_tcx();
let substs = Some(self.cx.tcx.node_id_item_substs(pat.id).substs); let substs = Some(self.cx.tcx.node_id_item_substs(pat.id).substs);
@ -111,7 +104,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
} }
} }
} }
_ => def =>
span_bug!( span_bug!(
pat.span, pat.span,
"def not a constant: {:?}", "def not a constant: {:?}",
@ -169,10 +162,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
} }
PatKind::Binding(bm, ref ident, ref sub) => { PatKind::Binding(bm, ref ident, ref sub) => {
let id = match self.binding_map { let id = self.cx.tcx.expect_def(pat.id).var_id();
None => pat.id,
Some(ref map) => map[&ident.node],
};
let var_ty = self.cx.tcx.node_id_to_type(pat.id); let var_ty = self.cx.tcx.node_id_to_type(pat.id);
let region = match var_ty.sty { let region = match var_ty.sty {
ty::TyRef(&r, _) => Some(r), ty::TyRef(&r, _) => Some(r),
@ -219,8 +209,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def, ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def,
_ => span_bug!(pat.span, "tuple struct pattern not applied to struct or enum"), _ => span_bug!(pat.span, "tuple struct pattern not applied to struct or enum"),
}; };
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); let variant_def = adt_def.variant_of_def(self.cx.tcx.expect_def(pat.id));
let variant_def = adt_def.variant_of_def(def);
let subpatterns = let subpatterns =
subpatterns.iter() subpatterns.iter()
@ -243,9 +232,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
"struct pattern not applied to struct or enum"); "struct pattern not applied to struct or enum");
} }
}; };
let variant_def = adt_def.variant_of_def(self.cx.tcx.expect_def(pat.id));
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
let variant_def = adt_def.variant_of_def(def);
let subpatterns = let subpatterns =
fields.iter() fields.iter()
@ -324,8 +311,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
pat: &hir::Pat, pat: &hir::Pat,
subpatterns: Vec<FieldPattern<'tcx>>) subpatterns: Vec<FieldPattern<'tcx>>)
-> PatternKind<'tcx> { -> PatternKind<'tcx> {
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); match self.cx.tcx.expect_def(pat.id) {
match def {
Def::Variant(enum_id, variant_id) => { Def::Variant(enum_id, variant_id) => {
let adt_def = self.cx.tcx.lookup_adt_def(enum_id); let adt_def = self.cx.tcx.lookup_adt_def(enum_id);
if adt_def.variants.len() > 1 { if adt_def.variants.len() > 1 {
@ -343,7 +329,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
PatternKind::Leaf { subpatterns: subpatterns } PatternKind::Leaf { subpatterns: subpatterns }
} }
_ => { def => {
span_bug!(pat.span, "inappropriate def for pattern: {:?}", def); span_bug!(pat.span, "inappropriate def for pattern: {:?}", def);
} }
} }

View File

@ -499,38 +499,36 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
} }
} }
hir::ExprPath(..) => { hir::ExprPath(..) => {
let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def()); match v.tcx.expect_def(e.id) {
match def { Def::Variant(..) => {
Some(Def::Variant(..)) => {
// Count the discriminator or function pointer. // Count the discriminator or function pointer.
v.add_qualif(ConstQualif::NON_ZERO_SIZED); v.add_qualif(ConstQualif::NON_ZERO_SIZED);
} }
Some(Def::Struct(..)) => { Def::Struct(..) => {
if let ty::TyFnDef(..) = node_ty.sty { if let ty::TyFnDef(..) = node_ty.sty {
// Count the function pointer. // Count the function pointer.
v.add_qualif(ConstQualif::NON_ZERO_SIZED); v.add_qualif(ConstQualif::NON_ZERO_SIZED);
} }
} }
Some(Def::Fn(..)) | Some(Def::Method(..)) => { Def::Fn(..) | Def::Method(..) => {
// Count the function pointer. // Count the function pointer.
v.add_qualif(ConstQualif::NON_ZERO_SIZED); v.add_qualif(ConstQualif::NON_ZERO_SIZED);
} }
Some(Def::Static(..)) => { Def::Static(..) => {
match v.mode { match v.mode {
Mode::Static | Mode::StaticMut => {} Mode::Static | Mode::StaticMut => {}
Mode::Const | Mode::ConstFn => {} Mode::Const | Mode::ConstFn => {}
Mode::Var => v.add_qualif(ConstQualif::NOT_CONST) Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
} }
} }
Some(Def::Const(did)) | Def::Const(did) | Def::AssociatedConst(did) => {
Some(Def::AssociatedConst(did)) => {
let substs = Some(v.tcx.node_id_item_substs(e.id).substs); let substs = Some(v.tcx.node_id_item_substs(e.id).substs);
if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) { if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) {
let inner = v.global_expr(Mode::Const, expr); let inner = v.global_expr(Mode::Const, expr);
v.add_qualif(inner); v.add_qualif(inner);
} }
} }
Some(Def::Local(..)) if v.mode == Mode::ConstFn => { Def::Local(..) if v.mode == Mode::ConstFn => {
// Sadly, we can't determine whether the types are zero-sized. // Sadly, we can't determine whether the types are zero-sized.
v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED); v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
} }
@ -550,8 +548,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
_ => break _ => break
}; };
} }
let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()); // The callee is an arbitrary expression, it doesn't necessarily have a definition.
let is_const = match def { let is_const = match v.tcx.expect_def_or_none(callee.id) {
Some(Def::Struct(..)) => true, Some(Def::Struct(..)) => true,
Some(Def::Variant(..)) => { Some(Def::Variant(..)) => {
// Count the discriminator. // Count the discriminator.
@ -586,8 +584,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
} }
} }
hir::ExprStruct(..) => { hir::ExprStruct(..) => {
let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id()); // unsafe_cell_type doesn't necessarily exist with no_core
if did == v.tcx.lang_items.unsafe_cell_type() { if Some(v.tcx.expect_def(e.id).def_id()) == v.tcx.lang_items.unsafe_cell_type() {
v.add_qualif(ConstQualif::MUTABLE_MEM); v.add_qualif(ConstQualif::MUTABLE_MEM);
} }
} }

View File

@ -65,7 +65,7 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> { fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
if let hir::TyPath(..) = ty.node { if let hir::TyPath(..) = ty.node {
match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() { match self.tcx.expect_def(ty.id) {
Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => { Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
Some(AccessLevel::Public) Some(AccessLevel::Public)
} }
@ -83,7 +83,7 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
} }
fn trait_level(&self, trait_ref: &hir::TraitRef) -> Option<AccessLevel> { fn trait_level(&self, trait_ref: &hir::TraitRef) -> Option<AccessLevel> {
let did = self.tcx.trait_ref_to_def_id(trait_ref); let did = self.tcx.expect_def(trait_ref.ref_id).def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(did) { if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
self.get(node_id) self.get(node_id)
} else { } else {
@ -317,7 +317,7 @@ impl<'b, 'a, 'tcx: 'a> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
fn visit_ty(&mut self, ty: &hir::Ty) { fn visit_ty(&mut self, ty: &hir::Ty) {
if let hir::TyPath(_, ref path) = ty.node { if let hir::TyPath(_, ref path) = ty.node {
let def = self.ev.tcx.def_map.borrow().get(&ty.id).unwrap().full_def(); let def = self.ev.tcx.expect_def(ty.id);
match def { match def {
Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) | Def::Struct(def_id) | Def::Enum(def_id) | Def::TyAlias(def_id) |
Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => { Def::Trait(def_id) | Def::AssociatedTy(def_id, _) => {
@ -343,7 +343,7 @@ impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor<
} }
fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) { fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) {
let def_id = self.ev.tcx.trait_ref_to_def_id(trait_ref); let def_id = self.ev.tcx.expect_def(trait_ref.ref_id).def_id();
if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) { if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) {
let item = self.ev.tcx.map.expect_item(node_id); let item = self.ev.tcx.map.expect_item(node_id);
self.ev.update(item.id, Some(AccessLevel::Reachable)); self.ev.update(item.id, Some(AccessLevel::Reachable));
@ -426,7 +426,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
} }
hir::ExprStruct(..) => { hir::ExprStruct(..) => {
let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap(); let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap();
let variant = adt.variant_of_def(self.tcx.resolve_expr(expr)); let variant = adt.variant_of_def(self.tcx.expect_def(expr.id));
// RFC 736: ensure all unmentioned fields are visible. // RFC 736: ensure all unmentioned fields are visible.
// Rather than computing the set of unmentioned fields // Rather than computing the set of unmentioned fields
// (i.e. `all_fields - fields`), just check them all. // (i.e. `all_fields - fields`), just check them all.
@ -436,7 +436,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
} }
hir::ExprPath(..) => { hir::ExprPath(..) => {
if let Def::Struct(..) = self.tcx.resolve_expr(expr) { if let Def::Struct(..) = self.tcx.expect_def(expr.id) {
let expr_ty = self.tcx.expr_ty(expr); let expr_ty = self.tcx.expr_ty(expr);
let def = match expr_ty.sty { let def = match expr_ty.sty {
ty::TyFnDef(_, _, &ty::BareFnTy { sig: ty::Binder(ty::FnSig { ty::TyFnDef(_, _, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
@ -470,8 +470,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
match pattern.node { match pattern.node {
PatKind::Struct(_, ref fields, _) => { PatKind::Struct(_, ref fields, _) => {
let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap(); let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap();
let def = self.tcx.def_map.borrow().get(&pattern.id).unwrap().full_def(); let variant = adt.variant_of_def(self.tcx.expect_def(pattern.id));
let variant = adt.variant_of_def(def);
for field in fields { for field in fields {
self.check_field(pattern.span, adt, variant.field_named(field.node.name)); self.check_field(pattern.span, adt, variant.field_named(field.node.name));
} }
@ -534,10 +533,9 @@ struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'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).map(|d| d.full_def()) { let did = match self.tcx.expect_def(path_id) {
// `int` etc. (None doesn't seem to occur.) Def::PrimTy(..) | Def::SelfTy(..) => return false,
None | Some(Def::PrimTy(..)) | Some(Def::SelfTy(..)) => return false, def => def.def_id(),
Some(def) => def.def_id(),
}; };
// A path can only be private if: // A path can only be private if:
@ -653,7 +651,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
let not_private_trait = let not_private_trait =
trait_ref.as_ref().map_or(true, // no trait counts as public trait trait_ref.as_ref().map_or(true, // no trait counts as public trait
|tr| { |tr| {
let did = self.tcx.trait_ref_to_def_id(tr); let did = self.tcx.expect_def(tr.ref_id).def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(did) { if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
self.trait_is_public(node_id) self.trait_is_public(node_id)
@ -911,8 +909,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
fn visit_ty(&mut self, ty: &hir::Ty) { fn visit_ty(&mut self, ty: &hir::Ty) {
if let hir::TyPath(_, ref path) = ty.node { if let hir::TyPath(_, ref path) = ty.node {
let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def(); match self.tcx.expect_def(ty.id) {
match def {
Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => { Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
// Public // Public
} }
@ -962,7 +959,7 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) { fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) {
// Non-local means public (private items can't leave their crate, modulo bugs) // Non-local means public (private items can't leave their crate, modulo bugs)
let def_id = self.tcx.trait_ref_to_def_id(trait_ref); let def_id = self.tcx.expect_def(trait_ref.ref_id).def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
let item = self.tcx.map.expect_item(node_id); let item = self.tcx.map.expect_item(node_id);
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);

View File

@ -677,100 +677,6 @@ fn foo<T>(x: T) {} // ok!
``` ```
"##, "##,
E0413: r##"
A declaration shadows an enum variant or unit-like struct in scope. Example of
erroneous code:
```compile_fail
struct Foo;
let Foo = 12i32; // error: declaration of `Foo` shadows an enum variant or
// unit-like struct in scope
```
To fix this error, rename the variable such that it doesn't shadow any enum
variable or structure in scope. Example:
```
struct Foo;
let foo = 12i32; // ok!
```
Or:
```
struct FooStruct;
let Foo = 12i32; // ok!
```
The goal here is to avoid a conflict of names.
"##,
E0414: r##"
A variable binding in an irrefutable pattern is shadowing the name of a
constant. Example of erroneous code:
```compile_fail
const FOO: u8 = 7;
let FOO = 5; // error: variable bindings cannot shadow constants
// or
fn bar(FOO: u8) { // error: variable bindings cannot shadow constants
}
// or
for FOO in bar {
}
```
Introducing a new variable in Rust is done through a pattern. Thus you can have
`let` bindings like `let (a, b) = ...`. However, patterns also allow constants
in them, e.g. if you want to match over a constant:
```ignore
const FOO: u8 = 1;
match (x,y) {
(3, 4) => { .. }, // it is (3,4)
(FOO, 1) => { .. }, // it is (1,1)
(foo, 1) => { .. }, // it is (anything, 1)
// call the value in the first slot "foo"
_ => { .. } // it is anything
}
```
Here, the second arm matches the value of `x` against the constant `FOO`,
whereas the third arm will accept any value of `x` and call it `foo`.
This works for `match`, however in cases where an irrefutable pattern is
required, constants can't be used. An irrefutable pattern is one which always
matches, whose purpose is only to bind variable names to values. These are
required by let, for, and function argument patterns.
Refutable patterns in such a situation do not make sense, for example:
```ignore
let Some(x) = foo; // what if foo is None, instead?
let (1, x) = foo; // what if foo.0 is not 1?
let (SOME_CONST, x) = foo; // what if foo.0 is not SOME_CONST?
let SOME_CONST = foo; // what if foo is not SOME_CONST?
```
Thus, an irrefutable variable binding can't contain a constant.
To fix this error, just give the marked variable a different name.
"##,
E0415: r##" E0415: r##"
More than one function parameter have the same name. Example of erroneous code: More than one function parameter have the same name. Example of erroneous code:
@ -814,60 +720,6 @@ match (A, B, C) {
``` ```
"##, "##,
E0417: r##"
A static variable was referenced in a pattern. Example of erroneous code:
```compile_fail
static FOO : i32 = 0;
match 0 {
FOO => {} // error: static variables cannot be referenced in a
// pattern, use a `const` instead
_ => {}
}
```
The compiler needs to know the value of the pattern at compile time;
compile-time patterns can defined via const or enum items. Please verify
that the identifier is spelled correctly, and if so, use a const instead
of static to define it. Example:
```
const FOO : i32 = 0;
match 0 {
FOO => {} // ok!
_ => {}
}
```
"##,
E0419: r##"
An unknown enum variant, struct or const was used. Example of erroneous code:
```compile_fail
match 0 {
Something::Foo => {} // error: unresolved enum variant, struct
// or const `Foo`
}
```
Please verify you didn't misspell it and the enum variant, struct or const has
been declared and imported into scope. Example:
```
enum Something {
Foo,
NotFoo,
}
match Something::NotFoo {
Something::Foo => {} // ok!
_ => {}
}
```
"##,
E0422: r##" E0422: r##"
You are trying to use an identifier that is either undefined or not a struct. You are trying to use an identifier that is either undefined or not a struct.
For instance: For instance:
@ -1255,8 +1107,15 @@ register_diagnostics! {
E0402, // cannot use an outer type parameter in this context E0402, // cannot use an outer type parameter in this context
E0406, // undeclared associated type E0406, // undeclared associated type
// E0410, merged into 408 // E0410, merged into 408
E0418, // is not an enum variant, struct or const // E0413, merged into 530
E0420, // is not an associated const // E0414, merged into 530
E0421, // unresolved associated const // E0417, merged into 532
E0427, // cannot use `ref` binding mode with ... // E0418, merged into 532
// E0419, merged into 531
// E0420, merged into 532
// E0421, merged into 531
E0530, // X bindings cannot shadow Ys
E0531, // unresolved pattern path kind `name`
E0532, // expected pattern path kind, found another pattern path kind
// E0427, merged into 530
} }

File diff suppressed because it is too large Load Diff

View File

@ -598,7 +598,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
Some(def) => def, Some(def) => def,
None => value_result.success().and_then(NameBinding::def).unwrap(), None => value_result.success().and_then(NameBinding::def).unwrap(),
}; };
let path_resolution = PathResolution { base_def: def, depth: 0 }; let path_resolution = PathResolution::new(def);
self.resolver.def_map.insert(directive.id, path_resolution); self.resolver.def_map.insert(directive.id, path_resolution);
debug!("(resolving single import) successfully resolved import"); debug!("(resolving single import) successfully resolved import");
@ -644,7 +644,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
// Record the destination of this import // Record the destination of this import
if let Some(did) = target_module.def_id() { if let Some(did) = target_module.def_id() {
let resolution = PathResolution { base_def: Def::Mod(did), depth: 0 }; let resolution = PathResolution::new(Def::Mod(did));
self.resolver.def_map.insert(directive.id, resolution); self.resolver.def_map.insert(directive.id, resolution);
} }

View File

@ -269,14 +269,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
// looks up anything, not just a type // looks up anything, not just a type
fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> { fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
if !self.tcx.def_map.borrow().contains_key(&ref_id) { match self.tcx.expect_def(ref_id) {
bug!("def_map has no key for {} in lookup_type_ref", ref_id);
}
let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
match def {
Def::PrimTy(..) => None, Def::PrimTy(..) => None,
Def::SelfTy(..) => None, Def::SelfTy(..) => None,
_ => Some(def.def_id()), def => Some(def.def_id()),
} }
} }
@ -290,13 +286,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
return; return;
} }
let def_map = self.tcx.def_map.borrow(); let def = self.tcx.expect_def(ref_id);
if !def_map.contains_key(&ref_id) {
span_bug!(span,
"def_map has no key for {} in lookup_def_kind",
ref_id);
}
let def = def_map.get(&ref_id).unwrap().full_def();
match def { match def {
Def::Mod(_) | Def::Mod(_) |
Def::ForeignMod(_) => { Def::ForeignMod(_) => {
@ -853,9 +843,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
} }
// Modules or types in the path prefix. // Modules or types in the path prefix.
let def_map = self.tcx.def_map.borrow(); match self.tcx.expect_def(id) {
let def = def_map.get(&id).unwrap().full_def();
match def {
Def::Method(did) => { Def::Method(did) => {
let ti = self.tcx.impl_or_trait_item(did); let ti = self.tcx.impl_or_trait_item(did);
if let ty::MethodTraitItem(m) = ti { if let ty::MethodTraitItem(m) = ti {
@ -924,8 +912,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
PatKind::Struct(ref path, ref fields, _) => { PatKind::Struct(ref path, ref fields, _) => {
visit::walk_path(self, path); visit::walk_path(self, path);
let adt = self.tcx.node_id_to_type(p.id).ty_adt_def().unwrap(); let adt = self.tcx.node_id_to_type(p.id).ty_adt_def().unwrap();
let def = self.tcx.def_map.borrow()[&p.id].full_def(); let variant = adt.variant_of_def(self.tcx.expect_def(p.id));
let variant = adt.variant_of_def(def);
for &Spanned { node: ref field, span } in fields { for &Spanned { node: ref field, span } in fields {
let sub_span = self.span.span_for_first_ident(span); let sub_span = self.span.span_for_first_ident(span);
@ -1269,7 +1256,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
ast::ExprKind::Struct(ref path, ref fields, ref base) => { ast::ExprKind::Struct(ref path, ref fields, ref base) => {
let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id); let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id);
let adt = self.tcx.expr_ty(&hir_expr).ty_adt_def().unwrap(); let adt = self.tcx.expr_ty(&hir_expr).ty_adt_def().unwrap();
let def = self.tcx.resolve_expr(&hir_expr); let def = self.tcx.expect_def(hir_expr.id);
self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base) self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base)
} }
ast::ExprKind::MethodCall(_, _, ref args) => self.process_method_call(ex, args), ast::ExprKind::MethodCall(_, _, ref args) => self.process_method_call(ex, args),
@ -1366,12 +1353,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
// process collected paths // process collected paths
for &(id, ref p, immut, ref_kind) in &collector.collected_paths { for &(id, ref p, immut, ref_kind) in &collector.collected_paths {
let def_map = self.tcx.def_map.borrow(); match self.tcx.expect_def(id) {
if !def_map.contains_key(&id) {
span_bug!(p.span, "def_map has no key for {} in visit_arm", id);
}
let def = def_map.get(&id).unwrap().full_def();
match def {
Def::Local(_, id) => { Def::Local(_, id) => {
let value = if immut == ast::Mutability::Immutable { let value = if immut == ast::Mutability::Immutable {
self.span.snippet(p.span).to_string() self.span.snippet(p.span).to_string()
@ -1401,8 +1383,8 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
Def::Static(_, _) | Def::Static(_, _) |
Def::Const(..) | Def::Const(..) |
Def::AssociatedConst(..) => {} Def::AssociatedConst(..) => {}
_ => error!("unexpected definition kind when processing collected paths: {:?}", def => error!("unexpected definition kind when processing collected paths: {:?}",
def), def),
} }
} }

View File

@ -465,11 +465,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
} }
pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> { pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
let def_map = self.tcx.def_map.borrow(); let def = self.tcx.expect_def(id);
if !def_map.contains_key(&id) {
span_bug!(path.span, "def_map has no key for {} in visit_expr", id);
}
let def = def_map.get(&id).unwrap().full_def();
let sub_span = self.span_utils.span_for_last_ident(path.span); let sub_span = self.span_utils.span_for_last_ident(path.span);
filter!(self.span_utils, sub_span, path.span, None); filter!(self.span_utils, sub_span, path.span, None);
match def { match def {
@ -637,13 +633,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
} }
fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> { fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
if !self.tcx.def_map.borrow().contains_key(&ref_id) { match self.tcx.expect_def(ref_id) {
bug!("def_map has no key for {} in lookup_type_ref", ref_id);
}
let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
match def {
Def::PrimTy(_) | Def::SelfTy(..) => None, Def::PrimTy(_) | Def::SelfTy(..) => None,
_ => Some(def.def_id()), def => Some(def.def_id()),
} }
} }

View File

@ -657,9 +657,8 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
ConstantValue(ConstantExpr(&l), debug_loc) ConstantValue(ConstantExpr(&l), debug_loc)
} }
PatKind::Path(..) | PatKind::TupleStruct(..) | PatKind::Struct(..) => { PatKind::Path(..) | PatKind::TupleStruct(..) | PatKind::Struct(..) => {
let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def()); match tcx.expect_def(cur.id) {
match opt_def { Def::Variant(enum_id, var_id) => {
Some(Def::Variant(enum_id, var_id)) => {
let variant = tcx.lookup_adt_def(enum_id).variant_with_id(var_id); let variant = tcx.lookup_adt_def(enum_id).variant_with_id(var_id);
Variant(Disr::from(variant.disr_val), Variant(Disr::from(variant.disr_val),
adt::represent_node(bcx, cur.id), adt::represent_node(bcx, cur.id),
@ -796,7 +795,7 @@ fn any_irrefutable_adt_pat(tcx: TyCtxt, m: &[Match], col: usize) -> bool {
match pat.node { match pat.node {
PatKind::Tuple(..) => true, PatKind::Tuple(..) => true,
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => { PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => {
match tcx.def_map.borrow().get(&pat.id).unwrap().full_def() { match tcx.expect_def(pat.id) {
Def::Struct(..) | Def::TyAlias(..) => true, Def::Struct(..) | Def::TyAlias(..) => true,
_ => false, _ => false,
} }
@ -1444,19 +1443,19 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
/// Checks whether the binding in `discr` is assigned to anywhere in the expression `body` /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool { fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool {
let (vid, field) = match discr.node { let (vid, field) = match discr.node {
hir::ExprPath(..) => match bcx.def(discr.id) { hir::ExprPath(..) => match bcx.tcx().expect_def(discr.id) {
Def::Local(_, vid) | Def::Upvar(_, vid, _, _) => (vid, None), Def::Local(_, vid) | Def::Upvar(_, vid, _, _) => (vid, None),
_ => return false _ => return false
}, },
hir::ExprField(ref base, field) => { hir::ExprField(ref base, field) => {
let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) { let vid = match bcx.tcx().expect_def_or_none(base.id) {
Some(Def::Local(_, vid)) | Some(Def::Upvar(_, vid, _, _)) => vid, Some(Def::Local(_, vid)) | Some(Def::Upvar(_, vid, _, _)) => vid,
_ => return false _ => return false
}; };
(vid, Some(mc::NamedField(field.node))) (vid, Some(mc::NamedField(field.node)))
}, },
hir::ExprTupField(ref base, field) => { hir::ExprTupField(ref base, field) => {
let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) { let vid = match bcx.tcx().expect_def_or_none(base.id) {
Some(Def::Local(_, vid)) | Some(Def::Upvar(_, vid, _, _)) => vid, Some(Def::Local(_, vid)) | Some(Def::Upvar(_, vid, _, _)) => vid,
_ => return false _ => return false
}; };
@ -1835,9 +1834,8 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
} }
} }
PatKind::TupleStruct(_, ref sub_pats, ddpos) => { PatKind::TupleStruct(_, ref sub_pats, ddpos) => {
let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def()); match bcx.tcx().expect_def(pat.id) {
match opt_def { Def::Variant(enum_id, var_id) => {
Some(Def::Variant(enum_id, var_id)) => {
let repr = adt::represent_node(bcx, pat.id); let repr = adt::represent_node(bcx, pat.id);
let vinfo = ccx.tcx().lookup_adt_def(enum_id).variant_with_id(var_id); let vinfo = ccx.tcx().lookup_adt_def(enum_id).variant_with_id(var_id);
let args = extract_variant_args(bcx, let args = extract_variant_args(bcx,
@ -1853,7 +1851,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
cleanup_scope); cleanup_scope);
} }
} }
Some(Def::Struct(..)) => { Def::Struct(..) => {
let expected_len = match *ccx.tcx().pat_ty(&pat) { let expected_len = match *ccx.tcx().pat_ty(&pat) {
ty::TyS{sty: ty::TyStruct(adt_def, _), ..} => { ty::TyS{sty: ty::TyStruct(adt_def, _), ..} => {
adt_def.struct_variant().fields.len() adt_def.struct_variant().fields.len()

View File

@ -260,8 +260,7 @@ impl<'a, 'tcx> VariantInfo<'tcx> {
/// Return the variant corresponding to a given node (e.g. expr) /// Return the variant corresponding to a given node (e.g. expr)
pub fn of_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>, id: ast::NodeId) -> Self { pub fn of_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>, id: ast::NodeId) -> Self {
let node_def = tcx.def_map.borrow().get(&id).map(|v| v.full_def()); Self::from_ty(tcx, ty, Some(tcx.expect_def(id)))
Self::from_ty(tcx, ty, node_def)
} }
pub fn field_index(&self, name: ast::Name) -> usize { pub fn field_index(&self, name: ast::Name) -> usize {
@ -656,15 +655,6 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
self.tcx().map.node_to_string(id).to_string() self.tcx().map.node_to_string(id).to_string()
} }
pub fn def(&self, nid: ast::NodeId) -> Def {
match self.tcx().def_map.borrow().get(&nid) {
Some(v) => v.full_def(),
None => {
bug!("no def associated with node id {}", nid);
}
}
}
pub fn to_str(&self) -> String { pub fn to_str(&self) -> String {
format!("[block {:p}]", self) format!("[block {:p}]", self)
} }

View File

@ -297,8 +297,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// `def` must be its own statement and cannot be in the `match` // `def` must be its own statement and cannot be in the `match`
// otherwise the `def_map` will be borrowed for the entire match instead // otherwise the `def_map` will be borrowed for the entire match instead
// of just to get the `def` value // of just to get the `def` value
let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def(); match ccx.tcx().expect_def(expr.id) {
match def {
Def::Const(def_id) | Def::AssociatedConst(def_id) => { Def::Const(def_id) | Def::AssociatedConst(def_id) => {
if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) { if !ccx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
debug!("get_const_expr_as_global ({:?}): found const {:?}", debug!("get_const_expr_as_global ({:?}): found const {:?}",
@ -803,8 +802,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
_ => break, _ => break,
} }
} }
let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def()); if let Some(Def::Static(def_id, _)) = cx.tcx().expect_def_or_none(cur.id) {
if let Some(Def::Static(def_id, _)) = opt_def {
get_static(cx, def_id).val get_static(cx, def_id).val
} else { } else {
// If this isn't the address of a static, then keep going through // If this isn't the address of a static, then keep going through
@ -891,8 +889,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
} }
}, },
hir::ExprPath(..) => { hir::ExprPath(..) => {
let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def(); match cx.tcx().expect_def(e.id) {
match def {
Def::Local(_, id) => { Def::Local(_, id) => {
if let Some(val) = fn_args.and_then(|args| args.get(&id).cloned()) { if let Some(val) = fn_args.and_then(|args| args.get(&id).cloned()) {
val val
@ -937,9 +934,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
_ => break, _ => break,
}; };
} }
let def = cx.tcx().def_map.borrow()[&callee.id].full_def();
let arg_vals = map_list(args)?; let arg_vals = map_list(args)?;
match def { match cx.tcx().expect_def(callee.id) {
Def::Fn(did) | Def::Method(did) => { Def::Fn(did) | Def::Method(did) => {
const_fn_call( const_fn_call(
cx, cx,

View File

@ -318,8 +318,8 @@ 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).map(|d| d.full_def()) { match bcx.tcx().expect_def(expr.id) {
Some(Def::Label(loop_id)) => loop_id, Def::Label(loop_id) => loop_id,
r => { r => {
bug!("{:?} in def-map for label", r) bug!("{:?} in def-map for label", r)
} }

View File

@ -153,7 +153,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// have side effects. This seems to be reached through tuple struct constructors being // have side effects. This seems to be reached through tuple struct constructors being
// passed zero-size constants. // passed zero-size constants.
if let hir::ExprPath(..) = expr.node { if let hir::ExprPath(..) = expr.node {
match bcx.def(expr.id) { match bcx.tcx().expect_def(expr.id) {
Def::Const(_) | Def::AssociatedConst(_) => { Def::Const(_) | Def::AssociatedConst(_) => {
assert!(type_is_zero_size(bcx.ccx(), bcx.tcx().node_id_to_type(expr.id))); assert!(type_is_zero_size(bcx.ccx(), bcx.tcx().node_id_to_type(expr.id)));
return bcx; return bcx;
@ -172,7 +172,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// `[x; N]` somewhere within. // `[x; N]` somewhere within.
match expr.node { match expr.node {
hir::ExprPath(..) => { hir::ExprPath(..) => {
match bcx.def(expr.id) { match bcx.tcx().expect_def(expr.id) {
Def::Const(did) | Def::AssociatedConst(did) => { Def::Const(did) | Def::AssociatedConst(did) => {
let empty_substs = bcx.tcx().mk_substs(Substs::empty()); let empty_substs = bcx.tcx().mk_substs(Substs::empty());
let const_expr = consts::get_const_expr(bcx.ccx(), did, expr, let const_expr = consts::get_const_expr(bcx.ccx(), did, expr,
@ -651,7 +651,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
trans(bcx, &e) trans(bcx, &e)
} }
hir::ExprPath(..) => { hir::ExprPath(..) => {
let var = trans_var(bcx, bcx.def(expr.id)); let var = trans_var(bcx, bcx.tcx().expect_def(expr.id));
DatumBlock::new(bcx, var.to_expr_datum()) DatumBlock::new(bcx, var.to_expr_datum())
} }
hir::ExprField(ref base, name) => { hir::ExprField(ref base, name) => {
@ -1073,7 +1073,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
trans_into(bcx, &e, dest) trans_into(bcx, &e, dest)
} }
hir::ExprPath(..) => { hir::ExprPath(..) => {
trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest) trans_def_dps_unadjusted(bcx, expr, bcx.tcx().expect_def(expr.id), dest)
} }
hir::ExprIf(ref cond, ref thn, ref els) => { hir::ExprIf(ref cond, ref thn, ref els) => {
controlflow::trans_if(bcx, expr.id, &cond, &thn, els.as_ref().map(|e| &**e), dest) controlflow::trans_if(bcx, expr.id, &cond, &thn, els.as_ref().map(|e| &**e), dest)
@ -2373,7 +2373,7 @@ fn expr_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, expr: &hir::Expr) -> ExprKin
match expr.node { match expr.node {
hir::ExprPath(..) => { hir::ExprPath(..) => {
match tcx.resolve_expr(expr) { match tcx.expect_def(expr.id) {
// Put functions and ctors with the ADTs, as they // Put functions and ctors with the ADTs, as they
// are zero-sized, so DPS is the cheapest option. // are zero-sized, so DPS is the cheapest option.
Def::Struct(..) | Def::Variant(..) | Def::Struct(..) | Def::Variant(..) |

View File

@ -734,7 +734,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId { fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
let path = &trait_ref.path; let path = &trait_ref.path;
match ::lookup_full_def(self.tcx(), path.span, trait_ref.ref_id) { match self.tcx().expect_def(trait_ref.ref_id) {
Def::Trait(trait_def_id) => trait_def_id, Def::Trait(trait_def_id) => trait_def_id,
Def::Err => { Def::Err => {
self.tcx().sess.fatal("cannot continue compilation due to previous error"); self.tcx().sess.fatal("cannot continue compilation due to previous error");
@ -1064,12 +1064,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
match ty.node { match ty.node {
hir::TyPath(None, ref path) => { hir::TyPath(None, ref path) => {
let def = match self.tcx().def_map.borrow().get(&ty.id) { let resolution = self.tcx().expect_resolution(ty.id);
Some(&def::PathResolution { base_def, depth: 0, .. }) => Some(base_def), match resolution.base_def {
_ => None Def::Trait(trait_def_id) if resolution.depth == 0 => {
};
match def {
Some(Def::Trait(trait_def_id)) => {
let mut projection_bounds = Vec::new(); let mut projection_bounds = Vec::new();
let trait_ref = let trait_ref =
self.object_path_to_poly_trait_ref(rscope, self.object_path_to_poly_trait_ref(rscope,
@ -1721,17 +1718,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
} }
hir::TyPath(ref maybe_qself, ref path) => { hir::TyPath(ref maybe_qself, ref path) => {
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) { let path_res = tcx.expect_resolution(ast_ty.id);
d
} else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
// Create some fake resolution that can't possibly be a type.
def::PathResolution {
base_def: Def::Mod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
depth: path.segments.len()
}
} else {
span_bug!(ast_ty.span, "unbound path {:?}", ast_ty)
};
let def = path_res.base_def; let def = path_res.base_def;
let base_ty_end = path.segments.len() - path_res.depth; let base_ty_end = path.segments.len() - path_res.depth;
let opt_self_ty = maybe_qself.as_ref().map(|qself| { let opt_self_ty = maybe_qself.as_ref().map(|qself| {
@ -1748,10 +1735,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
if path_res.depth != 0 && ty.sty != ty::TyError { if path_res.depth != 0 && ty.sty != ty::TyError {
// Write back the new resolution. // Write back the new resolution.
tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution { tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution::new(def));
base_def: def,
depth: 0
});
} }
ty ty
@ -2232,7 +2216,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
for ast_bound in ast_bounds { for ast_bound in ast_bounds {
match *ast_bound { match *ast_bound {
hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => { hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) { match tcx.expect_def(b.trait_ref.ref_id) {
Def::Trait(trait_did) => { Def::Trait(trait_did) => {
if tcx.try_add_builtin_trait(trait_did, if tcx.try_add_builtin_trait(trait_did,
&mut builtin_bounds) { &mut builtin_bounds) {

View File

@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use hir::def::{self, Def}; use hir::def::Def;
use rustc::infer::{self, InferOk, TypeOrigin}; use rustc::infer::{self, InferOk, TypeOrigin};
use hir::pat_util::{PatIdMap, pat_id_map};
use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const}; use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference}; use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
@ -21,7 +20,6 @@ use session::Session;
use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::cmp; use std::cmp;
use std::ops::Deref;
use syntax::ast; use syntax::ast;
use syntax::codemap::{Span, Spanned}; use syntax::codemap::{Span, Spanned};
use syntax::ptr::P; use syntax::ptr::P;
@ -29,18 +27,6 @@ use syntax::ptr::P;
use rustc::hir::{self, PatKind}; use rustc::hir::{self, PatKind};
use rustc::hir::print as pprust; use rustc::hir::print as pprust;
pub struct PatCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
pub fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
pub map: PatIdMap,
}
impl<'a, 'gcx, 'tcx> Deref for PatCtxt<'a, 'gcx, 'tcx> {
type Target = FnCtxt<'a, 'gcx, 'tcx>;
fn deref(&self) -> &Self::Target {
self.fcx
}
}
// This function exists due to the warning "diagnostic code E0164 already used" // This function exists due to the warning "diagnostic code E0164 already used"
fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: bool) { fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: bool) {
let name = pprust::path_to_string(path); let name = pprust::path_to_string(path);
@ -55,7 +41,7 @@ fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: b
} }
} }
impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) { pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
let tcx = self.tcx; let tcx = self.tcx;
@ -150,26 +136,22 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
self.demand_eqtype(pat.span, expected, lhs_ty); self.demand_eqtype(pat.span, expected, lhs_ty);
} }
PatKind::Path(..) if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => { PatKind::Path(..) if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) { let const_did = tcx.expect_def(pat.id).def_id();
let const_did = pat_def.def_id(); let const_scheme = tcx.lookup_item_type(const_did);
let const_scheme = tcx.lookup_item_type(const_did); assert!(const_scheme.generics.is_empty());
assert!(const_scheme.generics.is_empty()); let const_ty = self.instantiate_type_scheme(pat.span,
let const_ty = self.instantiate_type_scheme(pat.span, &Substs::empty(),
&Substs::empty(), &const_scheme.ty);
&const_scheme.ty); self.write_ty(pat.id, const_ty);
self.write_ty(pat.id, const_ty);
// FIXME(#20489) -- we should limit the types here to scalars or something! // FIXME(#20489) -- we should limit the types here to scalars or something!
// As with PatKind::Lit, what we really want here is that there // As with PatKind::Lit, what we really want here is that there
// exist a LUB, but for the cases that can occur, subtype // exist a LUB, but for the cases that can occur, subtype
// is good enough. // is good enough.
self.demand_suptype(pat.span, expected, const_ty); self.demand_suptype(pat.span, expected, const_ty);
} else {
self.write_error(pat.id);
}
} }
PatKind::Binding(bm, ref path, ref sub) => { PatKind::Binding(bm, _, ref sub) => {
let typ = self.local_ty(pat.span, pat.id); let typ = self.local_ty(pat.span, pat.id);
match bm { match bm {
hir::BindByRef(mutbl) => { hir::BindByRef(mutbl) => {
@ -198,15 +180,19 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
// if there are multiple arms, make sure they all agree on // if there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be // what the type of the binding `x` ought to be
if let Some(&canon_id) = self.map.get(&path.node) { match tcx.expect_def(pat.id) {
if canon_id != pat.id { Def::Err => {}
let ct = self.local_ty(pat.span, canon_id); Def::Local(_, var_id) => {
self.demand_eqtype(pat.span, ct, typ); if var_id != pat.id {
let vt = self.local_ty(pat.span, var_id);
self.demand_eqtype(pat.span, vt, typ);
}
} }
d => bug!("bad def for pattern binding `{:?}`", d)
}
if let Some(ref p) = *sub { if let Some(ref p) = *sub {
self.check_pat(&p, expected); self.check_pat(&p, expected);
}
} }
} }
PatKind::TupleStruct(ref path, ref subpats, ddpos) => { PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
@ -217,25 +203,12 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
} }
PatKind::QPath(ref qself, ref path) => { PatKind::QPath(ref qself, ref path) => {
let self_ty = self.to_ty(&qself.ty); let self_ty = self.to_ty(&qself.ty);
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) { let path_res = tcx.expect_resolution(pat.id);
if d.base_def == Def::Err { if path_res.base_def == Def::Err {
self.set_tainted_by_errors(); self.set_tainted_by_errors();
self.write_error(pat.id);
return;
}
d
} else if qself.position == 0 {
// This is just a sentinel for finish_resolving_def_to_ty.
let sentinel = self.tcx.map.local_def_id(ast::CRATE_NODE_ID);
def::PathResolution {
base_def: Def::Mod(sentinel),
depth: path.segments.len()
}
} else {
debug!("unbound path {:?}", pat);
self.write_error(pat.id); self.write_error(pat.id);
return; return;
}; }
if let Some((opt_ty, segments, def)) = if let Some((opt_ty, segments, def)) =
self.resolve_ty_and_def_ufcs(path_res, Some(self_ty), self.resolve_ty_and_def_ufcs(path_res, Some(self_ty),
path, pat.span, pat.id) { path, pat.span, pat.id) {
@ -493,12 +466,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Typecheck the patterns first, so that we get types for all the // Typecheck the patterns first, so that we get types for all the
// bindings. // bindings.
for arm in arms { for arm in arms {
let pcx = PatCtxt {
fcx: self,
map: pat_id_map(&arm.pats[0]),
};
for p in &arm.pats { for p in &arm.pats {
pcx.check_pat(&p, discrim_ty); self.check_pat(&p, discrim_ty);
} }
} }
@ -583,13 +552,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn check_pat_struct(&self, pat: &'gcx hir::Pat, pub fn check_pat_struct(&self, pat: &'gcx hir::Pat,
path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>], path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>],
etc: bool, expected: Ty<'tcx>) { etc: bool, expected: Ty<'tcx>) {
let tcx = self.tcx; let tcx = self.tcx;
let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); let def = tcx.expect_def(pat.id);
let variant = match self.def_struct_variant(def, path.span) { let variant = match self.def_struct_variant(def, path.span) {
Some((_, variant)) => variant, Some((_, variant)) => variant,
None => { None => {
@ -630,18 +599,16 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
// Typecheck the path. // Typecheck the path.
let tcx = self.tcx; let tcx = self.tcx;
let path_res = match tcx.def_map.borrow().get(&pat.id) { let path_res = tcx.expect_resolution(pat.id);
Some(&path_res) if path_res.base_def != Def::Err => path_res, if path_res.base_def == Def::Err {
_ => { self.set_tainted_by_errors();
self.set_tainted_by_errors(); self.write_error(pat.id);
self.write_error(pat.id);
for pat in subpats { for pat in subpats {
self.check_pat(&pat, tcx.types.err); self.check_pat(&pat, tcx.types.err);
}
return;
} }
}; return;
}
let (opt_ty, segments, def) = match self.resolve_ty_and_def_ufcs(path_res, let (opt_ty, segments, def) = match self.resolve_ty_and_def_ufcs(path_res,
None, path, None, path,

View File

@ -222,7 +222,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
if let Some(pr) = tcx.def_map.borrow().get(&expr.id) { if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
if pr.depth == 0 && pr.base_def != Def::Err { if pr.depth == 0 && pr.base_def != Def::Err {
if let Some(span) = tcx.map.span_if_local(pr.def_id()) { if let Some(span) = tcx.map.span_if_local(pr.base_def.def_id()) {
err.span_note(span, "defined here"); err.span_note(span, "defined here");
} }
} }

View File

@ -81,14 +81,13 @@ pub use self::compare_method::{compare_impl_method, compare_const_impl};
use self::TupleArgumentsFlag::*; use self::TupleArgumentsFlag::*;
use astconv::{AstConv, ast_region_to_region, PathParamMode}; use astconv::{AstConv, ast_region_to_region, PathParamMode};
use check::_match::PatCtxt;
use dep_graph::DepNode; use dep_graph::DepNode;
use fmt_macros::{Parser, Piece, Position}; use fmt_macros::{Parser, Piece, Position};
use middle::cstore::LOCAL_CRATE; use middle::cstore::LOCAL_CRATE;
use hir::def::{self, Def}; use hir::def::{self, Def};
use hir::def_id::DefId; use hir::def_id::DefId;
use hir::pat_util;
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable}; use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
use hir::pat_util::{self, pat_id_map};
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace}; use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
use rustc::traits::{self, ProjectionMode}; use rustc::traits::{self, ProjectionMode};
use rustc::ty::{GenericPredicates, TypeScheme}; use rustc::ty::{GenericPredicates, TypeScheme};
@ -102,7 +101,7 @@ use rustc::ty::util::{Representability, IntTypeExt};
use require_c_abi_if_variadic; use require_c_abi_if_variadic;
use rscope::{ElisionFailureInfo, RegionScope}; use rscope::{ElisionFailureInfo, RegionScope};
use session::{Session, CompileResult}; use session::{Session, CompileResult};
use {CrateCtxt, lookup_full_def}; use CrateCtxt;
use TypeAndSubsts; use TypeAndSubsts;
use lint; use lint;
use util::common::{block_query, ErrorReported, indenter, loop_query}; use util::common::{block_query, ErrorReported, indenter, loop_query};
@ -672,11 +671,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
}); });
// Check the pattern. // Check the pattern.
let pcx = PatCtxt { fcx.check_pat(&input.pat, *arg_ty);
fcx: &fcx,
map: pat_id_map(&input.pat),
};
pcx.check_pat(&input.pat, *arg_ty);
} }
visit.visit_block(body); visit.visit_block(body);
@ -3158,7 +3153,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
// Find the relevant variant // Find the relevant variant
let def = lookup_full_def(tcx, path.span, expr.id); let def = tcx.expect_def(expr.id);
if def == Def::Err { if def == Def::Err {
self.set_tainted_by_errors(); self.set_tainted_by_errors();
self.check_struct_fields_on_error(expr.id, fields, base_expr); self.check_struct_fields_on_error(expr.id, fields, base_expr);
@ -3350,18 +3345,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.to_ty(&qself.ty) self.to_ty(&qself.ty)
}); });
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) { let path_res = tcx.expect_resolution(id);
d
} else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
// Create some fake resolution that can't possibly be a type.
def::PathResolution {
base_def: Def::Mod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
depth: path.segments.len()
}
} else {
span_bug!(expr.span, "unbound path {:?}", expr)
};
if let Some((opt_ty, segments, def)) = if let Some((opt_ty, segments, def)) =
self.resolve_ty_and_def_ufcs(path_res, opt_self_ty, path, self.resolve_ty_and_def_ufcs(path_res, opt_self_ty, path,
expr.span, expr.id) { expr.span, expr.id) {
@ -3752,10 +3736,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if let Some(def) = def { if let Some(def) = def {
// Write back the new resolution. // Write back the new resolution.
self.tcx().def_map.borrow_mut().insert(node_id, def::PathResolution { self.tcx().def_map.borrow_mut().insert(node_id, def::PathResolution::new(def));
base_def: def,
depth: 0,
});
Some((Some(ty), slice::ref_slice(item_segment), def)) Some((Some(ty), slice::ref_slice(item_segment), def))
} else { } else {
self.write_error(node_id); self.write_error(node_id);
@ -3800,11 +3781,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
} }
let pcx = PatCtxt { self.check_pat(&local.pat, t);
fcx: self,
map: pat_id_map(&local.pat),
};
pcx.check_pat(&local.pat, t);
let pat_ty = self.node_ty(local.pat.id); let pat_ty = self.node_ty(local.pat.id);
if pat_ty.references_error() { if pat_ty.references_error() {
self.write_ty(local.id, pat_ty); self.write_ty(local.id, pat_ty);
@ -4562,7 +4539,7 @@ pub fn may_break(tcx: TyCtxt, id: ast::NodeId, b: &hir::Block) -> bool {
// <id> nested anywhere inside the loop? // <id> nested anywhere inside the loop?
(block_query(b, |e| { (block_query(b, |e| {
if let hir::ExprBreak(Some(_)) = e.node { if let hir::ExprBreak(Some(_)) = e.node {
lookup_full_def(tcx, e.span, e.id) == Def::Label(id) tcx.expect_def(e.id) == Def::Label(id)
} else { } else {
false false
} }

View File

@ -532,17 +532,13 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-> bool -> bool
{ {
if let hir::TyPath(None, _) = ast_ty.node { if let hir::TyPath(None, _) = ast_ty.node {
let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap(); let path_res = tcx.expect_resolution(ast_ty.id);
match path_res.base_def { match path_res.base_def {
Def::SelfTy(Some(def_id), None) => { Def::SelfTy(Some(def_id), None) |
path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id) Def::TyParam(_, _, def_id, _) if path_res.depth == 0 => {
} def_id == tcx.map.local_def_id(param_id)
Def::TyParam(_, _, def_id, _) => {
path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
}
_ => {
false
} }
_ => false
} }
} else { } else {
false false
@ -1719,7 +1715,7 @@ fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
match unbound { match unbound {
Some(ref tpb) => { Some(ref tpb) => {
// FIXME(#8559) currently requires the unbound to be built-in. // FIXME(#8559) currently requires the unbound to be built-in.
let trait_def_id = tcx.trait_ref_to_def_id(tpb); let trait_def_id = tcx.expect_def(tpb.ref_id).def_id();
match kind_id { match kind_id {
Ok(kind_id) if trait_def_id != kind_id => { Ok(kind_id) if trait_def_id != kind_id => {
tcx.sess.span_warn(span, tcx.sess.span_warn(span,

View File

@ -4125,7 +4125,7 @@ register_diagnostics! {
// E0239, // `next` method of `Iterator` trait has unexpected type // E0239, // `next` method of `Iterator` trait has unexpected type
// E0240, // E0240,
// E0241, // E0241,
E0242, // internal error looking up a definition // E0242,
E0245, // not a trait E0245, // not a trait
// E0246, // invalid recursive type // E0246, // invalid recursive type
// E0247, // E0247,

View File

@ -103,7 +103,6 @@ pub use rustc::util;
use dep_graph::DepNode; use dep_graph::DepNode;
use hir::map as hir_map; use hir::map as hir_map;
use hir::def::Def;
use rustc::infer::TypeOrigin; use rustc::infer::TypeOrigin;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
@ -176,15 +175,6 @@ fn write_substs_to_tcx<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
} }
} }
fn lookup_full_def(tcx: TyCtxt, sp: Span, id: ast::NodeId) -> Def {
match tcx.def_map.borrow().get(&id) {
Some(x) => x.full_def(),
None => {
span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
}
}
}
fn require_c_abi_if_variadic(tcx: TyCtxt, fn require_c_abi_if_variadic(tcx: TyCtxt,
decl: &hir::FnDecl, decl: &hir::FnDecl,
abi: Abi, abi: Abi,

View File

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

View File

@ -2631,7 +2631,7 @@ fn resolve_type(cx: &DocContext,
}; };
} }
}; };
let def = tcx.def_map.borrow().get(&id).expect("unresolved id not in defmap").full_def(); let def = tcx.expect_def(id);
debug!("resolve_type: def={:?}", def); debug!("resolve_type: def={:?}", def);
let is_generic = match def { let is_generic = match def {
@ -2700,7 +2700,7 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> { fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
cx.tcx_opt().and_then(|tcx| { cx.tcx_opt().and_then(|tcx| {
tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def())) tcx.expect_def_or_none(id).map(|def| register_def(cx, def))
}) })
} }

View File

@ -241,7 +241,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]; let def = tcx.expect_def(id);
let def_did = def.def_id(); let def_did = def.def_id();
let use_attrs = tcx.map.attrs(id).clean(self.cx); let use_attrs = tcx.map.attrs(id).clean(self.cx);
@ -251,10 +251,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
// reachable in documentation - a previously nonreachable item can be // reachable in documentation - a previously nonreachable item can be
// made reachable by cross-crate inlining which we're checking here. // made reachable by cross-crate inlining which we're checking here.
// (this is done here because we need to know this upfront) // (this is done here because we need to know this upfront)
if !def.def_id().is_local() && !is_no_inline { if !def_did.is_local() && !is_no_inline {
let attrs = clean::inline::load_attrs(self.cx, tcx, def_did); let attrs = clean::inline::load_attrs(self.cx, tcx, def_did);
let self_is_hidden = attrs.list("doc").has_word("hidden"); let self_is_hidden = attrs.list("doc").has_word("hidden");
match def.base_def { match def {
Def::Trait(did) | Def::Trait(did) |
Def::Struct(did) | Def::Struct(did) |
Def::Enum(did) | Def::Enum(did) |

View File

@ -15,6 +15,7 @@ pub use use_from_trait_xc::Trait;
fn main() { fn main() {
match () { match () {
Trait { x: 42 } => () //~ ERROR `Trait` does not name a struct Trait { x: 42 } => () //~ ERROR expected variant, struct or type alias, found trait `Trait`
//~^ ERROR `Trait` does not name a struct or a struct variant
} }
} }

View File

@ -23,5 +23,5 @@ mod bar1 {
fn main() { fn main() {
assert_eq!(1, bar1::Foo::ID); assert_eq!(1, bar1::Foo::ID);
//~^ERROR associated const `ID` is private //~^ERROR associated constant `ID` is private
} }

View File

@ -12,6 +12,6 @@ mod foo { pub struct bar; }
fn main() { fn main() {
let bar = 5; let bar = 5;
//~^ ERROR cannot be named the same //~^ ERROR let bindings cannot shadow structs
use foo::bar; use foo::bar;
} }

View File

@ -19,10 +19,10 @@ use foo::d; //~ NOTE is imported here
const a: u8 = 2; //~ NOTE is defined here const a: u8 = 2; //~ NOTE is defined here
fn main() { fn main() {
let a = 4; //~ ERROR let variables cannot let a = 4; //~ ERROR let bindings cannot shadow constants
//~^ NOTE cannot be named the same as a const variable //~^ NOTE cannot be named the same as a constant
let c = 4; //~ ERROR let variables cannot let c = 4; //~ ERROR let bindings cannot shadow constants
//~^ NOTE cannot be named the same as a const variable //~^ NOTE cannot be named the same as a constant
let d = 4; //~ ERROR let variables cannot let d = 4; //~ ERROR let bindings cannot shadow constants
//~^ NOTE cannot be named the same as a const variable //~^ NOTE cannot be named the same as a constant
} }

View File

@ -29,9 +29,9 @@ fn main() {
// XEmpty1() => () // ERROR unresolved enum variant, struct or const `XEmpty1` // XEmpty1() => () // ERROR unresolved enum variant, struct or const `XEmpty1`
// } // }
match e1 { match e1 {
Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1` Empty1(..) => () //~ ERROR unresolved variant or struct `Empty1`
} }
match xe1 { match xe1 {
XEmpty1(..) => () //~ ERROR unresolved enum variant, struct or const `XEmpty1` XEmpty1(..) => () //~ ERROR unresolved variant or struct `XEmpty1`
} }
} }

View File

@ -11,5 +11,5 @@
struct hello(isize); struct hello(isize);
fn main() { fn main() {
let hello = 0; //~ERROR cannot be named the same let hello = 0; //~ERROR let bindings cannot shadow structs
} }

View File

@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
//error-pattern:unresolved enum variant
fn main() { fn main() {
// a bug in the parser is allowing this: let a(1) = 13; //~ ERROR unresolved variant or struct `a`
let a(1) = 13;
} }

View File

@ -13,7 +13,7 @@ fn foo(_: usize) -> Foo { Foo(false) }
fn main() { fn main() {
match Foo(true) { match Foo(true) {
foo(x) //~ ERROR `foo` is not an enum variant, struct or const foo(x) //~ ERROR expected variant or struct, found function `foo`
=> () => ()
} }
} }

View File

@ -12,6 +12,6 @@ mod foo { pub fn bar() {} }
fn main() { fn main() {
match () { match () {
foo::bar => {} //~ ERROR `bar` is not an enum variant, struct or const foo::bar => {} //~ ERROR expected variant, struct or constant, found function `bar`
} }
} }

View File

@ -15,7 +15,7 @@ extern {
fn main() { fn main() {
let boolValue = match 42 { let boolValue = match 42 {
externalValue => true, externalValue => true,
//~^ ERROR static variables cannot be referenced in a pattern //~^ ERROR match bindings cannot shadow statics
_ => false _ => false
}; };
} }

View File

@ -14,6 +14,7 @@ enum Foo {
fn main() { fn main() {
match Foo::Bar(1) { match Foo::Bar(1) {
Foo { i } => () //~ ERROR `Foo` does not name a struct or a struct variant Foo { i } => () //~ ERROR expected variant, struct or type alias, found enum `Foo`
//~^ ERROR `Foo` does not name a struct or a struct variant
} }
} }

View File

@ -12,10 +12,10 @@
extern crate issue_17718_const_privacy as other; extern crate issue_17718_const_privacy as other;
use a::B; //~ ERROR: const `B` is private use a::B; //~ ERROR: constant `B` is private
use other::{ use other::{
FOO, FOO,
BAR, //~ ERROR: const `BAR` is private BAR, //~ ERROR: constant `BAR` is private
FOO2, FOO2,
}; };

View File

@ -14,8 +14,8 @@ const A3: usize = 1;
fn main() { fn main() {
match 1 { match 1 {
A1 => {} //~ ERROR: static variables cannot be referenced in a pattern A1 => {} //~ ERROR: match bindings cannot shadow statics
A2 => {} //~ ERROR: static variables cannot be referenced in a pattern A2 => {} //~ ERROR: match bindings cannot shadow statics
A3 => {} A3 => {}
_ => {} _ => {}
} }

View File

@ -13,7 +13,7 @@ pub static X: usize = 1;
fn main() { fn main() {
match 1 { match 1 {
self::X => { }, self::X => { },
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead //~^ ERROR expected variant, struct or constant, found static `X`
_ => { }, _ => { },
} }
} }

View File

@ -9,21 +9,21 @@
// except according to those terms. // except according to those terms.
static foo: i32 = 0; static foo: i32 = 0;
//~^ NOTE static variable defined here //~^ NOTE a static `foo` is defined here
fn bar(foo: i32) {} fn bar(foo: i32) {}
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead //~^ ERROR function parameters cannot shadow statics
//~| static variable used in pattern //~| cannot be named the same as a static
mod submod { mod submod {
pub static answer: i32 = 42; pub static answer: i32 = 42;
} }
use self::submod::answer; use self::submod::answer;
//~^ NOTE static variable imported here //~^ NOTE a static `answer` is imported here
fn question(answer: i32) {} fn question(answer: i32) {}
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead //~^ ERROR function parameters cannot shadow statics
//~| static variable used in pattern //~| cannot be named the same as a static
fn main() { fn main() {
} }

View File

@ -11,6 +11,7 @@
fn main() { fn main() {
match 'a' { match 'a' {
char{ch} => true char{ch} => true
//~^ ERROR `char` does not name a struct or a struct variant //~^ ERROR expected variant, struct or type alias, found builtin type `char`
//~| ERROR `char` does not name a struct or a struct variant
}; };
} }

View File

@ -10,11 +10,11 @@
fn main() { fn main() {
match Some(1) { match Some(1) {
None @ _ => {} //~ ERROR cannot be named the same None @ _ => {} //~ ERROR match bindings cannot shadow variants
}; };
const C: u8 = 1; const C: u8 = 1;
match 1 { match 1 {
C @ 2 => { //~ ERROR cannot be named the same C @ 2 => { //~ ERROR match bindings cannot shadow constant
println!("{}", C); println!("{}", C);
} }
_ => {} _ => {}

View File

@ -14,7 +14,9 @@ fn main() {
let u = A { x: 1 }; //~ ERROR `A` does not name a structure let u = A { x: 1 }; //~ ERROR `A` does not name a structure
let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure let v = u32 { x: 1 }; //~ ERROR `u32` does not name a structure
match () { match () {
A { x: 1 } => {} //~ ERROR `A` does not name a struct A { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found module `A`
u32 { x: 1 } => {} //~ ERROR `u32` does not name a struct //~^ ERROR `A` does not name a struct or a struct variant
u32 { x: 1 } => {} //~ ERROR expected variant, struct or type alias, found builtin type `u32
//~^ ERROR `u32` does not name a struct or a struct variant
} }
} }

View File

@ -21,6 +21,6 @@ impl S {
} }
fn main() { fn main() {
if let C1(..) = 0 {} //~ ERROR `C1` does not name a tuple variant or a tuple struct if let C1(..) = 0 {} //~ ERROR expected variant or struct, found constant `C1`
if let S::C2(..) = 0 {} //~ ERROR `S::C2` does not name a tuple variant or a tuple struct if let S::C2(..) = 0 {} //~ ERROR `S::C2` does not name a tuple variant or a tuple struct
} }

View File

@ -0,0 +1,17 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// 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.
struct S(u8);
const C: S = S(10);
fn main() {
let C(a) = S(11); //~ ERROR expected variant or struct, found constant `C`
let C(..) = S(11); //~ ERROR expected variant or struct, found constant `C`
}

View File

@ -0,0 +1,19 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// 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.
const C: u8 = 0; //~ NOTE a constant `C` is defined here
fn main() {
match 1u8 {
mut C => {} //~ ERROR match bindings cannot shadow constants
//~^ NOTE cannot be named the same as a constant
_ => {}
}
}

View File

@ -11,7 +11,7 @@
fn main() { fn main() {
let z = match 3 { let z = match 3 {
x(1) => x(1) //~ ERROR unresolved enum variant x(1) => x(1) //~ ERROR unresolved variant or struct `x`
//~^ ERROR unresolved name `x` //~^ ERROR unresolved name `x`
}; };
assert!(z == 3); assert!(z == 3);

View File

@ -19,6 +19,6 @@ impl MyTrait for Foo {}
fn main() { fn main() {
match 0u32 { match 0u32 {
<Foo as MyTrait>::trait_bar => {} <Foo as MyTrait>::trait_bar => {}
//~^ ERROR `trait_bar` is not an associated const //~^ ERROR expected associated constant, found method `trait_bar`
} }
} }

View File

@ -8,10 +8,11 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// error-pattern:cannot be named the same
use std::option::*; use std::option::*;
fn main() { fn main() {
let None: isize = 42; let None: isize = 42; //~ ERROR let bindings cannot shadow variants
log(debug, None); log(debug, None);
//~^ ERROR unresolved name `debug`
//~| ERROR unresolved name `log`
} }

View File

@ -11,5 +11,5 @@
struct foo(usize); struct foo(usize);
fn main() { fn main() {
let (foo, _) = (2, 3); //~ ERROR `foo` cannot be named the same as let (foo, _) = (2, 3); //~ ERROR let bindings cannot shadow structs
} }

View File

@ -27,7 +27,7 @@ impl S {
fn main() { fn main() {
match 10 { match 10 {
<S as Tr>::A::f::<u8> => {} //~ ERROR `f` is not an associated const <S as Tr>::A::f::<u8> => {} //~ ERROR associated items in match patterns must be constants
0 ... <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range 0 ... <S as Tr>::A::f::<u8> => {} //~ ERROR only char and numeric types are allowed in range
} }
} }

View File

@ -20,7 +20,7 @@ fn main() {
// instead of spitting out a custom error about some identifier collisions // instead of spitting out a custom error about some identifier collisions
// (we should allow shadowing) // (we should allow shadowing)
match 4 { match 4 {
a => {} //~ ERROR static variables cannot be referenced in a pattern a => {} //~ ERROR match bindings cannot shadow statics
_ => {} _ => {}
} }
} }
@ -44,7 +44,7 @@ fn mutable_statics() {
match (Foo { bar: Some(Direction::North), baz: NewBool(true) }) { match (Foo { bar: Some(Direction::North), baz: NewBool(true) }) {
Foo { bar: None, baz: NewBool(true) } => (), Foo { bar: None, baz: NewBool(true) } => (),
STATIC_MUT_FOO => (), STATIC_MUT_FOO => (),
//~^ ERROR static variables cannot be referenced in a pattern //~^ ERROR match bindings cannot shadow statics
Foo { bar: Some(Direction::South), .. } => (), Foo { bar: Some(Direction::South), .. } => (),
Foo { bar: Some(EAST), .. } => (), Foo { bar: Some(EAST), .. } => (),
Foo { bar: Some(Direction::North), baz: NewBool(true) } => (), Foo { bar: Some(Direction::North), baz: NewBool(true) } => (),

View File

@ -14,7 +14,7 @@ mod a {
trait A { trait A {
} }
impl A for a { //~ ERROR type name `a` is undefined or not in scope impl A for a { //~ ERROR expected type, found module
} }
fn main() { fn main() {

View File

@ -0,0 +1,18 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// 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.
// Make sure several unnamed function arguments don't conflict with each other
trait Tr {
fn f(u8, u8) {}
}
fn main() {
}