about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-08-16 00:12:12 -0700
committerGitHub <noreply@github.com>2016-08-16 00:12:12 -0700
commite25542cb02d946959517ebb68e2f7b1318817237 (patch)
tree64775f55741e98f44e5e2ee854e6707e2f4b4da9 /src/libsyntax
parent197be89f367d1240d5f9cd9c4efd77812775354e (diff)
parentf59f1f0914de50ffa70e3000c317a14f6d1b8605 (diff)
Auto merge of #35162 - canndrew:bang_type_coerced, r=nikomatsakis
Implement the `!` type

This implements the never type (`!`) and hides it behind the feature gate `#[feature(never_type)]`. With the feature gate off, things should build as normal (although some error messages may be different). With the gate on, `!` is usable as a type and diverging type variables (ie. types that are unconstrained by anything in the code) will default to `!` instead of `()`.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs7
-rw-r--r--src/libsyntax/feature_gate.rs19
-rw-r--r--src/libsyntax/fold.rs2
-rw-r--r--src/libsyntax/parse/parser.rs8
-rw-r--r--src/libsyntax/print/pprust.rs9
-rw-r--r--src/libsyntax/visit.rs6
6 files changed, 33 insertions, 18 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 3f929e6d23a..f8a5cb0b04a 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1348,6 +1348,7 @@ pub struct BareFnTy {
 /// The different kinds of types recognized by the compiler
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum TyKind {
+    /// A variable-length array (`[T]`)
     Vec(P<Ty>),
     /// A fixed length array (`[T; n]`)
     FixedLengthVec(P<Ty>, P<Expr>),
@@ -1357,6 +1358,8 @@ pub enum TyKind {
     Rptr(Option<Lifetime>, MutTy),
     /// A bare function (e.g. `fn(usize) -> bool`)
     BareFn(P<BareFnTy>),
+    /// The never type (`!`)
+    Never,
     /// A tuple (`(A, B, C, D,...)`)
     Tup(Vec<P<Ty>> ),
     /// A path (`module::module::...::Type`), optionally
@@ -1564,9 +1567,6 @@ impl fmt::Debug for ImplPolarity {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum FunctionRetTy {
-    /// Functions with return type `!`that always
-    /// raise an error or exit (i.e. never return to the caller)
-    None(Span),
     /// Return type is not specified.
     ///
     /// Functions default to `()` and
@@ -1580,7 +1580,6 @@ pub enum FunctionRetTy {
 impl FunctionRetTy {
     pub fn span(&self) -> Span {
         match *self {
-            FunctionRetTy::None(span) => span,
             FunctionRetTy::Default(span) => span,
             FunctionRetTy::Ty(ref ty) => ty.span,
         }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index a6f0e0ca31e..d94bfe7dcbd 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -284,7 +284,10 @@ declare_features! (
 
     // Allows tuple structs and variants in more contexts,
     // Permits numeric fields in struct expressions and patterns.
-    (active, relaxed_adts, "1.12.0", Some(35626))
+    (active, relaxed_adts, "1.12.0", Some(35626)),
+
+    // The `!` type
+    (active, never_type, "1.13.0", Some(35121))
 );
 
 declare_features! (
@@ -963,11 +966,25 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, conservative_impl_trait, ty.span,
                                    "`impl Trait` is experimental");
             }
+            ast::TyKind::Never => {
+                gate_feature_post!(&self, never_type, ty.span,
+                                   "The `!` type is experimental");
+            },
             _ => {}
         }
         visit::walk_ty(self, ty)
     }
 
+    fn visit_fn_ret_ty(&mut self, ret_ty: &ast::FunctionRetTy) {
+        if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
+            match output_ty.node {
+                ast::TyKind::Never => return,
+                _ => (),
+            };
+            self.visit_ty(output_ty)
+        }
+    }
+
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
             ast::ExprKind::Box(_) => {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index afc990f498e..b257ab98987 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -373,6 +373,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
                     decl: fld.fold_fn_decl(decl)
                 }))
             }
+            TyKind::Never => node,
             TyKind::Tup(tys) => TyKind::Tup(tys.move_map(|ty| fld.fold_ty(ty))),
             TyKind::Paren(ty) => TyKind::Paren(fld.fold_ty(ty)),
             TyKind::Path(qself, path) => {
@@ -637,7 +638,6 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
         output: match output {
             FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(fld.fold_ty(ty)),
             FunctionRetTy::Default(span) => FunctionRetTy::Default(span),
-            FunctionRetTy::None(span) => FunctionRetTy::None(span),
         },
         variadic: variadic
     })
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e174f3ad08d..126e8816d05 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1332,11 +1332,7 @@ impl<'a> Parser<'a> {
     /// Parse optional return type [ -> TY ] in function decl
     pub fn parse_ret_ty(&mut self) -> PResult<'a, FunctionRetTy> {
         if self.eat(&token::RArrow) {
-            if self.eat(&token::Not) {
-                Ok(FunctionRetTy::None(self.last_span))
-            } else {
-                Ok(FunctionRetTy::Ty(self.parse_ty()?))
-            }
+            Ok(FunctionRetTy::Ty(self.parse_ty()?))
         } else {
             let pos = self.span.lo;
             Ok(FunctionRetTy::Default(mk_sp(pos, pos)))
@@ -1399,6 +1395,8 @@ impl<'a> Parser<'a> {
             } else {
                 TyKind::Tup(ts)
             }
+        } else if self.eat(&token::Not) {
+            TyKind::Never
         } else if self.check(&token::BinOp(token::Star)) {
             // STAR POINTER (bare pointer?)
             self.bump();
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 62e55eb78b7..a77c678248b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -976,6 +976,9 @@ impl<'a> State<'a> {
                 try!(self.print_opt_lifetime(lifetime));
                 try!(self.print_mt(mt));
             }
+            ast::TyKind::Never => {
+                try!(word(&mut self.s, "!"));
+            },
             ast::TyKind::Tup(ref elts) => {
                 try!(self.popen());
                 try!(self.commasep(Inconsistent, &elts[..],
@@ -2693,10 +2696,6 @@ impl<'a> State<'a> {
                 self.maybe_print_comment(ty.span.lo)
             }
             ast::FunctionRetTy::Default(..) => unreachable!(),
-            ast::FunctionRetTy::None(span) => {
-                try!(self.word_nbsp("!"));
-                self.maybe_print_comment(span.lo)
-            }
         }
     }
 
@@ -2952,8 +2951,6 @@ impl<'a> State<'a> {
         try!(self.ibox(INDENT_UNIT));
         try!(self.word_space("->"));
         match decl.output {
-            ast::FunctionRetTy::None(_) =>
-                try!(self.word_nbsp("!")),
             ast::FunctionRetTy::Default(..) => unreachable!(),
             ast::FunctionRetTy::Ty(ref ty) =>
                 try!(self.print_type(&ty))
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 6d3cdbdc6da..582412119ca 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -128,6 +128,9 @@ pub trait Visitor: Sized {
     fn visit_vis(&mut self, vis: &Visibility) {
         walk_vis(self, vis)
     }
+    fn visit_fn_ret_ty(&mut self, ret_ty: &FunctionRetTy) {
+        walk_fn_ret_ty(self, ret_ty)
+    }
 }
 
 #[macro_export]
@@ -319,6 +322,7 @@ pub fn walk_ty<V: Visitor>(visitor: &mut V, typ: &Ty) {
             walk_list!(visitor, visit_lifetime, opt_lifetime);
             visitor.visit_ty(&mutable_type.ty)
         }
+        TyKind::Never => {},
         TyKind::Tup(ref tuple_element_types) => {
             walk_list!(visitor, visit_ty, tuple_element_types);
         }
@@ -509,7 +513,7 @@ pub fn walk_fn_decl<V: Visitor>(visitor: &mut V, function_declaration: &FnDecl)
         visitor.visit_pat(&argument.pat);
         visitor.visit_ty(&argument.ty)
     }
-    walk_fn_ret_ty(visitor, &function_declaration.output)
+    visitor.visit_fn_ret_ty(&function_declaration.output)
 }
 
 pub fn walk_fn_kind<V: Visitor>(visitor: &mut V, function_kind: FnKind) {