about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-04-13 01:43:09 +0000
committerbors <bors@rust-lang.org>2018-04-13 01:43:09 +0000
commitdefcfe7142fca424f7e34aa5c789239e9e9fcfe8 (patch)
tree8b6e479ea80191563607ff243cd46699c53ce56e /src/libsyntax
parentc4a03283cd17c86c9bcdc3fdc76d924ab5eaff2a (diff)
parentfcf48520a0d63828190217ea59849f9098177427 (diff)
downloadrust-defcfe7142fca424f7e34aa5c789239e9e9fcfe8.tar.gz
rust-defcfe7142fca424f7e34aa5c789239e9e9fcfe8.zip
Auto merge of #49718 - petrochenkov:fieldcmp, r=eddyb
Hygiene 2.0: Avoid comparing fields by name

There are two separate commits here (not counting tests):
- The first one unifies named (`obj.name`) and numeric (`obj.0`) field access expressions in AST and HIR. Before field references in these expressions are resolved it doesn't matter whether the field is named or numeric (it's just a symbol) and 99% of code is common. After field references are resolved we work with
them by index for all fields (see the second commit), so it's again not important whether the field was named or numeric (this includes MIR where all fields were already by index).
(This refactoring actually fixed some bugs in HIR-based borrow checker where borrows through names (`S {
0: ref x }`) and indices (`&s.0`) weren't considered overlapping.)
- The second commit removes all by-name field comparison and instead resolves field references to their indices  once, and then uses those resolutions. (There are still a few name comparisons in save-analysis, because save-analysis is weird, but they are made correctly hygienic).
Thus we are fixing a bunch of "secondary" field hygiene bugs (in borrow checker, lints).

Fixes https://github.com/rust-lang/rust/issues/46314
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs7
-rw-r--r--src/libsyntax/ext/build.rs4
-rw-r--r--src/libsyntax/fold.rs5
-rw-r--r--src/libsyntax/parse/parser.rs38
-rw-r--r--src/libsyntax/print/pprust.rs8
-rw-r--r--src/libsyntax/util/parser.rs3
-rw-r--r--src/libsyntax/visit.rs3
7 files changed, 9 insertions, 59 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index e7900af7f12..91c9a1524e1 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1018,7 +1018,6 @@ impl Expr {
             ExprKind::Assign(..) => ExprPrecedence::Assign,
             ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
             ExprKind::Field(..) => ExprPrecedence::Field,
-            ExprKind::TupField(..) => ExprPrecedence::TupField,
             ExprKind::Index(..) => ExprPrecedence::Index,
             ExprKind::Range(..) => ExprPrecedence::Range,
             ExprKind::Path(..) => ExprPrecedence::Path,
@@ -1133,12 +1132,8 @@ pub enum ExprKind {
     ///
     /// For example, `a += 1`.
     AssignOp(BinOp, P<Expr>, P<Expr>),
-    /// Access of a named struct field (`obj.foo`)
+    /// Access of a named (`obj.foo`) or unnamed (`obj.0`) struct field
     Field(P<Expr>, Ident),
-    /// Access of an unnamed field of a struct or tuple-struct
-    ///
-    /// For example, `foo.0`.
-    TupField(P<Expr>, Spanned<usize>),
     /// An indexing operation (`foo[2]`)
     Index(P<Expr>, P<Expr>),
     /// A range (`1..2`, `1..`, `..2`, `1...2`, `1...`, `...2`)
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 062f3ce1127..36244f0a3c4 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -636,8 +636,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr(sp, ast::ExprKind::Field(expr, ident.with_span_pos(sp)))
     }
     fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: usize) -> P<ast::Expr> {
-        let id = Spanned { node: idx, span: sp };
-        self.expr(sp, ast::ExprKind::TupField(expr, id))
+        let ident = Ident::from_str(&idx.to_string()).with_span_pos(sp);
+        self.expr(sp, ast::ExprKind::Field(expr, ident))
     }
     fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
         self.expr(sp, ast::ExprKind::AddrOf(ast::Mutability::Immutable, e))
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index ba6703b9c74..a0cd831a9ba 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1267,11 +1267,6 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
             ExprKind::Field(el, ident) => {
                 ExprKind::Field(folder.fold_expr(el), folder.fold_ident(ident))
             }
-            ExprKind::TupField(el, index) => {
-                ExprKind::TupField(folder.fold_expr(el),
-                             respan(folder.new_span(index.span),
-                                    folder.fold_usize(index.node)))
-            }
             ExprKind::Index(el, er) => {
                 ExprKind::Index(folder.fold_expr(el), folder.fold_expr(er))
             }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 027b24cbbdc..a7a9ce74512 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2144,10 +2144,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn mk_tup_field(&mut self, expr: P<Expr>, idx: codemap::Spanned<usize>) -> ast::ExprKind {
-        ExprKind::TupField(expr, idx)
-    }
-
     pub fn mk_assign_op(&mut self, binop: ast::BinOp,
                         lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
         ExprKind::AssignOp(binop, lhs, rhs)
@@ -2605,35 +2601,11 @@ impl<'a> Parser<'a> {
                   token::Ident(..) => {
                     e = self.parse_dot_suffix(e, lo)?;
                   }
-                  token::Literal(token::Integer(index_ident), suf) => {
-                    let sp = self.span;
-
-                    // A tuple index may not have a suffix
-                    self.expect_no_suffix(sp, "tuple index", suf);
-
-                    let idx_span = self.span;
+                  token::Literal(token::Integer(name), _) => {
+                    let span = self.span;
                     self.bump();
-
-                    let invalid_msg = "invalid tuple or struct index";
-
-                    let index = index_ident.as_str().parse::<usize>().ok();
-                    match index {
-                        Some(n) => {
-                            if n.to_string() != index_ident.as_str() {
-                                let mut err = self.struct_span_err(self.prev_span, invalid_msg);
-                                err.span_suggestion(self.prev_span,
-                                                    "try simplifying the index",
-                                                    n.to_string());
-                                err.emit();
-                            }
-                            let field = self.mk_tup_field(e, respan(idx_span, n));
-                            e = self.mk_expr(lo.to(idx_span), field, ThinVec::new());
-                        }
-                        None => {
-                            let prev_span = self.prev_span;
-                            self.span_err(prev_span, invalid_msg);
-                        }
-                    }
+                    let field = ExprKind::Field(e, Ident::new(name, span));
+                    e = self.mk_expr(lo.to(span), field, ThinVec::new());
                   }
                   token::Literal(token::Float(n), _suf) => {
                     self.bump();
@@ -7058,7 +7030,7 @@ impl<'a> Parser<'a> {
             match self.token {
                 token::Ident(ident, false) if ident.name == keywords::Underscore.name() => {
                     self.bump(); // `_`
-                    Ok(Some(Ident { name: ident.name.gensymed(), ..ident }))
+                    Ok(Some(Ident::new(ident.name.gensymed(), ident.span)))
                 }
                 _ => self.parse_ident().map(Some),
             }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 8168db19058..3741850b8a9 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1966,8 +1966,7 @@ impl<'a> State<'a> {
                        args: &[P<ast::Expr>]) -> io::Result<()> {
         let prec =
             match func.node {
-                ast::ExprKind::Field(..) |
-                ast::ExprKind::TupField(..) => parser::PREC_FORCE_PAREN,
+                ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
                 _ => parser::PREC_POSTFIX,
             };
 
@@ -2203,11 +2202,6 @@ impl<'a> State<'a> {
                 self.s.word(".")?;
                 self.print_ident(ident)?;
             }
-            ast::ExprKind::TupField(ref expr, id) => {
-                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
-                self.s.word(".")?;
-                self.print_usize(id.node)?;
-            }
             ast::ExprKind::Index(ref expr, ref index) => {
                 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX)?;
                 self.s.word("[")?;
diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs
index 4770273e8c4..524f9f127f5 100644
--- a/src/libsyntax/util/parser.rs
+++ b/src/libsyntax/util/parser.rs
@@ -251,7 +251,6 @@ pub enum ExprPrecedence {
     Call,
     MethodCall,
     Field,
-    TupField,
     Index,
     Try,
     InlineAsm,
@@ -320,7 +319,6 @@ impl ExprPrecedence {
             ExprPrecedence::Call |
             ExprPrecedence::MethodCall |
             ExprPrecedence::Field |
-            ExprPrecedence::TupField |
             ExprPrecedence::Index |
             ExprPrecedence::Try |
             ExprPrecedence::InlineAsm |
@@ -365,7 +363,6 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
         ast::ExprKind::Cast(ref x, _) |
         ast::ExprKind::Type(ref x, _) |
         ast::ExprKind::Field(ref x, _) |
-        ast::ExprKind::TupField(ref x, _) |
         ast::ExprKind::Index(ref x, _) => {
             // &X { y: 1 }, X { y: 1 }.y
             contains_exterior_struct_lit(&x)
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index fdb3e2c5f31..8743840e443 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -749,9 +749,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(subexpression);
             visitor.visit_ident(ident);
         }
-        ExprKind::TupField(ref subexpression, _) => {
-            visitor.visit_expr(subexpression);
-        }
         ExprKind::Index(ref main_expression, ref index_expression) => {
             visitor.visit_expr(main_expression);
             visitor.visit_expr(index_expression)