diff options
| author | bors <bors@rust-lang.org> | 2016-08-16 00:12:12 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-08-16 00:12:12 -0700 |
| commit | e25542cb02d946959517ebb68e2f7b1318817237 (patch) | |
| tree | 64775f55741e98f44e5e2ee854e6707e2f4b4da9 /src/libsyntax | |
| parent | 197be89f367d1240d5f9cd9c4efd77812775354e (diff) | |
| parent | f59f1f0914de50ffa70e3000c317a14f6d1b8605 (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.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 6 |
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) { |
