Simplify PatIdent to contain an Ident rather than a Path

Rationale: for what appear to be historical reasons only, the PatIdent contains
a Path rather than an Ident.  This means that there are many places in the code
where an ident is artificially promoted to a path, and---much more problematically---
a bunch of elements from a path are simply thrown away, which seems like an invitation
to some really nasty bugs.

This commit replaces the Path in a PatIdent with a SpannedIdent, which just contains an ident
and a span.
This commit is contained in:
John Clements 2014-06-30 18:02:14 -07:00 committed by Alex Crichton
parent cff79ab563
commit e38cb972dc
26 changed files with 153 additions and 255 deletions

View File

@ -902,12 +902,10 @@ impl LintPass for NonUppercasePatternStatics {
fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
// Lint for constants that look like binding identifiers (#7526) // Lint for constants that look like binding identifiers (#7526)
match (&p.node, cx.tcx.def_map.borrow().find(&p.id)) { match (&p.node, cx.tcx.def_map.borrow().find(&p.id)) {
(&ast::PatIdent(_, ref path, _), Some(&def::DefStatic(_, false))) => { (&ast::PatIdent(_, ref path1, _), Some(&def::DefStatic(_, false))) => {
// last identifier alone is right choice for this lint. let s = token::get_ident(path1.node);
let ident = path.segments.last().unwrap().identifier;
let s = token::get_ident(ident);
if s.get().chars().any(|c| c.is_lowercase()) { if s.get().chars().any(|c| c.is_lowercase()) {
cx.span_lint(NON_UPPERCASE_PATTERN_STATICS, path.span, cx.span_lint(NON_UPPERCASE_PATTERN_STATICS, path1.span,
format!("static constant in pattern `{}` should have an uppercase \ format!("static constant in pattern `{}` should have an uppercase \
name such as `{}`", name such as `{}`",
s.get(), s.get().chars().map(|c| c.to_uppercase()) s.get(), s.get().chars().map(|c| c.to_uppercase())
@ -931,15 +929,13 @@ impl LintPass for UppercaseVariables {
fn check_pat(&mut self, cx: &Context, p: &ast::Pat) { fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
match &p.node { match &p.node {
&ast::PatIdent(_, ref path, _) => { &ast::PatIdent(_, ref path1, _) => {
match cx.tcx.def_map.borrow().find(&p.id) { match cx.tcx.def_map.borrow().find(&p.id) {
Some(&def::DefLocal(_, _)) | Some(&def::DefBinding(_, _)) | Some(&def::DefLocal(_, _)) | Some(&def::DefBinding(_, _)) |
Some(&def::DefArg(_, _)) => { Some(&def::DefArg(_, _)) => {
// last identifier alone is right choice for this lint. let s = token::get_ident(path1.node);
let ident = path.segments.last().unwrap().identifier;
let s = token::get_ident(ident);
if s.get().len() > 0 && s.get().char_at(0).is_uppercase() { if s.get().len() > 0 && s.get().char_at(0).is_uppercase() {
cx.span_lint(UPPERCASE_VARIABLES, path.span, cx.span_lint(UPPERCASE_VARIABLES, path1.span,
"variable names should start with \ "variable names should start with \
a lowercase character"); a lowercase character");
} }
@ -1113,15 +1109,10 @@ impl UnusedMut {
// avoid false warnings in match arms with multiple patterns // avoid false warnings in match arms with multiple patterns
let mut mutables = HashMap::new(); let mut mutables = HashMap::new();
for &p in pats.iter() { for &p in pats.iter() {
pat_util::pat_bindings(&cx.tcx.def_map, &*p, |mode, id, _, path| { pat_util::pat_bindings(&cx.tcx.def_map, &*p, |mode, id, _, path1| {
let ident = path1.node;
match mode { match mode {
ast::BindByValue(ast::MutMutable) => { ast::BindByValue(ast::MutMutable) => {
if path.segments.len() != 1 {
cx.sess().span_bug(p.span,
"mutable binding that doesn't consist \
of exactly one segment");
}
let ident = path.segments.get(0).identifier;
if !token::get_ident(ident).get().starts_with("_") { if !token::get_ident(ident).get().starts_with("_") {
mutables.insert_or_update_with(ident.name as uint, mutables.insert_or_update_with(ident.name as uint,
vec!(id), |_, old| { old.push(id); }); vec!(id), |_, old| { old.push(id); });

View File

@ -809,9 +809,8 @@ fn encode_method_argument_names(ebml_w: &mut Encoder,
for arg in decl.inputs.iter() { for arg in decl.inputs.iter() {
ebml_w.start_tag(tag_method_argument_name); ebml_w.start_tag(tag_method_argument_name);
match arg.pat.node { match arg.pat.node {
ast::PatIdent(_, ref name, _) => { ast::PatIdent(_, ref path1, _) => {
let name = name.segments.last().unwrap().identifier; let name = token::get_ident(path1.node);
let name = token::get_ident(name);
ebml_w.writer.write(name.get().as_bytes()); ebml_w.writer.write(name.get().as_bytes());
} }
_ => {} _ => {}
@ -1106,8 +1105,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
match ty.node { match ty.node {
ast::TyPath(ref path, ref bounds, _) if path.segments ast::TyPath(ref path, ref bounds, _) if path.segments
.len() == 1 => { .len() == 1 => {
let ident = path.segments.last().unwrap().identifier;
assert!(bounds.is_none()); assert!(bounds.is_none());
encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path)); encode_impl_type_basename(ebml_w, ident);
} }
_ => {} _ => {}
} }

View File

@ -66,9 +66,9 @@ pub fn gather_move_from_pat(bccx: &BorrowckCtxt,
move_pat: &ast::Pat, move_pat: &ast::Pat,
cmt: mc::cmt) { cmt: mc::cmt) {
let pat_span_path_opt = match move_pat.node { let pat_span_path_opt = match move_pat.node {
ast::PatIdent(_, ref path, _) => { ast::PatIdent(_, ref path1, _) => {
Some(MoveSpanAndPath::with_span_and_path(move_pat.span, Some(MoveSpanAndPath{span: move_pat.span,
(*path).clone())) ident: path1.node})
}, },
_ => None, _ => None,
}; };

View File

@ -56,19 +56,8 @@ impl MoveError {
#[deriving(Clone)] #[deriving(Clone)]
pub struct MoveSpanAndPath { pub struct MoveSpanAndPath {
span: codemap::Span, pub span: codemap::Span,
path: ast::Path pub ident: ast::Ident
}
impl MoveSpanAndPath {
pub fn with_span_and_path(span: codemap::Span,
path: ast::Path)
-> MoveSpanAndPath {
MoveSpanAndPath {
span: span,
path: path,
}
}
} }
pub struct GroupedMoveErrors { pub struct GroupedMoveErrors {
@ -83,7 +72,7 @@ fn report_move_errors(bccx: &BorrowckCtxt, errors: &Vec<MoveError>) {
let mut is_first_note = true; let mut is_first_note = true;
for move_to in error.move_to_places.iter() { for move_to in error.move_to_places.iter() {
note_move_destination(bccx, move_to.span, note_move_destination(bccx, move_to.span,
&move_to.path, is_first_note); &move_to.ident, is_first_note);
is_first_note = false; is_first_note = false;
} }
} }
@ -154,9 +143,9 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
fn note_move_destination(bccx: &BorrowckCtxt, fn note_move_destination(bccx: &BorrowckCtxt,
move_to_span: codemap::Span, move_to_span: codemap::Span,
pat_ident_path: &ast::Path, pat_ident: &ast::Ident,
is_first_note: bool) { is_first_note: bool) {
let pat_name = pprust::path_to_str(pat_ident_path); let pat_name = pprust::ident_to_str(pat_ident);
if is_first_note { if is_first_note {
bccx.span_note( bccx.span_note(
move_to_span, move_to_span,

View File

@ -247,6 +247,10 @@ impl<'a> Visitor<MarkSymbolVisitorContext> for MarkSymbolVisitor<'a> {
ast::PatStruct(_, ref fields, _) => { ast::PatStruct(_, ref fields, _) => {
self.handle_field_pattern_match(pat, fields.as_slice()); self.handle_field_pattern_match(pat, fields.as_slice());
} }
ast::PatIdent(_, _, _) => {
// it might be the only use of a static:
self.lookup_and_handle_definition(&pat.id)
}
_ => () _ => ()
} }

View File

@ -20,7 +20,7 @@ use util::ppaux::UserString;
use syntax::ast::*; use syntax::ast::*;
use syntax::attr; use syntax::attr;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::print::pprust::{expr_to_str,path_to_str}; use syntax::print::pprust::{expr_to_str, ident_to_str};
use syntax::{visit}; use syntax::{visit};
use syntax::visit::Visitor; use syntax::visit::Visitor;
@ -627,7 +627,7 @@ fn check_sized(tcx: &ty::ctxt, ty: ty::t, name: String, sp: Span) {
fn check_pat(cx: &mut Context, pat: &Pat) { fn check_pat(cx: &mut Context, pat: &Pat) {
let var_name = match pat.node { let var_name = match pat.node {
PatWild => Some("_".to_string()), PatWild => Some("_".to_string()),
PatIdent(_, ref path, _) => Some(path_to_str(path).to_string()), PatIdent(_, ref path1, _) => Some(ident_to_str(&path1.node).to_string()),
_ => None _ => None
}; };

View File

@ -367,9 +367,9 @@ fn visit_fn(ir: &mut IrMaps,
for arg in decl.inputs.iter() { for arg in decl.inputs.iter() {
pat_util::pat_bindings(&ir.tcx.def_map, pat_util::pat_bindings(&ir.tcx.def_map,
&*arg.pat, &*arg.pat,
|_bm, arg_id, _x, path| { |_bm, arg_id, _x, path1| {
debug!("adding argument {}", arg_id); debug!("adding argument {}", arg_id);
let ident = ast_util::path_to_ident(path); let ident = path1.node;
fn_maps.add_variable(Arg(arg_id, ident)); fn_maps.add_variable(Arg(arg_id, ident));
}) })
}; };
@ -399,9 +399,9 @@ fn visit_fn(ir: &mut IrMaps,
} }
fn visit_local(ir: &mut IrMaps, local: &Local) { fn visit_local(ir: &mut IrMaps, local: &Local) {
pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path| { pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path1| {
debug!("adding local variable {}", p_id); debug!("adding local variable {}", p_id);
let name = ast_util::path_to_ident(path); let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp)); ir.add_live_node_for_node(p_id, VarDefNode(sp));
ir.add_variable(Local(LocalInfo { ir.add_variable(Local(LocalInfo {
id: p_id, id: p_id,
@ -413,10 +413,10 @@ fn visit_local(ir: &mut IrMaps, local: &Local) {
fn visit_arm(ir: &mut IrMaps, arm: &Arm) { fn visit_arm(ir: &mut IrMaps, arm: &Arm) {
for pat in arm.pats.iter() { for pat in arm.pats.iter() {
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path| { pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
debug!("adding local variable {} from match with bm {:?}", debug!("adding local variable {} from match with bm {:?}",
p_id, bm); p_id, bm);
let name = ast_util::path_to_ident(path); let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp)); ir.add_live_node_for_node(p_id, VarDefNode(sp));
ir.add_variable(Local(LocalInfo { ir.add_variable(Local(LocalInfo {
id: p_id, id: p_id,
@ -1522,10 +1522,10 @@ impl<'a> Liveness<'a> {
for arg in decl.inputs.iter() { for arg in decl.inputs.iter() {
pat_util::pat_bindings(&self.ir.tcx.def_map, pat_util::pat_bindings(&self.ir.tcx.def_map,
&*arg.pat, &*arg.pat,
|_bm, p_id, sp, path| { |_bm, p_id, sp, path1| {
let var = self.variable(p_id, sp); let var = self.variable(p_id, sp);
// Ignore unused self. // Ignore unused self.
let ident = ast_util::path_to_ident(path); let ident = path1.node;
if ident.name != special_idents::self_.name { if ident.name != special_idents::self_.name {
self.warn_about_unused(sp, p_id, entry_ln, var); self.warn_about_unused(sp, p_id, entry_ln, var);
} }

View File

@ -14,7 +14,7 @@ use middle::resolve;
use std::collections::HashMap; use std::collections::HashMap;
use std::gc::{Gc, GC}; use std::gc::{Gc, GC};
use syntax::ast::*; use syntax::ast::*;
use syntax::ast_util::{path_to_ident, walk_pat}; use syntax::ast_util::{walk_pat};
use syntax::codemap::{Span, DUMMY_SP}; use syntax::codemap::{Span, DUMMY_SP};
pub type PatIdMap = HashMap<Ident, NodeId>; pub type PatIdMap = HashMap<Ident, NodeId>;
@ -23,8 +23,8 @@ pub type PatIdMap = HashMap<Ident, NodeId>;
// use the NodeId of their namesake in the first pattern. // use the NodeId of their namesake in the first pattern.
pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap { pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap {
let mut map = HashMap::new(); let mut map = HashMap::new();
pat_bindings(dm, pat, |_bm, p_id, _s, n| { pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
map.insert(path_to_ident(n), p_id); map.insert(path1.node, p_id);
}); });
map map
} }
@ -75,7 +75,7 @@ pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &Pat) -> bool {
/// `match foo() { Some(a) => (), None => () }` /// `match foo() { Some(a) => (), None => () }`
pub fn pat_bindings(dm: &resolve::DefMap, pub fn pat_bindings(dm: &resolve::DefMap,
pat: &Pat, pat: &Pat,
it: |BindingMode, NodeId, Span, &Path|) { it: |BindingMode, NodeId, Span, &SpannedIdent|) {
walk_pat(pat, |p| { walk_pat(pat, |p| {
match p.node { match p.node {
PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => { PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
@ -102,10 +102,10 @@ pub fn pat_contains_bindings(dm: &resolve::DefMap, pat: &Pat) -> bool {
contains_bindings contains_bindings
} }
pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> { pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Ident> {
match pat.node { match pat.node {
PatIdent(BindByValue(_), ref path, None) => { PatIdent(BindByValue(_), ref path1, None) => {
Some(path) Some(&path1.node)
} }
_ => { _ => {
None None

View File

@ -23,11 +23,10 @@ use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
use syntax::ast::*; use syntax::ast::*;
use syntax::ast; use syntax::ast;
use syntax::ast_util::{local_def}; use syntax::ast_util::{local_def};
use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method}; use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
use syntax::ext::mtwt; use syntax::ext::mtwt;
use syntax::parse::token::special_idents; use syntax::parse::token::special_idents;
use syntax::parse::token; use syntax::parse::token;
use syntax::print::pprust::path_to_str;
use syntax::codemap::{Span, DUMMY_SP, Pos}; use syntax::codemap::{Span, DUMMY_SP, Pos};
use syntax::owned_slice::OwnedSlice; use syntax::owned_slice::OwnedSlice;
use syntax::visit; use syntax::visit;
@ -1247,7 +1246,7 @@ impl<'a> Resolver<'a> {
// Create the module and add all methods. // Create the module and add all methods.
match ty.node { match ty.node {
TyPath(ref path, _, _) if path.segments.len() == 1 => { TyPath(ref path, _, _) if path.segments.len() == 1 => {
let name = path_to_ident(path); let name = path.segments.last().unwrap().identifier;
let parent_opt = parent.module().children.borrow() let parent_opt = parent.module().children.borrow()
.find_copy(&name.name); .find_copy(&name.name);
@ -4104,8 +4103,8 @@ impl<'a> Resolver<'a> {
// user and one 'x' came from the macro. // user and one 'x' came from the macro.
fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
let mut result = HashMap::new(); let mut result = HashMap::new();
pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path| { pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
let name = mtwt::resolve(path_to_ident(path)); let name = mtwt::resolve(path1.node);
result.insert(name, result.insert(name,
binding_info {span: sp, binding_info {span: sp,
binding_mode: binding_mode}); binding_mode: binding_mode});
@ -4314,8 +4313,7 @@ impl<'a> Resolver<'a> {
let pat_id = pattern.id; let pat_id = pattern.id;
walk_pat(pattern, |pattern| { walk_pat(pattern, |pattern| {
match pattern.node { match pattern.node {
PatIdent(binding_mode, ref path, _) PatIdent(binding_mode, ref path1, _) => {
if !path.global && path.segments.len() == 1 => {
// The meaning of pat_ident with no type parameters // The meaning of pat_ident with no type parameters
// depends on whether an enum variant or unit-like struct // depends on whether an enum variant or unit-like struct
@ -4326,7 +4324,7 @@ impl<'a> Resolver<'a> {
// such a value is simply disallowed (since it's rarely // such a value is simply disallowed (since it's rarely
// what you want). // what you want).
let ident = path.segments.get(0).identifier; let ident = path1.node;
let renamed = mtwt::resolve(ident); let renamed = mtwt::resolve(ident);
match self.resolve_bare_identifier_pattern(ident) { match self.resolve_bare_identifier_pattern(ident) {
@ -4416,57 +4414,12 @@ impl<'a> Resolver<'a> {
format!("identifier `{}` is bound \ format!("identifier `{}` is bound \
more than once in the same \ more than once in the same \
pattern", pattern",
path_to_str(path)).as_slice()); token::get_ident(ident)).as_slice());
} }
// Else, not bound in the same pattern: do // Else, not bound in the same pattern: do
// nothing. // nothing.
} }
} }
// Check the types in the path pattern.
for ty in path.segments
.iter()
.flat_map(|seg| seg.types.iter()) {
self.resolve_type(&**ty);
}
}
PatIdent(binding_mode, ref path, _) => {
// This must be an enum variant, struct, or constant.
match self.resolve_path(pat_id, path, ValueNS, false) {
Some(def @ (DefVariant(..), _)) |
Some(def @ (DefStruct(..), _)) => {
self.record_def(pattern.id, def);
}
Some(def @ (DefStatic(..), _)) => {
self.enforce_default_binding_mode(
pattern,
binding_mode,
"a constant");
self.record_def(pattern.id, def);
}
Some(_) => {
self.resolve_error(
path.span,
format!("`{}` is not an enum variant or constant",
token::get_ident(
path.segments
.last()
.unwrap()
.identifier)).as_slice())
}
None => {
self.resolve_error(path.span,
"unresolved enum variant");
}
}
// Check the types in the path pattern.
for ty in path.segments
.iter()
.flat_map(|s| s.types.iter()) {
self.resolve_type(&**ty);
}
} }
PatEnum(ref path, _) => { PatEnum(ref path, _) => {
@ -5202,8 +5155,8 @@ impl<'a> Resolver<'a> {
in a static method. Maybe a \ in a static method. Maybe a \
`self` argument is missing?"); `self` argument is missing?");
} else { } else {
let name = path_to_ident(path).name; let last_name = path.segments.last().unwrap().identifier.name;
let mut msg = match self.find_fallback_in_self_type(name) { let mut msg = match self.find_fallback_in_self_type(last_name) {
NoSuggestion => { NoSuggestion => {
// limit search to 5 to reduce the number // limit search to 5 to reduce the number
// of stupid suggestions // of stupid suggestions

View File

@ -926,7 +926,7 @@ impl <'l> DxrVisitor<'l> {
self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef)); self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef));
visit::walk_pat(self, p, e); visit::walk_pat(self, p, e);
} }
ast::PatIdent(bm, ref path, ref optional_subpattern) => { ast::PatIdent(bm, ref path1, ref optional_subpattern) => {
let immut = match bm { let immut = match bm {
// Even if the ref is mut, you can't change the ref, only // Even if the ref is mut, you can't change the ref, only
// the data pointed at, so showing the initialising expression // the data pointed at, so showing the initialising expression
@ -940,7 +940,8 @@ impl <'l> DxrVisitor<'l> {
} }
}; };
// collect path for either visit_local or visit_arm // collect path for either visit_local or visit_arm
self.collected_paths.push((p.id, path.clone(), immut, recorder::VarRef)); let path = ast_util::ident_to_path(path1.span,path1.node);
self.collected_paths.push((p.id, path, immut, recorder::VarRef));
match *optional_subpattern { match *optional_subpattern {
None => {} None => {}
Some(subpattern) => self.visit_pat(&*subpattern, e), Some(subpattern) => self.visit_pat(&*subpattern, e),

View File

@ -231,8 +231,6 @@ use std::rc::Rc;
use std::gc::{Gc}; use std::gc::{Gc};
use syntax::ast; use syntax::ast;
use syntax::ast::Ident; use syntax::ast::Ident;
use syntax::ast_util::path_to_ident;
use syntax::ast_util;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
@ -435,13 +433,13 @@ fn expand_nested_bindings<'a, 'b>(
m.iter().map(|br| { m.iter().map(|br| {
match br.pats.get(col).node { match br.pats.get(col).node {
ast::PatIdent(_, ref path, Some(inner)) => { ast::PatIdent(_, ref path1, Some(inner)) => {
let pats = Vec::from_slice(br.pats.slice(0u, col)) let pats = Vec::from_slice(br.pats.slice(0u, col))
.append((vec!(inner)) .append((vec!(inner))
.append(br.pats.slice(col + 1u, br.pats.len())).as_slice()); .append(br.pats.slice(col + 1u, br.pats.len())).as_slice());
let mut bound_ptrs = br.bound_ptrs.clone(); let mut bound_ptrs = br.bound_ptrs.clone();
bound_ptrs.push((path_to_ident(path), val)); bound_ptrs.push((path1.node, val));
Match { Match {
pats: pats, pats: pats,
data: &*br.data, data: &*br.data,
@ -479,9 +477,9 @@ fn enter_match<'a, 'b>(
let this = *br.pats.get(col); let this = *br.pats.get(col);
let mut bound_ptrs = br.bound_ptrs.clone(); let mut bound_ptrs = br.bound_ptrs.clone();
match this.node { match this.node {
ast::PatIdent(_, ref path, None) => { ast::PatIdent(_, ref path1, None) => {
if pat_is_binding(dm, &*this) { if pat_is_binding(dm, &*this) {
bound_ptrs.push((path_to_ident(path), val)); bound_ptrs.push((path1.node, val));
} }
} }
_ => {} _ => {}
@ -1431,8 +1429,8 @@ fn create_bindings_map(bcx: &Block, pat: Gc<ast::Pat>) -> BindingsMap {
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let tcx = bcx.tcx(); let tcx = bcx.tcx();
let mut bindings_map = HashMap::new(); let mut bindings_map = HashMap::new();
pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path| { pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
let ident = path_to_ident(path); let ident = path1.node;
let variable_ty = node_id_type(bcx, p_id); let variable_ty = node_id_type(bcx, p_id);
let llvariable_ty = type_of::type_of(ccx, variable_ty); let llvariable_ty = type_of::type_of(ccx, variable_ty);
@ -1586,10 +1584,10 @@ pub fn store_local<'a>(bcx: &'a Block<'a>,
// In such cases, the more general path is unsafe, because // In such cases, the more general path is unsafe, because
// it assumes it is matching against a valid value. // it assumes it is matching against a valid value.
match simple_identifier(&*pat) { match simple_identifier(&*pat) {
Some(path) => { Some(ident) => {
let var_scope = cleanup::var_scope(tcx, local.id); let var_scope = cleanup::var_scope(tcx, local.id);
return mk_binding_alloca( return mk_binding_alloca(
bcx, pat.id, path, BindLocal, var_scope, (), bcx, pat.id, ident, BindLocal, var_scope, (),
|(), bcx, v, _| expr::trans_into(bcx, &*init_expr, |(), bcx, v, _| expr::trans_into(bcx, &*init_expr,
expr::SaveIn(v))); expr::SaveIn(v)));
} }
@ -1621,10 +1619,10 @@ pub fn store_local<'a>(bcx: &'a Block<'a>,
// create dummy memory for the variables if we have no // create dummy memory for the variables if we have no
// value to store into them immediately // value to store into them immediately
let tcx = bcx.tcx(); let tcx = bcx.tcx();
pat_bindings(&tcx.def_map, &*pat, |_, p_id, _, path| { pat_bindings(&tcx.def_map, &*pat, |_, p_id, _, path1| {
let scope = cleanup::var_scope(tcx, p_id); let scope = cleanup::var_scope(tcx, p_id);
bcx = mk_binding_alloca( bcx = mk_binding_alloca(
bcx, p_id, path, BindLocal, scope, (), bcx, p_id, &path1.node, BindLocal, scope, (),
|(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx }); |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx });
}); });
bcx bcx
@ -1652,7 +1650,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
let _icx = push_ctxt("match::store_arg"); let _icx = push_ctxt("match::store_arg");
match simple_identifier(&*pat) { match simple_identifier(&*pat) {
Some(path) => { Some(ident) => {
// Generate nicer LLVM for the common case of fn a pattern // Generate nicer LLVM for the common case of fn a pattern
// like `x: T` // like `x: T`
let arg_ty = node_id_type(bcx, pat.id); let arg_ty = node_id_type(bcx, pat.id);
@ -1667,7 +1665,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
bcx bcx
} else { } else {
mk_binding_alloca( mk_binding_alloca(
bcx, pat.id, path, BindArgument, arg_scope, arg, bcx, pat.id, ident, BindArgument, arg_scope, arg,
|arg, bcx, llval, _| arg.store_to(bcx, llval)) |arg, bcx, llval, _| arg.store_to(bcx, llval))
} }
} }
@ -1685,17 +1683,16 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
fn mk_binding_alloca<'a,A>(bcx: &'a Block<'a>, fn mk_binding_alloca<'a,A>(bcx: &'a Block<'a>,
p_id: ast::NodeId, p_id: ast::NodeId,
path: &ast::Path, ident: &ast::Ident,
binding_mode: IrrefutablePatternBindingMode, binding_mode: IrrefutablePatternBindingMode,
cleanup_scope: cleanup::ScopeId, cleanup_scope: cleanup::ScopeId,
arg: A, arg: A,
populate: |A, &'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>) populate: |A, &'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>)
-> &'a Block<'a> { -> &'a Block<'a> {
let var_ty = node_id_type(bcx, p_id); let var_ty = node_id_type(bcx, p_id);
let ident = ast_util::path_to_ident(path);
// Allocate memory on stack for the binding. // Allocate memory on stack for the binding.
let llval = alloc_ty(bcx, var_ty, bcx.ident(ident).as_slice()); let llval = alloc_ty(bcx, var_ty, bcx.ident(*ident).as_slice());
// Subtle: be sure that we *populate* the memory *before* // Subtle: be sure that we *populate* the memory *before*
// we schedule the cleanup. // we schedule the cleanup.
@ -1753,13 +1750,13 @@ fn bind_irrefutable_pat<'a>(
let tcx = bcx.tcx(); let tcx = bcx.tcx();
let ccx = bcx.ccx(); let ccx = bcx.ccx();
match pat.node { match pat.node {
ast::PatIdent(pat_binding_mode, ref path, inner) => { ast::PatIdent(pat_binding_mode, ref path1, inner) => {
if pat_is_binding(&tcx.def_map, &*pat) { if pat_is_binding(&tcx.def_map, &*pat) {
// Allocate the stack slot where the value of this // Allocate the stack slot where the value of this
// binding will live and place it into the appropriate // binding will live and place it into the appropriate
// map. // map.
bcx = mk_binding_alloca( bcx = mk_binding_alloca(
bcx, pat.id, path, binding_mode, cleanup_scope, (), bcx, pat.id, &path1.node, binding_mode, cleanup_scope, (),
|(), bcx, llval, ty| { |(), bcx, llval, ty| {
match pat_binding_mode { match pat_binding_mode {
ast::BindByValue(_) => { ast::BindByValue(_) => {

View File

@ -842,8 +842,8 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
let cx = bcx.ccx(); let cx = bcx.ccx();
let def_map = &cx.tcx.def_map; let def_map = &cx.tcx.def_map;
pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, path_ref| { pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, path1| {
let var_ident = ast_util::path_to_ident(path_ref); let var_ident = path1.node;
let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) { let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
Some(datum) => datum, Some(datum) => datum,
@ -890,8 +890,8 @@ pub fn create_captured_var_metadata(bcx: &Block,
} }
Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => { Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
match pat.node { match pat.node {
ast::PatIdent(_, ref path, _) => { ast::PatIdent(_, ref path1, _) => {
ast_util::path_to_ident(path) path1.node
} }
_ => { _ => {
cx.sess() cx.sess()
@ -990,7 +990,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
let def_map = &cx.tcx.def_map; let def_map = &cx.tcx.def_map;
let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata; let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path_ref| { pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path1| {
let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) { let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
Some(v) => v, Some(v) => v,
None => { None => {
@ -1005,8 +1005,6 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
Referenced variable location is not an alloca!"); Referenced variable location is not an alloca!");
} }
let argument_ident = ast_util::path_to_ident(path_ref);
let argument_index = { let argument_index = {
let counter = &fcx.debug_context.get_ref(cx, span).argument_counter; let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
let argument_index = counter.get(); let argument_index = counter.get();
@ -1015,7 +1013,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
}; };
declare_local(bcx, declare_local(bcx,
argument_ident, path1.node,
llarg.ty, llarg.ty,
scope_metadata, scope_metadata,
DirectVariable { alloca: llarg.val }, DirectVariable { alloca: llarg.val },
@ -3220,10 +3218,9 @@ fn populate_scope_map(cx: &CrateContext,
// Push argument identifiers onto the stack so arguments integrate nicely // Push argument identifiers onto the stack so arguments integrate nicely
// with variable shadowing. // with variable shadowing.
for &arg_pat in arg_pats.iter() { for &arg_pat in arg_pats.iter() {
pat_util::pat_bindings(def_map, &*arg_pat, |_, _, _, path_ref| { pat_util::pat_bindings(def_map, &*arg_pat, |_, _, _, path1| {
let ident = ast_util::path_to_ident(path_ref);
scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
ident: Some(ident) }); ident: Some(path1.node) });
}) })
} }
@ -3331,13 +3328,13 @@ fn populate_scope_map(cx: &CrateContext,
// ast_util::walk_pat() here because we have to visit *all* nodes in // ast_util::walk_pat() here because we have to visit *all* nodes in
// order to put them into the scope map. The above functions don't do that. // order to put them into the scope map. The above functions don't do that.
match pat.node { match pat.node {
ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => { ast::PatIdent(_, ref path1, ref sub_pat_opt) => {
// Check if this is a binding. If so we need to put it on the // Check if this is a binding. If so we need to put it on the
// scope stack and maybe introduce an artificial scope // scope stack and maybe introduce an artificial scope
if pat_util::pat_is_binding(def_map, &*pat) { if pat_util::pat_is_binding(def_map, &*pat) {
let ident = ast_util::path_to_ident(path_ref); let ident = path1.node;
// LLVM does not properly generate 'DW_AT_start_scope' fields // LLVM does not properly generate 'DW_AT_start_scope' fields
// for variable DIEs. For this reason we have to introduce // for variable DIEs. For this reason we have to introduce

View File

@ -2771,8 +2771,8 @@ pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
match cx.map.find(id) { match cx.map.find(id) {
Some(ast_map::NodeLocal(pat)) => { Some(ast_map::NodeLocal(pat)) => {
match pat.node { match pat.node {
ast::PatIdent(_, ref path, _) => { ast::PatIdent(_, ref path1, _) => {
token::get_ident(ast_util::path_to_ident(path)) token::get_ident(path1.node)
} }
_ => { _ => {
cx.sess.bug( cx.sess.bug(

View File

@ -485,7 +485,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
demand::suptype(fcx, pat.span, expected, const_pty.ty); demand::suptype(fcx, pat.span, expected, const_pty.ty);
fcx.write_ty(pat.id, const_pty.ty); fcx.write_ty(pat.id, const_pty.ty);
} }
ast::PatIdent(bm, ref name, sub) if pat_is_binding(&tcx.def_map, pat) => { ast::PatIdent(bm, ref path1, sub) if pat_is_binding(&tcx.def_map, pat) => {
let typ = fcx.local_ty(pat.span, pat.id); let typ = fcx.local_ty(pat.span, pat.id);
match bm { match bm {
@ -507,7 +507,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
} }
} }
let canon_id = *pcx.map.get(&ast_util::path_to_ident(name)); let canon_id = *pcx.map.get(&path1.node);
if canon_id != pat.id { if canon_id != pat.id {
let ct = fcx.local_ty(pat.span, canon_id); let ct = fcx.local_ty(pat.span, canon_id);
demand::eqtype(fcx, pat.span, ct, typ); demand::eqtype(fcx, pat.span, ct, typ);
@ -521,8 +521,10 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
_ => () _ => ()
} }
} }
ast::PatIdent(_, ref path, _) => { // it's not a binding, it's an enum in disguise:
check_pat_variant(pcx, pat, path, &Some(Vec::new()), expected); ast::PatIdent(_, ref path1, _) => {
let path = ast_util::ident_to_path(path1.span,path1.node);
check_pat_variant(pcx, pat, &path, &Some(Vec::new()), expected);
} }
ast::PatEnum(ref path, ref subpats) => { ast::PatEnum(ref path, ref subpats) => {
check_pat_variant(pcx, pat, path, subpats, expected); check_pat_variant(pcx, pat, path, subpats, expected);

View File

@ -406,11 +406,11 @@ impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
// Add pattern bindings. // Add pattern bindings.
fn visit_pat(&mut self, p: &ast::Pat, _: ()) { fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
match p.node { match p.node {
ast::PatIdent(_, ref path, _) ast::PatIdent(_, ref path1, _)
if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => { if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
self.assign(p.id, None); self.assign(p.id, None);
debug!("Pattern binding {} is assigned to {}", debug!("Pattern binding {} is assigned to {}",
token::get_ident(path.segments.get(0).identifier), token::get_ident(path1.node),
self.fcx.infcx().ty_to_str( self.fcx.infcx().ty_to_str(
self.fcx.inh.locals.borrow().get_copy(&p.id))); self.fcx.inh.locals.borrow().get_copy(&p.id)));
} }

View File

@ -1583,8 +1583,6 @@ impl Clean<PathSegment> for ast::PathSegment {
} }
fn path_to_str(p: &ast::Path) -> String { fn path_to_str(p: &ast::Path) -> String {
use syntax::parse::token;
let mut s = String::new(); let mut s = String::new();
let mut first = true; let mut first = true;
for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) { for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
@ -1953,7 +1951,7 @@ fn name_from_pat(p: &ast::Pat) -> String {
match p.node { match p.node {
PatWild => "_".to_string(), PatWild => "_".to_string(),
PatWildMulti => "..".to_string(), PatWildMulti => "..".to_string(),
PatIdent(_, ref p, _) => path_to_str(p), PatIdent(_, ref p, _) => token::get_ident(p.node).get().to_string(),
PatEnum(ref p, _) => path_to_str(p), PatEnum(ref p, _) => path_to_str(p),
PatStruct(..) => fail!("tried to get argument name from pat_struct, \ PatStruct(..) => fail!("tried to get argument name from pat_struct, \
which is not allowed in function arguments"), which is not allowed in function arguments"),

View File

@ -293,8 +293,8 @@ pub enum Pat_ {
// In the nullary enum case, the parser can't determine // In the nullary enum case, the parser can't determine
// which it is. The resolver determines this, and // which it is. The resolver determines this, and
// records this pattern's NodeId in an auxiliary // records this pattern's NodeId in an auxiliary
// set (of "pat_idents that refer to nullary enums") // set (of "PatIdents that refer to nullary enums")
PatIdent(BindingMode, Path, Option<Gc<Pat>>), PatIdent(BindingMode, SpannedIdent, Option<Gc<Pat>>),
PatEnum(Path, Option<Vec<Gc<Pat>>>), /* "none" means a * pattern where PatEnum(Path, Option<Vec<Gc<Pat>>>), /* "none" means a * pattern where
* we don't bind the fields to names */ * we don't bind the fields to names */
PatStruct(Path, Vec<FieldPat>, bool), PatStruct(Path, Vec<FieldPat>, bool),
@ -818,7 +818,7 @@ pub struct Arg {
impl Arg { impl Arg {
pub fn new_self(span: Span, mutability: Mutability) -> Arg { pub fn new_self(span: Span, mutability: Mutability) -> Arg {
let path = ast_util::ident_to_path(span, special_idents::self_); let path = Spanned{span:span,node:special_idents::self_};
Arg { Arg {
// HACK(eddyb) fake type for the self argument. // HACK(eddyb) fake type for the self argument.
ty: P(Ty { ty: P(Ty {

View File

@ -33,12 +33,6 @@ pub fn path_name_i(idents: &[Ident]) -> String {
}).collect::<Vec<String>>().connect("::") }).collect::<Vec<String>>().connect("::")
} }
// totally scary function: ignores all but the last element, should have
// a different name
pub fn path_to_ident(path: &Path) -> Ident {
path.segments.last().unwrap().identifier
}
pub fn local_def(id: NodeId) -> DefId { pub fn local_def(id: NodeId) -> DefId {
ast::DefId { krate: LOCAL_CRATE, node: id } ast::DefId { krate: LOCAL_CRATE, node: id }
} }
@ -186,6 +180,8 @@ pub fn block_from_expr(e: Gc<Expr>) -> P<Block> {
}) })
} }
// convert a span and an identifier to the corresponding
// 1-segment path
pub fn ident_to_path(s: Span, identifier: Ident) -> Path { pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
ast::Path { ast::Path {
span: s, span: s,
@ -202,7 +198,7 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> Gc<Pat> { pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> Gc<Pat> {
box(GC) ast::Pat { id: id, box(GC) ast::Pat { id: id,
node: PatIdent(BindByValue(MutImmutable), ident_to_path(s, i), None), node: PatIdent(BindByValue(MutImmutable), codemap::Spanned{span:s, node:i}, None),
span: s } span: s }
} }

View File

@ -759,8 +759,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
span: Span, span: Span,
ident: ast::Ident, ident: ast::Ident,
bm: ast::BindingMode) -> Gc<ast::Pat> { bm: ast::BindingMode) -> Gc<ast::Pat> {
let path = self.path_ident(span, ident); let pat = ast::PatIdent(bm, Spanned{span: span, node: ident}, None);
let pat = ast::PatIdent(bm, path, None);
self.pat(span, pat) self.pat(span, pat)
} }
fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<Gc<ast::Pat>> ) -> Gc<ast::Pat> { fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<Gc<ast::Pat>> ) -> Gc<ast::Pat> {

View File

@ -1049,7 +1049,7 @@ impl<'a> TraitDef<'a> {
fn create_subpatterns(&self, fn create_subpatterns(&self,
cx: &mut ExtCtxt, cx: &mut ExtCtxt,
field_paths: Vec<ast::Path> , field_paths: Vec<ast::SpannedIdent> ,
mutbl: ast::Mutability) mutbl: ast::Mutability)
-> Vec<Gc<ast::Pat>> { -> Vec<Gc<ast::Pat>> {
field_paths.iter().map(|path| { field_paths.iter().map(|path| {
@ -1095,15 +1095,10 @@ impl<'a> TraitDef<'a> {
cx.span_bug(sp, "a struct with named and unnamed fields in `deriving`"); cx.span_bug(sp, "a struct with named and unnamed fields in `deriving`");
} }
}; };
let path = let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice());
cx.path_ident(sp, paths.push(codemap::Spanned{span: sp, node: ident});
cx.ident_of(format!("{}_{}",
prefix,
i).as_slice()));
paths.push(path.clone());
let val = cx.expr( let val = cx.expr(
sp, ast::ExprParen( sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)))));
cx.expr_deref(sp, cx.expr_path(path))));
ident_expr.push((sp, opt_id, val)); ident_expr.push((sp, opt_id, val));
} }
@ -1145,15 +1140,11 @@ impl<'a> TraitDef<'a> {
let mut ident_expr = Vec::new(); let mut ident_expr = Vec::new();
for (i, va) in variant_args.iter().enumerate() { for (i, va) in variant_args.iter().enumerate() {
let sp = self.set_expn_info(cx, va.ty.span); let sp = self.set_expn_info(cx, va.ty.span);
let path = let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice());
cx.path_ident(sp, let path1 = codemap::Spanned{span: sp, node: ident};
cx.ident_of(format!("{}_{}", paths.push(path1);
prefix, let expr_path = cx.expr_path(cx.path_ident(sp, ident));
i).as_slice())); let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path)));
paths.push(path.clone());
let val = cx.expr(
sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(path))));
ident_expr.push((sp, None, val)); ident_expr.push((sp, None, val));
} }

View File

@ -705,22 +705,10 @@ impl Visitor<()> for NameFinderContext {
// we found a pat_ident! // we found a pat_ident!
ast::Pat { ast::Pat {
id: _, id: _,
node: ast::PatIdent(_, ref path, ref inner), node: ast::PatIdent(_, ref path1, ref inner),
span: _ span: _
} => { } => {
match path { self.ident_accumulator.push(path1.node);
// a path of length one:
&ast::Path {
global: false,
span: _,
segments: ref segments
} if segments.len() == 1 => {
self.ident_accumulator.push(segments.get(0)
.identifier)
}
// I believe these must be enums...
_ => ()
}
// visit optional subpattern of pat_ident: // visit optional subpattern of pat_ident:
for subpat in inner.iter() { for subpat in inner.iter() {
self.visit_pat(&**subpat, ()) self.visit_pat(&**subpat, ())

View File

@ -791,9 +791,10 @@ pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {
let node = match p.node { let node = match p.node {
PatWild => PatWild, PatWild => PatWild,
PatWildMulti => PatWildMulti, PatWildMulti => PatWildMulti,
PatIdent(binding_mode, ref pth, ref sub) => { PatIdent(binding_mode, ref pth1, ref sub) => {
PatIdent(binding_mode, PatIdent(binding_mode,
folder.fold_path(pth), Spanned{span: folder.new_span(pth1.span),
node: folder.fold_ident(pth1.node)},
sub.map(|x| folder.fold_pat(x))) sub.map(|x| folder.fold_pat(x)))
} }
PatLit(e) => PatLit(folder.fold_expr(e)), PatLit(e) => PatLit(folder.fold_expr(e)),

View File

@ -594,22 +594,14 @@ mod test {
#[test] fn parse_ident_pat () { #[test] fn parse_ident_pat () {
let sess = new_parse_sess(); let sess = new_parse_sess();
let mut parser = string_to_parser(&sess, "b".to_string()); let mut parser = string_to_parser(&sess, "b".to_string());
assert!(parser.parse_pat() == assert!(parser.parse_pat()
box(GC) ast::Pat{id: ast::DUMMY_NODE_ID, == box(GC) ast::Pat{
node: ast::PatIdent( id: ast::DUMMY_NODE_ID,
ast::BindByValue(ast::MutImmutable), node: ast::PatIdent(ast::BindByValue(ast::MutImmutable),
ast::Path { Spanned{ span:sp(0, 1),
span:sp(0,1), node: str_to_ident("b")
global:false,
segments: vec!(
ast::PathSegment {
identifier: str_to_ident("b"),
lifetimes: Vec::new(),
types: OwnedSlice::empty(),
}
),
}, },
None /* no idea */), None),
span: sp(0,1)}); span: sp(0,1)});
parser_done(parser); parser_done(parser);
} }
@ -643,19 +635,10 @@ mod test {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: ast::PatIdent( node: ast::PatIdent(
ast::BindByValue(ast::MutImmutable), ast::BindByValue(ast::MutImmutable),
ast::Path { Spanned{
span:sp(6,7), span: sp(6,7),
global:false, node: str_to_ident("b")},
segments: vec!( None
ast::PathSegment {
identifier:
str_to_ident("b"),
lifetimes: Vec::new(),
types: OwnedSlice::empty(),
}
),
},
None // no idea
), ),
span: sp(6,7) span: sp(6,7)
}, },

View File

@ -58,7 +58,7 @@ use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use ast::Visibility; use ast::Visibility;
use ast; use ast;
use ast_util::{as_prec, lit_is_str, operator_prec}; use ast_util::{as_prec, ident_to_path, lit_is_str, operator_prec};
use ast_util; use ast_util;
use codemap::{Span, BytePos, Spanned, spanned, mk_sp}; use codemap::{Span, BytePos, Spanned, spanned, mk_sp};
use codemap; use codemap;
@ -2854,8 +2854,7 @@ impl<'a> Parser<'a> {
self.bump(); self.bump();
self.parse_pat() self.parse_pat()
} else { } else {
let fieldpath = ast_util::ident_to_path(self.last_span, let fieldpath = codemap::Spanned{span:self.last_span, node: fieldname};
fieldname);
box(GC) ast::Pat { box(GC) ast::Pat {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
node: PatIdent(bind_type, fieldpath, None), node: PatIdent(bind_type, fieldpath, None),
@ -2961,6 +2960,7 @@ impl<'a> Parser<'a> {
} }
_ => {} _ => {}
} }
// at this point, token != _, ~, &, &&, (, [
if (!is_ident_or_path(&self.token) && self.token != token::MOD_SEP) if (!is_ident_or_path(&self.token) && self.token != token::MOD_SEP)
|| self.is_keyword(keywords::True) || self.is_keyword(keywords::True)
@ -3017,7 +3017,9 @@ impl<'a> Parser<'a> {
let end = self.parse_expr_res(RESTRICT_NO_BAR_OP); let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
pat = PatRange(start, end); pat = PatRange(start, end);
} else if is_plain_ident(&self.token) && !can_be_enum_or_struct { } else if is_plain_ident(&self.token) && !can_be_enum_or_struct {
let name = self.parse_path(NoTypesAllowed).path; let id = self.parse_ident();
let id_span = self.last_span;
let pth1 = codemap::Spanned{span:id_span, node: id};
if self.eat(&token::NOT) { if self.eat(&token::NOT) {
// macro invocation // macro invocation
let ket = token::close_delimiter_for(&self.token) let ket = token::close_delimiter_for(&self.token)
@ -3028,7 +3030,7 @@ impl<'a> Parser<'a> {
seq_sep_none(), seq_sep_none(),
|p| p.parse_token_tree()); |p| p.parse_token_tree());
let mac = MacInvocTT(name, tts, EMPTY_CTXT); let mac = MacInvocTT(ident_to_path(id_span,id), tts, EMPTY_CTXT);
pat = ast::PatMac(codemap::Spanned {node: mac, span: self.span}); pat = ast::PatMac(codemap::Spanned {node: mac, span: self.span});
} else { } else {
let sub = if self.eat(&token::AT) { let sub = if self.eat(&token::AT) {
@ -3038,7 +3040,7 @@ impl<'a> Parser<'a> {
// or just foo // or just foo
None None
}; };
pat = PatIdent(BindByValue(MutImmutable), name, sub); pat = PatIdent(BindByValue(MutImmutable), pth1, sub);
} }
} else { } else {
// parse an enum pat // parse an enum pat
@ -3084,7 +3086,10 @@ impl<'a> Parser<'a> {
// or an identifier pattern, resolve // or an identifier pattern, resolve
// will sort it out: // will sort it out:
pat = PatIdent(BindByValue(MutImmutable), pat = PatIdent(BindByValue(MutImmutable),
enum_path, codemap::Spanned{
span: enum_path.span,
node: enum_path.segments.get(0)
.identifier},
None); None);
} else { } else {
pat = PatEnum(enum_path, Some(args)); pat = PatEnum(enum_path, Some(args));
@ -3115,7 +3120,7 @@ impl<'a> Parser<'a> {
"expected identifier, found path"); "expected identifier, found path");
} }
// why a path here, and not just an identifier? // why a path here, and not just an identifier?
let name = self.parse_path(NoTypesAllowed).path; let name = codemap::Spanned{span: self.last_span, node: self.parse_ident()};
let sub = if self.eat(&token::AT) { let sub = if self.eat(&token::AT) {
Some(self.parse_pat()) Some(self.parse_pat())
} else { } else {

View File

@ -196,6 +196,10 @@ pub fn path_to_str(p: &ast::Path) -> String {
to_str(|s| s.print_path(p, false)) to_str(|s| s.print_path(p, false))
} }
pub fn ident_to_str(id: &ast::Ident) -> String {
to_str(|s| s.print_ident(*id))
}
pub fn fun_to_str(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident, pub fn fun_to_str(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
opt_explicit_self: Option<ast::ExplicitSelf_>, opt_explicit_self: Option<ast::ExplicitSelf_>,
generics: &ast::Generics) -> String { generics: &ast::Generics) -> String {
@ -1705,7 +1709,7 @@ impl<'a> State<'a> {
match pat.node { match pat.node {
ast::PatWild => try!(word(&mut self.s, "_")), ast::PatWild => try!(word(&mut self.s, "_")),
ast::PatWildMulti => try!(word(&mut self.s, "..")), ast::PatWildMulti => try!(word(&mut self.s, "..")),
ast::PatIdent(binding_mode, ref path, sub) => { ast::PatIdent(binding_mode, ref path1, sub) => {
match binding_mode { match binding_mode {
ast::BindByRef(mutbl) => { ast::BindByRef(mutbl) => {
try!(self.word_nbsp("ref")); try!(self.word_nbsp("ref"));
@ -1716,7 +1720,7 @@ impl<'a> State<'a> {
try!(self.word_nbsp("mut")); try!(self.word_nbsp("mut"));
} }
} }
try!(self.print_path(path, true)); try!(self.print_ident(path1.node));
match sub { match sub {
Some(ref p) => { Some(ref p) => {
try!(word(&mut self.s, "@")); try!(word(&mut self.s, "@"));
@ -2148,9 +2152,8 @@ impl<'a> State<'a> {
ast::TyInfer => try!(self.print_pat(&*input.pat)), ast::TyInfer => try!(self.print_pat(&*input.pat)),
_ => { _ => {
match input.pat.node { match input.pat.node {
ast::PatIdent(_, ref path, _) if ast::PatIdent(_, ref path1, _) if
path.segments.len() == 1 && path1.node.name ==
path.segments.get(0).identifier.name ==
parse::token::special_idents::invalid.name => { parse::token::special_idents::invalid.name => {
// Do nothing. // Do nothing.
} }

View File

@ -454,8 +454,8 @@ pub fn walk_pat<E: Clone, V: Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E)
PatRegion(ref subpattern) => { PatRegion(ref subpattern) => {
visitor.visit_pat(&**subpattern, env) visitor.visit_pat(&**subpattern, env)
} }
PatIdent(_, ref path, ref optional_subpattern) => { PatIdent(_, ref pth1, ref optional_subpattern) => {
visitor.visit_path(path, pattern.id, env.clone()); visitor.visit_ident(pth1.span, pth1.node, env.clone());
match *optional_subpattern { match *optional_subpattern {
None => {} None => {}
Some(ref subpattern) => visitor.visit_pat(&**subpattern, env), Some(ref subpattern) => visitor.visit_pat(&**subpattern, env),