about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGianni Ciccarelli <gianni.ciccarelli@gmail.com>2017-04-24 09:56:54 +0000
committerGianni Ciccarelli <gianni.ciccarelli@gmail.com>2017-04-25 05:28:22 +0000
commit715811d0be05dcdc55b44f97d9fd2cd1eb7eee05 (patch)
treec893a210beed2ccc862c0154255461010915c50b /src
parentb0fca5f790e86a4235c64095f4ac55d325253b92 (diff)
downloadrust-715811d0be05dcdc55b44f97d9fd2cd1eb7eee05.tar.gz
rust-715811d0be05dcdc55b44f97d9fd2cd1eb7eee05.zip
support `default impl` for specialization
    pr review
Diffstat (limited to 'src')
m---------src/compiler-rt0
m---------src/doc/book0
m---------src/doc/reference0
-rw-r--r--src/grammar/parser-lalr.y28
m---------src/jemalloc0
m---------src/liblibc0
-rw-r--r--src/librustc/hir/lowering.rs3
-rw-r--r--src/librustc/ich/impls_hir.rs2
-rw-r--r--src/librustc/middle/cstore.rs2
-rw-r--r--src/librustc/traits/project.rs25
-rw-r--r--src/librustc/traits/util.rs21
-rw-r--r--src/librustc_metadata/cstore_impl.rs7
-rw-r--r--src/librustc_metadata/schema.rs1
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs16
-rw-r--r--src/librustc_typeck/collect.rs6
-rw-r--r--src/libsyntax/parse/parser.rs14
m---------src/rt/hoedown0
-rw-r--r--src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs19
-rw-r--r--src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs106
20 files changed, 194 insertions, 58 deletions
diff --git a/src/compiler-rt b/src/compiler-rt
-Subproject a8fc4c169fac43a5dc204d4fd56ddb1739f8c17
+Subproject d30da544a8afc5d78391dee270bdf40e74a215d
diff --git a/src/doc/book b/src/doc/book
-Subproject beea82b9230cd641dd1ca263cf31025ace4aebb
+Subproject ad7de198561b3a12217ea2da76d796d9c7fc0ed
diff --git a/src/doc/reference b/src/doc/reference
-Subproject b060f732145f2fa16df84c74e511df08a3a47c5
+Subproject 6b0de90d87dda15e323ef24cdf7ed873ac5cf4d
diff --git a/src/grammar/parser-lalr.y b/src/grammar/parser-lalr.y
index 3aa76d168df..69ba0c9098b 100644
--- a/src/grammar/parser-lalr.y
+++ b/src/grammar/parser-lalr.y
@@ -89,6 +89,7 @@ extern char *yytext;
 %token TRAIT
 %token TYPE
 %token UNSAFE
+%token DEFAULT
 %token USE
 %token WHILE
 %token CONTINUE
@@ -534,6 +535,11 @@ maybe_unsafe
 | %empty { $$ = mk_none(); }
 ;
 
+maybe_default_impl
+:         IMPL { $$ = mk_none(); }
+| DEFAULT IMPL { $$ = $1 }
+;
+
 trait_method
 : type_method { $$ = mk_node("Required", 1, $1); }
 | method      { $$ = mk_node("Provided", 1, $1); }
@@ -588,27 +594,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 IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+: maybe_unsafe maybe_default_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);
+  $$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8, $2);
 }
-| maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_unsafe maybe_default_impl generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
 {
-  $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
+  $$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10, $2);
 }
-| maybe_unsafe IMPL generic_params trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_unsafe maybe_default_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);
+  $$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10, $2);
 }
-| maybe_unsafe IMPL generic_params '!' trait_ref FOR ty_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
+| maybe_unsafe maybe_default_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);
+  $$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11, $2);
 }
-| maybe_unsafe IMPL generic_params trait_ref FOR DOTDOT '{' '}'
+| maybe_unsafe maybe_default_impl generic_params trait_ref FOR DOTDOT '{' '}'
 {
   $$ = mk_node("ItemImplDefault", 3, $1, $3, $4);
 }
-| maybe_unsafe IMPL generic_params '!' trait_ref FOR DOTDOT '{' '}'
+| maybe_unsafe maybe_default_impl generic_params '!' trait_ref FOR DOTDOT '{' '}'
 {
   $$ = mk_node("ItemImplDefaultNeg", 3, $1, $3, $4);
 }
@@ -1935,4 +1941,4 @@ brackets_delimited_token_trees
                $2,
                mk_node("TTTok", 1, mk_atom("]")));
 }
-;
+;
\ No newline at end of file
diff --git a/src/jemalloc b/src/jemalloc
-Subproject e058ca661692a8d01f8cf9d35939dfe3105ce96
+Subproject 11bfb0dcf85f7aa92abd30524bb1e42e18d108c
diff --git a/src/liblibc b/src/liblibc
-Subproject 05a2d197356ef253dfd985166576619ac9b6947
+Subproject c34a802d1eb037b44c5252078c7270b5472e0f6
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index d072340d8c8..8dda297e897 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1362,6 +1362,9 @@ 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
+        //     not cause an assertion failure inside the `lower_defaultness` function
     }
 
     fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 82e03a9fddc..3aeee1c1b98 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -933,7 +933,7 @@ impl_stable_hash_for!(enum hir::Item_ {
     ItemUnion(variant_data, generics),
     ItemTrait(unsafety, generics, bounds, item_refs),
     ItemDefaultImpl(unsafety, trait_ref),
-    ItemImpl(unsafety, impl_polarity, generics, trait_ref, ty, impl_item_refs)
+    ItemImpl(unsafety, impl_polarity, impl_defaultness, generics, trait_ref, ty, impl_item_refs)
 });
 
 impl_stable_hash_for!(struct hir::TraitItemRef {
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 3251addcb32..60171f1a428 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -195,6 +195,7 @@ pub trait CrateStore {
     fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
 
     // impl info
+    fn impl_defaultness(&self, def: DefId) -> hir::Defaultness;
     fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
 
     // trait/impl-item info
@@ -329,6 +330,7 @@ impl CrateStore for DummyCrateStore {
     fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
 
     // impl info
+    fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { bug!("impl_defaultness") }
     fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
 
     // trait/impl-item info
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index f417ad5b3d9..7675b2d00eb 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -33,7 +33,6 @@ use ty::subst::Subst;
 use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder};
 use util::common::FN_OUTPUT_NAME;
-use hir::{self};
 
 /// Depending on the stage of compilation, we want projection to be
 /// more or less conservative.
@@ -924,28 +923,8 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>(
                         // being invoked).
                         node_item.item.defaultness.has_value()
                     } else {
-                        let is_default = match selcx.tcx()
-                                                    .map
-                                                    .as_local_node_id(node_item.node.def_id()) {
-                            Some(node_id) => {
-                                let item = selcx.tcx().map.expect_item(node_id);
-                                if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
-                                    defaultness.is_default()
-                                } else {
-                                    false
-                                }
-                            }
-                            None => {
-                                selcx.tcx()
-                                     .global_tcx()
-                                     .sess
-                                     .cstore
-                                     .impl_defaultness(node_item.node.def_id())
-                                     .is_default()
-                            }
-                        };
-
-                        node_item.item.defaultness.is_default() || is_default
+                        node_item.item.defaultness.is_default() ||
+                        selcx.tcx().impl_is_default(node_item.node.def_id())
                     };
 
                     // Only reveal a specializable default if we're past type-checking
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index d4245ec9b24..4aa7950de8f 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -13,6 +13,7 @@ use ty::subst::{Subst, Substs};
 use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
 use ty::outlives::Component;
 use util::nodemap::FxHashSet;
+use hir::{self};
 
 use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
 
@@ -504,6 +505,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         };
         ty::Binder((trait_ref, sig.skip_binder().output()))
     }
+
+    pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
+        match self.hir.as_local_node_id(node_item_def_id) {
+            Some(node_id) => {
+                let item = self.hir.expect_item(node_id);
+                if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
+                    defaultness.is_default()
+                } else {
+                    false
+                }
+            }
+            None => {
+                self.global_tcx()
+                    .sess
+                    .cstore
+                    .impl_defaultness(node_item_def_id)
+                    .is_default()
+            }
+        }
+    }
 }
 
 pub enum TupleArgumentsFlag { Yes, No }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 618c1711dad..767114a37be 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -90,7 +90,6 @@ provide! { <'tcx> tcx, def_id, cdata
     associated_item => { cdata.get_associated_item(def_id.index) }
     impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
     impl_polarity => { cdata.get_impl_polarity(def_id.index) }
-    impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
     coerce_unsized_info => {
         cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
             bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
@@ -179,6 +178,12 @@ impl CrateStore for cstore::CStore {
         result
     }
 
+    fn impl_defaultness(&self, def: DefId) -> hir::Defaultness
+    {
+        self.dep_graph.read(DepNode::MetaData(def));
+        self.get_crate_data(def.krate).get_impl_defaultness(def.index)
+    }
+
     fn impl_parent(&self, impl_def: DefId) -> Option<DefId> {
         self.dep_graph.read(DepNode::MetaData(impl_def));
         self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index)
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 933c3482474..5870903e771 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -416,6 +416,7 @@ pub struct ImplData<'tcx> {
 
 impl_stable_hash_for!(struct ImplData<'tcx> {
     polarity,
+    defaultness,
     parent_impl,
     coerce_unsized_info,
     trait_ref
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 36e59b4774a..507ac1efc2c 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -429,7 +429,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                                 }
                             }
                             None => {
-                                if let Some(NodeItem(item)) = self.tcx.map.get_if_local(id) {
+                                if let Some(NodeItem(item)) = self.tcx.hir.get_if_local(id) {
                                     if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
                                         trait_id = self.lookup_def_id(ty.id);
                                     }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 74886e503a8..a00d1ad0eae 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1142,21 +1142,7 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     if let Some(parent) = parent {
         if parent.item.is_final() {
-            let is_final = match tcx.map.as_local_node_id(parent.node.def_id()) {
-                Some(node_id) => {
-                    let item = tcx.map.expect_item(node_id);
-                    if let hir::ItemImpl(_, _, defaultness, ..) = item.node {
-                        defaultness.is_final()
-                    } else {
-                        true
-                    }
-                }
-                None => {
-                    tcx.global_tcx().sess.cstore.impl_defaultness(parent.node.def_id()).is_final()
-                }
-            };
-
-            if is_final {
+            if !tcx.impl_is_default(parent.node.def_id()) {
                 report_forbidden_specialization(tcx, impl_item, parent.node.def_id());
             }
         }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 660ce837043..0203c3b6299 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -309,7 +309,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         NodeItem(item) => {
             match item.node {
                 ItemFn(.., ref generics, _) |
-                ItemImpl(_, _, ref generics, ..) |
+                ItemImpl(_, _, _, ref generics, ..) |
                 ItemTy(_, ref generics) |
                 ItemEnum(_, ref generics) |
                 ItemStruct(_, ref generics) |
@@ -825,7 +825,7 @@ fn generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         NodeItem(item) => {
             match item.node {
                 ItemFn(.., ref generics, _) |
-                ItemImpl(_, _, ref generics, ..) => generics,
+                ItemImpl(_, _, _, ref generics, ..) => generics,
 
                 ItemTy(_, ref generics) |
                 ItemEnum(_, ref generics) |
@@ -1236,7 +1236,7 @@ fn predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         NodeItem(item) => {
             match item.node {
                 ItemFn(.., ref generics, _) |
-                ItemImpl(_, _, ref generics, ..) |
+                ItemImpl(_, _, _, ref generics, ..) |
                 ItemTy(_, ref generics) |
                 ItemEnum(_, ref generics) |
                 ItemStruct(_, ref generics) |
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 58f81c8b3d7..2c10fff03db 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4918,6 +4918,14 @@ 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");
+                }
+                _ => {}
+            }
+
             self.expect(&token::OpenDelim(token::Brace))?;
             self.expect(&token::CloseDelim(token::Brace))?;
             Ok((keywords::Invalid.ident(),
@@ -5760,13 +5768,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::Default) &&
-            self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) &&
+           (self.check_keyword(keywords::Unsafe) &&
+            self.look_ahead(1, |t| t.is_keyword(keywords::Default)) &&
             self.look_ahead(2, |t| t.is_keyword(keywords::Impl)))
         {
             // IMPL ITEM
-            let defaultness = self.parse_defaultness()?;
             self.expect_keyword(keywords::Unsafe)?;
+            let defaultness = self.parse_defaultness()?;
             self.expect_keyword(keywords::Impl)?;
             let (ident,
                  item_,
diff --git a/src/rt/hoedown b/src/rt/hoedown
new file mode 160000
+Subproject da282f1bb7277b4d30fa1599ee29ad8eb4dd2a9
diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs
new file mode 100644
index 00000000000..c1746d765dd
--- /dev/null
+++ b/src/test/compile-fail/specialization/defaultimpl/specialization-no-default-trait-implementations.rs
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+#![feature(specialization)]
+#![feature(optin_builtin_traits)]
+
+trait Foo {}
+
+default impl Foo for .. {}
+//~^ ERROR `default impl` is not allowed for default trait implementations
+
+fn main() {}
diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs b/src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs
new file mode 100644
index 00000000000..9376d0db2df
--- /dev/null
+++ b/src/test/run-pass/specialization/defaultimpl/specialization-basics-unsafe.rs
@@ -0,0 +1,106 @@
+// Copyright 2014 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.
+
+#![feature(specialization)]
+
+// Tests a variety of basic specialization scenarios and method
+// dispatch for them.
+
+unsafe trait Foo {
+    fn foo(&self) -> &'static str;
+}
+
+unsafe default impl<T> Foo for T {
+    fn foo(&self) -> &'static str {
+        "generic"
+    }
+}
+
+unsafe default 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 {
+    fn foo(&self) -> &'static str {
+        "generic pair"
+    }
+}
+
+unsafe default impl<T: Clone> Foo for (T, T) {
+    fn foo(&self) -> &'static str {
+        "generic uniform pair"
+    }
+}
+
+unsafe default impl Foo for (u8, u32) {
+    fn foo(&self) -> &'static str {
+        "(u8, u32)"
+    }
+}
+
+unsafe default impl Foo for (u8, u8) {
+    fn foo(&self) -> &'static str {
+        "(u8, u8)"
+    }
+}
+
+unsafe default impl<T: Clone> Foo for Vec<T> {
+    fn foo(&self) -> &'static str {
+        "generic Vec"
+    }
+}
+
+unsafe impl Foo for Vec<i32> {
+    fn foo(&self) -> &'static str {
+        "Vec<i32>"
+    }
+}
+
+unsafe impl Foo for String {
+    fn foo(&self) -> &'static str {
+        "String"
+    }
+}
+
+unsafe impl Foo for i32 {
+    fn foo(&self) -> &'static str {
+        "i32"
+    }
+}
+
+struct NotClone;
+
+unsafe trait MyMarker {}
+unsafe default impl<T: Clone + MyMarker> Foo for T {
+    fn foo(&self) -> &'static str {
+        "generic Clone + MyMarker"
+    }
+}
+
+#[derive(Clone)]
+struct MarkedAndClone;
+unsafe impl MyMarker for MarkedAndClone {}
+
+fn  main() {
+    assert!(NotClone.foo() == "generic");
+    assert!(0u8.foo() == "generic Clone");
+    assert!(vec![NotClone].foo() == "generic");
+    assert!(vec![0u8].foo() == "generic Vec");
+    assert!(vec![0i32].foo() == "Vec<i32>");
+    assert!(0i32.foo() == "i32");
+    assert!(String::new().foo() == "String");
+    assert!(((), 0).foo() == "generic pair");
+    assert!(((), ()).foo() == "generic uniform pair");
+    assert!((0u8, 0u32).foo() == "(u8, u32)");
+    assert!((0u8, 0u8).foo() == "(u8, u8)");
+    assert!(MarkedAndClone.foo() == "generic Clone + MyMarker");
+}