]> git.lizzy.rs Git - rust.git/commitdiff
support `default impl` for specialization
authorGianni Ciccarelli <gianni.ciccarelli@gmail.com>
Wed, 26 Apr 2017 03:17:48 +0000 (03:17 +0000)
committerGianni Ciccarelli <gianni.ciccarelli@gmail.com>
Wed, 26 Apr 2017 14:43:09 +0000 (14:43 +0000)
    `[default] [unsafe] impl` and typecheck

src/grammar/parser-lalr.y
src/librustc/hir/lowering.rs
src/librustc/traits/util.rs
src/librustc_typeck/check/mod.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/parser.rs
src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs

index 69ba0c9098be36f8cc589a6ab287c0cf34566c6d..c9fcdf7647b9cfa79e42164ca858d728a7685dd7 100644 (file)
@@ -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);
 }
index 8dda297e897b2af3504736da7f0b3ba7d9946941..8f4dce5a78303d51d2c5850fd4fceb6af612df39 100644 (file)
@@ -1363,7 +1363,7 @@ fn lower_item_kind(&mut self,
             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
     }
 
index 4aa7950de8f1ed1c85ff1dd172af533a4d4fcb6d..e7c61dde768c011626a2dd5c11b2bad482a86f60 100644 (file)
@@ -14,6 +14,7 @@
 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 @@ pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
             }
         }
     }
+
+    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 }
index a00d1ad0eae652aab8fe2911041f2ed0153cfb16..631e09d831d5c61f26f6a2989f2df14f43f17745 100644 (file)
@@ -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());
         }
     }
 
index 152a4e7ee1add2b01a477aaf07afef124bcbb900..b6a2c983fd4d7fb687abc39bea3ea65ddb14a844 100644 (file)
@@ -1226,13 +1226,10 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                     _ => {}
                 }
 
-                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");
                 }
             }
 
index 2c10fff03dbe858b9c0b7d83f6ebcd683d334bb1..f806e1e3bde624144ecc065a31fc7920238800d6 100644 (file)
@@ -4918,12 +4918,9 @@ fn parse_item_impl(&mut self,
                                           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 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
         }
         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_,
index 9376d0db2df63efe0ebb70f41c102a20dc6bb632..7daecc842f3f9fd8a2140a3785db00b2f34cbffc 100644 (file)
@@ -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 @@ fn foo(&self) -> &'static str {
 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"
     }