From 6f872113ab05c0a23a8784e54d22b9e0641dde41 Mon Sep 17 00:00:00 2001
From: Hugo van der Wijst <hugo@wij.st>
Date: Wed, 4 Feb 2015 20:00:28 +0100
Subject: [PATCH] Add QPath construction to ExtCtxt for UFCS support.

---
 src/libsyntax/ext/build.rs | 56 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 53c35ef34cd0d..4d618e560c5cc 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -41,6 +41,18 @@ pub trait AstBuilder {
                 bindings: Vec<P<ast::TypeBinding>> )
         -> ast::Path;
 
+    fn qpath(&self, self_type: P<ast::Ty>,
+             trait_ref: P<ast::TraitRef>,
+             ident: ast::Ident )
+        -> P<ast::QPath>;
+    fn qpath_all(&self, self_type: P<ast::Ty>,
+                trait_ref: P<ast::TraitRef>,
+                ident: ast::Ident,
+                lifetimes: Vec<ast::Lifetime>,
+                types: Vec<P<ast::Ty>>,
+                bindings: Vec<P<ast::TypeBinding>> )
+        -> P<ast::QPath>;
+
     // types
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
 
@@ -103,6 +115,7 @@ pub trait AstBuilder {
     // expressions
     fn expr(&self, span: Span, node: ast::Expr_) -> P<ast::Expr>;
     fn expr_path(&self, path: ast::Path) -> P<ast::Expr>;
+    fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr>;
     fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>;
 
     fn expr_self(&self, span: Span) -> P<ast::Expr>;
@@ -331,6 +344,44 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         }
     }
 
+    /// Constructs a qualified path.
+    ///
+    /// Constructs a path like `<self_type as trait_ref>::ident`.
+    fn qpath(&self,
+             self_type: P<ast::Ty>,
+             trait_ref: P<ast::TraitRef>,
+             ident: ast::Ident)
+             -> P<ast::QPath> {
+        self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new())
+    }
+
+    /// Constructs a qualified path.
+    ///
+    /// Constructs a path like `<self_type as trait_ref>::ident<a, T, A=Bar>`.
+    fn qpath_all(&self,
+                 self_type: P<ast::Ty>,
+                 trait_ref: P<ast::TraitRef>,
+                 ident: ast::Ident,
+                 lifetimes: Vec<ast::Lifetime>,
+                 types: Vec<P<ast::Ty>>,
+                 bindings: Vec<P<ast::TypeBinding>> )
+                 -> P<ast::QPath> {
+        let segment = ast::PathSegment {
+            identifier: ident,
+            parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+                lifetimes: lifetimes,
+                types: OwnedSlice::from_vec(types),
+                bindings: OwnedSlice::from_vec(bindings),
+            })
+        };
+
+        P(ast::QPath {
+            self_type: self_type,
+            trait_ref: trait_ref,
+            item_path: segment,
+        })
+    }
+
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
         ast::MutTy {
             ty: ty,
@@ -554,6 +605,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr(path.span, ast::ExprPath(path))
     }
 
+    /// Constructs a QPath expression.
+    fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr> {
+        self.expr(span, ast::ExprQPath(qpath))
+    }
+
     fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr> {
         self.expr_path(self.path_ident(span, id))
     }