summary refs log tree commit diff
path: root/src/libsyntax/fold.rs
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-08-05 19:44:21 -0700
committerPatrick Walton <pcwalton@mimiga.net>2014-09-17 16:38:57 -0700
commit78a841810eb36e486ba68e6b9fa80e45d805cc4f (patch)
treeb1c7c6d9c49f84e03b374b5b70cb0c9d0b60a7de /src/libsyntax/fold.rs
parent8067f4425d245a210c732a0333245fbe83190e89 (diff)
downloadrust-78a841810eb36e486ba68e6b9fa80e45d805cc4f.tar.gz
rust-78a841810eb36e486ba68e6b9fa80e45d805cc4f.zip
librustc: Implement associated types behind a feature gate.
The implementation essentially desugars during type collection and AST
type conversion time into the parameter scheme we have now. Only fully
qualified names--e.g. `<T as Foo>::Bar`--are supported.
Diffstat (limited to 'src/libsyntax/fold.rs')
-rw-r--r--src/libsyntax/fold.rs135
1 files changed, 114 insertions, 21 deletions
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 4806c5fa7c0..3beba5bcda4 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -287,6 +287,15 @@ pub trait Folder {
         noop_fold_where_predicate(where_predicate, self)
     }
 
+    fn fold_typedef(&mut self, typedef: Typedef) -> Typedef {
+        noop_fold_typedef(typedef, self)
+    }
+
+    fn fold_associated_type(&mut self, associated_type: AssociatedType)
+                            -> AssociatedType {
+        noop_fold_associated_type(associated_type, self)
+    }
+
     fn new_id(&mut self, i: NodeId) -> NodeId {
         i
     }
@@ -414,6 +423,13 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
                         fld.fold_opt_bounds(bounds),
                         id)
             }
+            TyQPath(ref qpath) => {
+                TyQPath(P(QPath {
+                    for_type: fld.fold_ty(qpath.for_type.clone()),
+                    trait_name: fld.fold_path(qpath.trait_name.clone()),
+                    item_name: fld.fold_ident(qpath.item_name.clone()),
+                }))
+            }
             TyFixedLengthVec(ty, e) => {
                 TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
             }
@@ -735,6 +751,44 @@ pub fn noop_fold_where_predicate<T: Folder>(
     }
 }
 
+pub fn noop_fold_typedef<T>(t: Typedef, folder: &mut T)
+                            -> Typedef
+                            where T: Folder {
+    let new_id = folder.new_id(t.id);
+    let new_span = folder.new_span(t.span);
+    let new_attrs = t.attrs.iter().map(|attr| {
+        folder.fold_attribute((*attr).clone())
+    }).collect();
+    let new_ident = folder.fold_ident(t.ident);
+    let new_type = folder.fold_ty(t.typ);
+    ast::Typedef {
+        ident: new_ident,
+        typ: new_type,
+        id: new_id,
+        span: new_span,
+        vis: t.vis,
+        attrs: new_attrs,
+    }
+}
+
+pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
+                                    -> AssociatedType
+                                    where T: Folder {
+    let new_id = folder.new_id(at.id);
+    let new_span = folder.new_span(at.span);
+    let new_ident = folder.fold_ident(at.ident);
+    let new_attrs = at.attrs
+                      .iter()
+                      .map(|attr| folder.fold_attribute((*attr).clone()))
+                      .collect();
+    ast::AssociatedType {
+        ident: new_ident,
+        attrs: new_attrs,
+        id: new_id,
+        span: new_span,
+    }
+}
+
 pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
     struct_def.map(|StructDef {fields, ctor_id, super_struct, is_virtual}| StructDef {
         fields: fields.move_map(|f| fld.fold_struct_field(f)),
@@ -857,31 +911,59 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
         ItemImpl(generics, ifce, ty, impl_items) => {
+            let mut new_impl_items = Vec::new();
+            for impl_item in impl_items.iter() {
+                match *impl_item {
+                    MethodImplItem(ref x) => {
+                        for method in folder.fold_method((*x).clone())
+                                            .move_iter() {
+                            new_impl_items.push(MethodImplItem(method))
+                        }
+                    }
+                    TypeImplItem(ref t) => {
+                        new_impl_items.push(TypeImplItem(
+                                P(folder.fold_typedef((**t).clone()))));
+                    }
+                }
+            }
+            let ifce = match ifce {
+                None => None,
+                Some(ref trait_ref) => {
+                    Some(folder.fold_trait_ref((*trait_ref).clone()))
+                }
+            };
             ItemImpl(folder.fold_generics(generics),
-                     ifce.map(|p| folder.fold_trait_ref(p)),
+                     ifce,
                      folder.fold_ty(ty),
-                     impl_items.into_iter().flat_map(|impl_item| match impl_item {
-                        MethodImplItem(x) => {
-                            folder.fold_method(x).into_iter().map(|x| MethodImplItem(x))
-                        }
-                     }).collect())
+                     new_impl_items)
         }
         ItemTrait(generics, unbound, bounds, methods) => {
             let bounds = folder.fold_bounds(bounds);
-            let methods = methods.into_iter().flat_map(|method| match method {
-                RequiredMethod(m) => {
-                    SmallVector::one(RequiredMethod(folder.fold_type_method(m))).into_iter()
-                }
-                ProvidedMethod(method) => {
-                    // the awkward collect/iter idiom here is because
-                    // even though an iter and a map satisfy the same trait bound,
-                    // they're not actually the same type, so the method arms
-                    // don't unify.
-                    let methods: SmallVector<ast::TraitItem> =
-                        folder.fold_method(method).into_iter()
-                        .map(|m| ProvidedMethod(m)).collect();
-                    methods.into_iter()
-                }
+            let methods = methods.into_iter().flat_map(|method| {
+                let r = match method {
+                    RequiredMethod(m) => {
+                            SmallVector::one(RequiredMethod(
+                                    folder.fold_type_method(m)))
+                                .move_iter()
+                    }
+                    ProvidedMethod(method) => {
+                        // the awkward collect/iter idiom here is because
+                        // even though an iter and a map satisfy the same
+                        // trait bound, they're not actually the same type, so
+                        // the method arms don't unify.
+                        let methods: SmallVector<ast::TraitItem> =
+                            folder.fold_method(method).move_iter()
+                            .map(|m| ProvidedMethod(m)).collect();
+                        methods.move_iter()
+                    }
+                    TypeTraitItem(at) => {
+                        SmallVector::one(TypeTraitItem(P(
+                                    folder.fold_associated_type(
+                                        (*at).clone()))))
+                            .move_iter()
+                    }
+                };
+                r
             }).collect();
             ItemTrait(folder.fold_generics(generics),
                       unbound,
@@ -893,7 +975,18 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
 }
 
 pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMethod {
-    let TypeMethod {id, ident, attrs, fn_style, abi, decl, generics, explicit_self, vis, span} = m;
+    let TypeMethod {
+        id,
+        ident,
+        attrs,
+        fn_style,
+        abi,
+        decl,
+        generics,
+        explicit_self,
+        vis,
+        span
+    } = m;
     TypeMethod {
         id: fld.new_id(id),
         ident: fld.fold_ident(ident),