about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGianni Ciccarelli <gianni.ciccarelli@gmail.com>2017-04-26 03:17:48 +0000
committerGianni Ciccarelli <gianni.ciccarelli@gmail.com>2017-04-26 14:43:09 +0000
commitb48eb5e0be2a6e06d9629f770288c46f7bcb326c (patch)
tree788c9f27af9f780a3765dbdd80e9981274698265 /src
parent715811d0be05dcdc55b44f97d9fd2cd1eb7eee05 (diff)
downloadrust-b48eb5e0be2a6e06d9629f770288c46f7bcb326c.tar.gz
rust-b48eb5e0be2a6e06d9629f770288c46f7bcb326c.zip
support `default impl` for specialization
    `[default] [unsafe] impl` and typecheck
Diffstat (limited to 'src')
-rw-r--r--src/grammar/parser-lalr.y29
-rw-r--r--src/librustc/hir/lowering.rs2
-rw-r--r--src/librustc/traits/util.rs5
-rw-r--r--src/librustc_typeck/check/mod.rs6
-rw-r--r--src/libsyntax/feature_gate.rs11
-rw-r--r--src/libsyntax/parse/parser.rs15
-rw-r--r--src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs22
7 files changed, 44 insertions, 46 deletions
diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y
index 69ba0c9098b..c9fcdf7647b 100644
--- a/src/grammar/parser-lalr.y
+++ b/src/grammar/parser-lalr.y
@@ -535,10 +535,11 @@ maybe_unsafe
 | %empty { $$ = mk_none(); }
 ;
 
-maybe_default_impl
-:         IMPL { $$ = mk_none(); }
-| DEFAULT IMPL { $$ = $1 }
-;
+maybe_default_maybe_unsafe
+: DEFAULT UNSAFE { $$ = mk_atom("DefaultUnsafe"); }
+| DEFAULT        { $$ = mk_atom("Default"); }
+|         UNSAFE { $$ = mk_atom("Unsafe"); }
+| %empty { $$ = mk_none(); }
 
 trait_method
 : type_method { $$ = mk_node("Required", 1, $1); }
@@ -594,27 +595,27 @@ impl_method
 // they are ambiguous with traits. We do the same here, regrettably,
 // by splitting ty into ty and ty_prim.
 item_impl
-: maybe_unsafe maybe_default_impl generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+: maybe_default_maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
 {
-  $$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8, $2);
+  $$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
 }
-| maybe_unsafe maybe_default_impl generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
 {
-  $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10, $2);
+  $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
 }
-| maybe_unsafe maybe_default_impl generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
 {
-  $$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10, $2);
+  $$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
 }
-| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
 {
-  $$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11, $2);
+  $$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
 }
-| maybe_unsafe maybe_default_impl generic_params trait_ref FOR DOTDOT '{' '}'
+| maybe_default_maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
 {
   $$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
 }
-| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR DOTDOT '{' '}'
+| maybe_default_maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
 {
   $$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
 }
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 8dda297e897..8f4dce5a783 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1363,7 +1363,7 @@ impl<'a> LoweringContext<'a> {
             ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
         }
 
-        // [1] `defaultness.has_value()` is necer called for an `impl`, always `true` in order to
+        // [1] `defaultness.has_value()` is never called for an `impl`, always `true` in order to
         //     not cause an assertion failure inside the `lower_defaultness` function
     }
 
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 4aa7950de8f..e7c61dde768 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -14,6 +14,7 @@ use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
 use ty::outlives::Component;
 use util::nodemap::FxHashSet;
 use hir::{self};
+use traits::specialize::specialization_graph::NodeItem;
 
 use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
 
@@ -525,6 +526,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
         }
     }
+
+    pub fn impl_item_is_final(self, node_item: &NodeItem<hir::Defaultness>) -> bool {
+        node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id())
+    }
 }
 
 pub enum TupleArgumentsFlag { Yes, No }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a00d1ad0eae..631e09d831d 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1141,10 +1141,8 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         .map(|node_item| node_item.map(|parent| parent.defaultness));
 
     if let Some(parent) = parent {
-        if parent.item.is_final() {
-            if !tcx.impl_is_default(parent.node.def_id()) {
-                report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
-            }
+        if tcx.impl_item_is_final(&parent) {
+            report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
         }
     }
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 152a4e7ee1a..b6a2c983fd4 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1226,13 +1226,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     _ => {}
                 }
 
-                match defaultness {
-                    ast::Defaultness::Default => {
-                        gate_feature_post!(&self, specialization,
-                                      i.span,
-                                      "specialization is unstable");
-                    }
-                    _ => {}
+                if let ast::Defaultness::Default = defaultness {
+                    gate_feature_post!(&self, specialization,
+                                       i.span,
+                                       "specialization is unstable");
                 }
             }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2c10fff03db..f806e1e3bde 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4918,12 +4918,9 @@ impl<'a> Parser<'a> {
                                           allowed to have generics");
             }
 
-            match defaultness {
-                ast::Defaultness::Default => {
-                    self.span_err(impl_span, "`default impl` is not allowed for \
-                                               default trait implementations");
-                }
-                _ => {}
+            if let ast::Defaultness::Default = defaultness {
+                self.span_err(impl_span, "`default impl` is not allowed for \
+                                         default trait implementations");
             }
 
             self.expect(&token::OpenDelim(token::Brace))?;
@@ -5768,13 +5765,13 @@ impl<'a> Parser<'a> {
         }
         if (self.check_keyword(keywords::Unsafe) &&
             self.look_ahead(1, |t| t.is_keyword(keywords::Impl))) ||
-           (self.check_keyword(keywords::Unsafe) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Default)) &&
+           (self.check_keyword(keywords::Default) &&
+            self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
             self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
         {
             // IMPL ITEM
-            self.expect_keyword(keywords::Unsafe)?;
             let defaultness = self.parse_defaultness()?;
+            self.expect_keyword(keywords::Unsafe)?;
             self.expect_keyword(keywords::Impl)?;
             let (ident,
                  item_,
diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs b/src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs
index 9376d0db2df..7daecc842f3 100644
--- a/src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs
+++ b/src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs
@@ -17,61 +17,61 @@ unsafe trait Foo {
     fn foo(&self) -> &'static str;
 }
 
-unsafe default impl<T> Foo for T {
+default unsafe impl<T> Foo for T {
     fn foo(&self) -> &'static str {
         "generic"
     }
 }
 
-unsafe default impl<T: Clone> Foo for T {
+default unsafe impl<T: Clone> Foo for T {
     fn foo(&self) -> &'static str {
         "generic Clone"
     }
 }
 
-unsafe default impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
+default unsafe impl<T, U> Foo for (T, U) where T: Clone, U: Clone {
     fn foo(&self) -> &'static str {
         "generic pair"
     }
 }
 
-unsafe default impl<T: Clone> Foo for (T, T) {
+default unsafe impl<T: Clone> Foo for (T, T) {
     fn foo(&self) -> &'static str {
         "generic uniform pair"
     }
 }
 
-unsafe default impl Foo for (u8, u32) {
+default unsafe impl Foo for (u8, u32) {
     fn foo(&self) -> &'static str {
         "(u8, u32)"
     }
 }
 
-unsafe default impl Foo for (u8, u8) {
+default unsafe impl Foo for (u8, u8) {
     fn foo(&self) -> &'static str {
         "(u8, u8)"
     }
 }
 
-unsafe default impl<T: Clone> Foo for Vec<T> {
+default unsafe impl<T: Clone> Foo for Vec<T> {
     fn foo(&self) -> &'static str {
         "generic Vec"
     }
 }
 
-unsafe impl Foo for Vec<i32> {
+default unsafe impl Foo for Vec<i32> {
     fn foo(&self) -> &'static str {
         "Vec<i32>"
     }
 }
 
-unsafe impl Foo for String {
+default unsafe impl Foo for String {
     fn foo(&self) -> &'static str {
         "String"
     }
 }
 
-unsafe impl Foo for i32 {
+default unsafe impl Foo for i32 {
     fn foo(&self) -> &'static str {
         "i32"
     }
@@ -80,7 +80,7 @@ unsafe impl Foo for i32 {
 struct NotClone;
 
 unsafe trait MyMarker {}
-unsafe default impl<T: Clone + MyMarker> Foo for T {
+default unsafe impl<T: Clone + MyMarker> Foo for T {
     fn foo(&self) -> &'static str {
         "generic Clone + MyMarker"
     }