about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2013-10-30 16:44:55 -0700
committerAlex Crichton <alex@alexcrichton.com>2013-10-30 19:52:00 -0700
commit0db50056aec603eadff2e7f2e8e6519824add552 (patch)
tree75ef2967bd65b547ed30471d74962af85433e518
parentfed48cc861fd858762c1e9b498675bfa4dee2d38 (diff)
downloadrust-0db50056aec603eadff2e7f2e8e6519824add552.tar.gz
rust-0db50056aec603eadff2e7f2e8e6519824add552.zip
Forbid type parameters in inner statics
Closes #9186
-rw-r--r--src/libextra/treemap.rs47
-rw-r--r--src/librustc/middle/resolve.rs17
-rw-r--r--src/test/compile-fail/inner-static-type-parameter.rs21
3 files changed, 62 insertions, 23 deletions
diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs
index 7ef9ba76b99..db5b12f021e 100644
--- a/src/libextra/treemap.rs
+++ b/src/libextra/treemap.rs
@@ -145,7 +145,7 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
     pub fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> {
         TreeMapIterator {
             stack: ~[],
-            node: &self.root,
+            node: deref(&self.root),
             remaining_min: self.length,
             remaining_max: self.length
         }
@@ -162,7 +162,7 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
     fn iter_for_traversal<'a>(&'a self) -> TreeMapIterator<'a, K, V> {
         TreeMapIterator {
             stack: ~[],
-            node: &self.root,
+            node: deref(&self.root),
             remaining_min: 0,
             remaining_max: self.length
         }
@@ -173,8 +173,8 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
     pub fn lower_bound_iter<'a>(&'a self, k: &K) -> TreeMapIterator<'a, K, V> {
         let mut iter: TreeMapIterator<'a, K, V> = self.iter_for_traversal();
         loop {
-            match *iter.node {
-              Some(ref r) => {
+            match iter.node {
+              Some(r) => {
                 match k.cmp(&r.key) {
                   Less => iter_traverse_left(&mut iter),
                   Greater => iter_traverse_right(&mut iter),
@@ -197,8 +197,8 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
     pub fn upper_bound_iter<'a>(&'a self, k: &K) -> TreeMapIterator<'a, K, V> {
         let mut iter: TreeMapIterator<'a, K, V> = self.iter_for_traversal();
         loop {
-            match *iter.node {
-              Some(ref r) => {
+            match iter.node {
+              Some(r) => {
                 match k.cmp(&r.key) {
                   Less => iter_traverse_left(&mut iter),
                   Greater => iter_traverse_right(&mut iter),
@@ -229,24 +229,34 @@ impl<K: TotalOrd, V> TreeMap<K, V> {
 
 /// Lazy forward iterator over a map
 pub struct TreeMapIterator<'self, K, V> {
-    priv stack: ~[&'self ~TreeNode<K, V>],
-    priv node: &'self Option<~TreeNode<K, V>>,
+    priv stack: ~[&'self TreeNode<K, V>],
+    priv node: Option<&'self TreeNode<K, V>>,
     priv remaining_min: uint,
     priv remaining_max: uint
 }
 
+fn deref<'a, K, V>(node: &'a Option<~TreeNode<K, V>>) -> Option<&'a TreeNode<K, V>> {
+    match *node {
+        Some(ref n) => {
+            let n: &TreeNode<K, V> = *n;
+            Some(n)
+        }
+        None => None
+    }
+}
+
 impl<'self, K, V> TreeMapIterator<'self, K, V> {
     #[inline(always)]
     fn next_(&mut self, forward: bool) -> Option<(&'self K, &'self V)> {
         while !self.stack.is_empty() || self.node.is_some() {
-            match *self.node {
-              Some(ref x) => {
+            match self.node {
+              Some(x) => {
                 self.stack.push(x);
-                self.node = if forward { &x.left } else { &x.right };
+                self.node = deref(if forward { &x.left } else { &x.right });
               }
               None => {
                 let res = self.stack.pop();
-                self.node = if forward { &res.right } else { &res.left };
+                self.node = deref(if forward { &res.right } else { &res.left });
                 self.remaining_max -= 1;
                 if self.remaining_min > 0 {
                     self.remaining_min -= 1;
@@ -302,14 +312,14 @@ impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapRevIterator<'self, K
 ///   - complete initialization with `iter_traverse_complete`
 #[inline]
 fn iter_traverse_left<'a, K, V>(it: &mut TreeMapIterator<'a, K, V>) {
-    let node = it.node.get_ref();
+    let node = it.node.unwrap();
     it.stack.push(node);
-    it.node = &node.left;
+    it.node = deref(&node.left);
 }
 
 #[inline]
 fn iter_traverse_right<'a, K, V>(it: &mut TreeMapIterator<'a, K, V>) {
-    it.node = &(it.node.get_ref().right);
+    it.node = deref(&it.node.get_ref().right);
 }
 
 /// iter_traverse_left, iter_traverse_right and iter_traverse_complete are used to
@@ -321,11 +331,10 @@ fn iter_traverse_right<'a, K, V>(it: &mut TreeMapIterator<'a, K, V>) {
 /// traversed left.
 #[inline]
 fn iter_traverse_complete<'a, K, V>(it: &mut TreeMapIterator<'a, K, V>) {
-    static none: Option<~TreeNode<K, V>> = None;
-    match *it.node {
-        Some(ref n) => {
+    match it.node {
+        Some(n) => {
             it.stack.push(n);
-            it.node = &none;
+            it.node = None;
         }
         None => ()
     }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 8c5deeb94d5..9f848b4c227 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -3488,10 +3488,17 @@ impl Resolver {
                     return None;
                 }
                 ConstantItemRibKind => {
-                    // Still doesn't deal with upvars
-                    self.resolve_error(span,
-                                          "attempt to use a non-constant \
-                                           value in a constant");
+                    if is_ty_param {
+                        // see #9186
+                        self.resolve_error(span,
+                                              "cannot use an outer type \
+                                               parameter in this context");
+                    } else {
+                        // Still doesn't deal with upvars
+                        self.resolve_error(span,
+                                              "attempt to use a non-constant \
+                                               value in a constant");
+                    }
 
                 }
             }
@@ -3764,7 +3771,9 @@ impl Resolver {
 
     fn with_constant_rib(&mut self, f: &fn(&mut Resolver)) {
         self.value_ribs.push(@Rib::new(ConstantItemRibKind));
+        self.type_ribs.push(@Rib::new(ConstantItemRibKind));
         f(self);
+        self.type_ribs.pop();
         self.value_ribs.pop();
     }
 
diff --git a/src/test/compile-fail/inner-static-type-parameter.rs b/src/test/compile-fail/inner-static-type-parameter.rs
new file mode 100644
index 00000000000..0ec4b62f8d2
--- /dev/null
+++ b/src/test/compile-fail/inner-static-type-parameter.rs
@@ -0,0 +1,21 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// see #9186
+
+enum Bar<T> { What }
+
+fn foo<T>() {
+    static a: Bar<T> = What;
+    //~^ ERROR: cannot use an outer type parameter in this context
+}
+
+fn main() {
+}