about summary refs log tree commit diff
path: root/src/libsyntax/ast.rs
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-12-17 01:53:11 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-12-17 19:00:50 +0300
commit70e5c3731961b5754bc5b155a75b2f7ff7fb997b (patch)
tree0ec785acdd6d1c3ffe94041151b4514424d15e43 /src/libsyntax/ast.rs
parentaf57acef1cd1651861be0bfe77b4f4dd3066ce02 (diff)
downloadrust-70e5c3731961b5754bc5b155a75b2f7ff7fb997b.tar.gz
rust-70e5c3731961b5754bc5b155a75b2f7ff7fb997b.zip
syntax: recovery for incorrect associated item paths like `[T; N]::clone`
Diffstat (limited to 'src/libsyntax/ast.rs')
-rw-r--r--src/libsyntax/ast.rs94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 0d289dbd46b..461cb0480d2 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -20,6 +20,7 @@ use syntax_pos::{Span, DUMMY_SP};
 use codemap::{respan, Spanned};
 use abi::Abi;
 use ext::hygiene::{Mark, SyntaxContext};
+use parse::parser::{RecoverQPath, PathStyle};
 use print::pprust;
 use ptr::P;
 use rustc_data_structures::indexed_vec;
@@ -519,6 +520,38 @@ impl Pat {
     }
 }
 
+impl RecoverQPath for Pat {
+    fn to_ty(&self) -> Option<P<Ty>> {
+        let node = match &self.node {
+            PatKind::Wild => TyKind::Infer,
+            PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) =>
+                TyKind::Path(None, Path::from_ident(ident.span, ident.node)),
+            PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
+            PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
+            PatKind::Ref(pat, mutbl) =>
+                pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
+            PatKind::Slice(pats, None, _) if pats.len() == 1 =>
+                pats[0].to_ty().map(TyKind::Slice)?,
+            PatKind::Tuple(pats, None) => {
+                let mut tys = Vec::new();
+                for pat in pats {
+                    tys.push(pat.to_ty()?);
+                }
+                TyKind::Tup(tys)
+            }
+            _ => return None,
+        };
+
+        Some(P(Ty { node, id: self.id, span: self.span }))
+    }
+    fn to_recovered(&self, qself: Option<QSelf>, path: Path) -> Self {
+        Self { span: path.span, node: PatKind::Path(qself, path), id: self.id }
+    }
+    fn to_string(&self) -> String {
+        pprust::pat_to_string(self)
+    }
+}
+
 /// A single field in a struct pattern
 ///
 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
@@ -877,6 +910,54 @@ impl Expr {
             true
         }
     }
+
+    fn to_bound(&self) -> Option<TyParamBound> {
+        match &self.node {
+            ExprKind::Path(None, path) =>
+                Some(TraitTyParamBound(PolyTraitRef::new(Vec::new(), path.clone(), self.span),
+                                       TraitBoundModifier::None)),
+            _ => None,
+        }
+    }
+}
+
+impl RecoverQPath for Expr {
+    fn to_ty(&self) -> Option<P<Ty>> {
+        let node = match &self.node {
+            ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
+            ExprKind::Mac(mac) => TyKind::Mac(mac.clone()),
+            ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?,
+            ExprKind::AddrOf(mutbl, expr) =>
+                expr.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
+            ExprKind::Repeat(expr, expr_len) =>
+                expr.to_ty().map(|ty| TyKind::Array(ty, expr_len.clone()))?,
+            ExprKind::Array(exprs) if exprs.len() == 1 =>
+                exprs[0].to_ty().map(TyKind::Slice)?,
+            ExprKind::Tup(exprs) => {
+                let mut tys = Vec::new();
+                for expr in exprs {
+                    tys.push(expr.to_ty()?);
+                }
+                TyKind::Tup(tys)
+            }
+            ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add =>
+                if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) {
+                    TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
+                } else {
+                    return None;
+                }
+            _ => return None,
+        };
+
+        Some(P(Ty { node, id: self.id, span: self.span }))
+    }
+    fn to_recovered(&self, qself: Option<QSelf>, path: Path) -> Self {
+        Self { span: path.span, node: ExprKind::Path(qself, path),
+               id: self.id, attrs: self.attrs.clone() }
+    }
+    fn to_string(&self) -> String {
+        pprust::expr_to_string(self)
+    }
 }
 
 impl fmt::Debug for Expr {
@@ -1388,6 +1469,19 @@ pub struct Ty {
     pub span: Span,
 }
 
+impl RecoverQPath for Ty {
+    fn to_ty(&self) -> Option<P<Ty>> {
+        Some(P(self.clone()))
+    }
+    fn to_recovered(&self, qself: Option<QSelf>, path: Path) -> Self {
+        Self { span: path.span, node: TyKind::Path(qself, path), id: self.id }
+    }
+    fn to_string(&self) -> String {
+        pprust::ty_to_string(self)
+    }
+    const PATH_STYLE: PathStyle = PathStyle::Type;
+}
+
 impl fmt::Debug for Ty {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "type({})", pprust::ty_to_string(self))