Rename empty/bang to never

Split Ty::is_empty method into is_never and is_uninhabited
This commit is contained in:
Andrew Cann 2016-08-02 15:56:20 +08:00
parent f0a8b6d43f
commit fadabe08f5
76 changed files with 161 additions and 150 deletions

View file

@ -703,24 +703,24 @@ mod impls {
// that supports `!` // that supports `!`
macro_rules! not_stage0 { macro_rules! not_stage0 {
() => { () => {
#[unstable(feature = "bang_type", issue = "35121")] #[unstable(feature = "never_type", issue = "35121")]
impl PartialEq for ! { impl PartialEq for ! {
fn eq(&self, _: &!) -> bool { fn eq(&self, _: &!) -> bool {
*self *self
} }
} }
#[unstable(feature = "bang_type", issue = "35121")] #[unstable(feature = "never_type", issue = "35121")]
impl Eq for ! {} impl Eq for ! {}
#[unstable(feature = "bang_type", issue = "35121")] #[unstable(feature = "never_type", issue = "35121")]
impl PartialOrd for ! { impl PartialOrd for ! {
fn partial_cmp(&self, _: &!) -> Option<Ordering> { fn partial_cmp(&self, _: &!) -> Option<Ordering> {
*self *self
} }
} }
#[unstable(feature = "bang_type", issue = "35121")] #[unstable(feature = "never_type", issue = "35121")]
impl Ord for ! { impl Ord for ! {
fn cmp(&self, _: &!) -> Ordering { fn cmp(&self, _: &!) -> Ordering {
*self *self

View file

@ -1367,14 +1367,14 @@ fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperEx
// that supports `!` // that supports `!`
macro_rules! not_stage0 { macro_rules! not_stage0 {
() => { () => {
#[unstable(feature = "bang_type", issue = "35121")] #[unstable(feature = "never_type", issue = "35121")]
impl Debug for ! { impl Debug for ! {
fn fmt(&self, _: &mut Formatter) -> Result { fn fmt(&self, _: &mut Formatter) -> Result {
*self *self
} }
} }
#[unstable(feature = "bang_type", issue = "35121")] #[unstable(feature = "never_type", issue = "35121")]
impl Display for ! { impl Display for ! {
fn fmt(&self, _: &mut Formatter) -> Result { fn fmt(&self, _: &mut Formatter) -> Result {
*self *self

View file

@ -89,7 +89,7 @@
#![feature(question_mark)] #![feature(question_mark)]
// NOTE: remove the cfg_attr next snapshot // NOTE: remove the cfg_attr next snapshot
#![cfg_attr(not(stage0), feature(bang_type))] #![cfg_attr(not(stage0), feature(never_type))]
#[macro_use] #[macro_use]
mod macros; mod macros;

View file

@ -379,7 +379,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
let ret = self.straightline(call_expr, func_or_rcvr_exit, args); let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
if fn_ty.fn_ret().0.is_empty(self.tcx) { // FIXME(canndrew): This is_never should probably be an is_uninhabited.
if fn_ty.fn_ret().0.is_never() {
self.add_unreachable_node() self.add_unreachable_node()
} else { } else {
ret ret

View file

@ -353,7 +353,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
} }
})) }))
} }
TyEmpty => node, TyNever => node,
TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
TyPath(qself, path) => { TyPath(qself, path) => {
let qself = qself.map(|QSelf { ty, position }| { let qself = qself.map(|QSelf { ty, position }| {

View file

@ -403,7 +403,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
walk_list!(visitor, visit_lifetime, opt_lifetime); walk_list!(visitor, visit_lifetime, opt_lifetime);
visitor.visit_ty(&mutable_type.ty) visitor.visit_ty(&mutable_type.ty)
} }
TyEmpty => {}, TyNever => {},
TyTup(ref tuple_element_types) => { TyTup(ref tuple_element_types) => {
walk_list!(visitor, visit_ty, tuple_element_types); walk_list!(visitor, visit_ty, tuple_element_types);
} }

View file

@ -270,7 +270,7 @@ impl<'a> LoweringContext<'a> {
decl: self.lower_fn_decl(&f.decl), decl: self.lower_fn_decl(&f.decl),
})) }))
} }
Empty => hir::TyEmpty, Never => hir::TyNever,
Tup(ref tys) => hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect()), Tup(ref tys) => hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect()),
Paren(ref ty) => { Paren(ref ty) => {
return self.lower_ty(ty); return self.lower_ty(ty);

View file

@ -1122,8 +1122,8 @@ pub enum Ty_ {
TyRptr(Option<Lifetime>, MutTy), TyRptr(Option<Lifetime>, MutTy),
/// A bare function (e.g. `fn(usize) -> bool`) /// A bare function (e.g. `fn(usize) -> bool`)
TyBareFn(P<BareFnTy>), TyBareFn(P<BareFnTy>),
/// The empty type (`!`) /// The never type (`!`)
TyEmpty, TyNever,
/// A tuple (`(A, B, C, D,...)`) /// A tuple (`(A, B, C, D,...)`)
TyTup(HirVec<P<Ty>>), TyTup(HirVec<P<Ty>>),
/// A path (`module::module::...::Type`), optionally /// A path (`module::module::...::Type`), optionally

View file

@ -504,7 +504,7 @@ impl<'a> State<'a> {
self.print_opt_lifetime(lifetime)?; self.print_opt_lifetime(lifetime)?;
self.print_mt(mt)?; self.print_mt(mt)?;
} }
hir::TyEmpty => { hir::TyNever => {
word(&mut self.s, "!")?; word(&mut self.s, "!")?;
}, },
hir::TyTup(ref elts) => { hir::TyTup(ref elts) => {

View file

@ -168,7 +168,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::TyTrait(..) | ty::TyTrait(..) |
ty::TyStruct(..) | ty::TyStruct(..) |
ty::TyClosure(..) | ty::TyClosure(..) |
ty::TyEmpty | ty::TyNever |
ty::TyTuple(..) | ty::TyTuple(..) |
ty::TyProjection(..) | ty::TyProjection(..) |
ty::TyParam(..) | ty::TyParam(..) |

View file

@ -717,7 +717,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone()); let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone());
if let Some(adjustment) = adj { if let Some(adjustment) = adj {
match adjustment { match adjustment {
adjustment::AdjustEmptyToAny(..) | adjustment::AdjustNeverToAny(..) |
adjustment::AdjustReifyFnPointer | adjustment::AdjustReifyFnPointer |
adjustment::AdjustUnsafeFnPointer | adjustment::AdjustUnsafeFnPointer |
adjustment::AdjustMutToConstPointer => { adjustment::AdjustMutToConstPointer => {

View file

@ -1111,8 +1111,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
} }
hir::ExprCall(ref f, ref args) => { hir::ExprCall(ref f, ref args) => {
// FIXME(canndrew): This is_never should really be an is_uninhabited
let diverges = !self.ir.tcx.is_method_call(expr.id) && let diverges = !self.ir.tcx.is_method_call(expr.id) &&
self.ir.tcx.expr_ty_adjusted(&f).fn_ret().0.is_empty(self.ir.tcx); self.ir.tcx.expr_ty_adjusted(&f).fn_ret().0.is_never();
let succ = if diverges { let succ = if diverges {
self.s.exit_ln self.s.exit_ln
} else { } else {
@ -1125,7 +1126,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprMethodCall(_, _, ref args) => { hir::ExprMethodCall(_, _, ref args) => {
let method_call = ty::MethodCall::expr(expr.id); let method_call = ty::MethodCall::expr(expr.id);
let method_ty = self.ir.tcx.tables.borrow().method_map[&method_call].ty; let method_ty = self.ir.tcx.tables.borrow().method_map[&method_call].ty;
let succ = if method_ty.fn_ret().0.is_empty(self.ir.tcx) { // FIXME(canndrew): This is_never should really be an is_uninhabited
let succ = if method_ty.fn_ret().0.is_never() {
self.s.exit_ln self.s.exit_ln
} else { } else {
succ succ

View file

@ -451,7 +451,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
self.cat_expr_autoderefd(expr, autoderefs) self.cat_expr_autoderefd(expr, autoderefs)
} }
adjustment::AdjustEmptyToAny(..) | adjustment::AdjustNeverToAny(..) |
adjustment::AdjustReifyFnPointer | adjustment::AdjustReifyFnPointer |
adjustment::AdjustUnsafeFnPointer | adjustment::AdjustUnsafeFnPointer |
adjustment::AdjustMutToConstPointer | adjustment::AdjustMutToConstPointer |

View file

@ -253,7 +253,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
ty::TySlice(..) | ty::TySlice(..) |
ty::TyRawPtr(..) | ty::TyRawPtr(..) |
ty::TyRef(..) | ty::TyRef(..) |
ty::TyEmpty | ty::TyNever |
ty::TyTuple(..) | ty::TyTuple(..) |
ty::TyParam(..) | ty::TyParam(..) |
ty::TyProjection(..) => { ty::TyProjection(..) => {

View file

@ -212,7 +212,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyProjection(..) => Some(13), ty::TyProjection(..) => Some(13),
ty::TyParam(..) => Some(14), ty::TyParam(..) => Some(14),
ty::TyAnon(..) => Some(15), ty::TyAnon(..) => Some(15),
ty::TyEmpty => Some(16), ty::TyNever => Some(16),
ty::TyInfer(..) | ty::TyError => None ty::TyInfer(..) | ty::TyError => None
} }
} }

View file

@ -1772,7 +1772,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
ty::TyChar | ty::TyBox(_) | ty::TyRef(..) | ty::TyChar | ty::TyBox(_) | ty::TyRef(..) |
ty::TyArray(..) | ty::TyClosure(..) | ty::TyEmpty | ty::TyArray(..) | ty::TyClosure(..) | ty::TyNever |
ty::TyError => { ty::TyError => {
// safe for everything // safe for everything
Where(ty::Binder(Vec::new())) Where(ty::Binder(Vec::new()))
@ -1820,7 +1820,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar | ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
ty::TyRawPtr(..) | ty::TyError | ty::TyEmpty | ty::TyRawPtr(..) | ty::TyError | ty::TyNever |
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
Where(ty::Binder(Vec::new())) Where(ty::Binder(Vec::new()))
} }
@ -1886,7 +1886,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ty::TyError | ty::TyError |
ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::IntVar(_)) |
ty::TyInfer(ty::FloatVar(_)) | ty::TyInfer(ty::FloatVar(_)) |
ty::TyEmpty | ty::TyNever |
ty::TyChar => { ty::TyChar => {
Vec::new() Vec::new()
} }

View file

@ -11,7 +11,7 @@
pub use self::AutoAdjustment::*; pub use self::AutoAdjustment::*;
pub use self::AutoRef::*; pub use self::AutoRef::*;
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeVariants}; use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFoldable};
use ty::LvaluePreference::{NoPreference}; use ty::LvaluePreference::{NoPreference};
use syntax::ast; use syntax::ast;
@ -21,7 +21,7 @@ use hir;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum AutoAdjustment<'tcx> { pub enum AutoAdjustment<'tcx> {
AdjustEmptyToAny(Ty<'tcx>), // go from ! to any type AdjustNeverToAny(Ty<'tcx>), // go from ! to any type
AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type
AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer
AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer
@ -107,10 +107,7 @@ pub struct AutoDerefRef<'tcx> {
impl<'tcx> AutoAdjustment<'tcx> { impl<'tcx> AutoAdjustment<'tcx> {
pub fn is_identity(&self) -> bool { pub fn is_identity(&self) -> bool {
match *self { match *self {
AdjustEmptyToAny(ty) => match ty.sty { AdjustNeverToAny(ty) => ty.is_never(),
TypeVariants::TyEmpty => true,
_ => false,
},
AdjustReifyFnPointer | AdjustReifyFnPointer |
AdjustUnsafeFnPointer | AdjustUnsafeFnPointer |
AdjustMutToConstPointer => false, AdjustMutToConstPointer => false,
@ -159,7 +156,7 @@ impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> {
return match adjustment { return match adjustment {
Some(adjustment) => { Some(adjustment) => {
match *adjustment { match *adjustment {
AdjustEmptyToAny(ref ty) => ty, AdjustNeverToAny(ref ty) => ty,
AdjustReifyFnPointer => { AdjustReifyFnPointer => {
match self.sty { match self.sty {

View file

@ -185,7 +185,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
// Scalar and unique types are sendable, and durable // Scalar and unique types are sendable, and durable
ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) | ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyEmpty | ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar => { ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar => {
TC::None TC::None
} }

View file

@ -190,7 +190,7 @@ pub struct CommonTypes<'tcx> {
pub u64: Ty<'tcx>, pub u64: Ty<'tcx>,
pub f32: Ty<'tcx>, pub f32: Ty<'tcx>,
pub f64: Ty<'tcx>, pub f64: Ty<'tcx>,
pub empty: Ty<'tcx>, pub never: Ty<'tcx>,
pub err: Ty<'tcx>, pub err: Ty<'tcx>,
} }
@ -257,7 +257,7 @@ impl<'tcx> CommonTypes<'tcx> {
CommonTypes { CommonTypes {
bool: mk(TyBool), bool: mk(TyBool),
char: mk(TyChar), char: mk(TyChar),
empty: mk(TyEmpty), never: mk(TyNever),
err: mk(TyError), err: mk(TyError),
isize: mk(TyInt(ast::IntTy::Is)), isize: mk(TyInt(ast::IntTy::Is)),
i8: mk(TyInt(ast::IntTy::I8)), i8: mk(TyInt(ast::IntTy::I8)),
@ -977,7 +977,7 @@ macro_rules! sty_debug_print {
for &Interned(t) in tcx.interners.type_.borrow().iter() { for &Interned(t) in tcx.interners.type_.borrow().iter() {
let variant = match t.sty { let variant = match t.sty {
ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
ty::TyFloat(..) | ty::TyStr | ty::TyEmpty => continue, ty::TyFloat(..) | ty::TyStr | ty::TyNever => continue,
ty::TyError => /* unimportant */ continue, ty::TyError => /* unimportant */ continue,
$(ty::$variant(..) => &mut $variant,)* $(ty::$variant(..) => &mut $variant,)*
}; };

View file

@ -214,7 +214,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String { fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
match self.sty { match self.sty {
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyBool | ty::TyChar | ty::TyInt(_) |
ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyEmpty => self.to_string(), ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr | ty::TyNever => self.to_string(),
ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(), ty::TyTuple(ref tys) if tys.is_empty() => self.to_string(),
ty::TyEnum(def, _) => format!("enum `{}`", tcx.item_path_str(def.did)), ty::TyEnum(def, _) => format!("enum `{}`", tcx.item_path_str(def.did)),

View file

@ -26,7 +26,7 @@ pub enum SimplifiedType {
StrSimplifiedType, StrSimplifiedType,
VecSimplifiedType, VecSimplifiedType,
PtrSimplifiedType, PtrSimplifiedType,
EmptySimplifiedType, NeverSimplifiedType,
TupleSimplifiedType(usize), TupleSimplifiedType(usize),
TraitSimplifiedType(DefId), TraitSimplifiedType(DefId),
StructSimplifiedType(DefId), StructSimplifiedType(DefId),
@ -82,7 +82,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
ty::TyClosure(def_id, _) => { ty::TyClosure(def_id, _) => {
Some(ClosureSimplifiedType(def_id)) Some(ClosureSimplifiedType(def_id))
} }
ty::TyEmpty => Some(EmptySimplifiedType), ty::TyNever => Some(NeverSimplifiedType),
ty::TyTuple(ref tys) => { ty::TyTuple(ref tys) => {
Some(TupleSimplifiedType(tys.len())) Some(TupleSimplifiedType(tys.len()))
} }

View file

@ -60,7 +60,7 @@ impl FlagComputation {
&ty::TyInt(_) | &ty::TyInt(_) |
&ty::TyFloat(_) | &ty::TyFloat(_) |
&ty::TyUint(_) | &ty::TyUint(_) |
&ty::TyEmpty | &ty::TyNever |
&ty::TyStr => { &ty::TyStr => {
} }

View file

@ -349,7 +349,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
ty::TyAnon(..) | ty::TyAnon(..) |
ty::TyInfer(_) | ty::TyInfer(_) |
ty::TyError | ty::TyError |
ty::TyEmpty | ty::TyNever |
ty::TyFloat(_) => None, ty::TyFloat(_) => None,
} }
} }

View file

@ -795,8 +795,8 @@ impl<'a, 'gcx, 'tcx> Layout {
ty::TyFloat(FloatTy::F64) => Scalar { value: F64, non_zero: false }, ty::TyFloat(FloatTy::F64) => Scalar { value: F64, non_zero: false },
ty::TyFnPtr(_) => Scalar { value: Pointer, non_zero: true }, ty::TyFnPtr(_) => Scalar { value: Pointer, non_zero: true },
// The empty type. // The never type.
ty::TyEmpty => Univariant { variant: Struct::new(dl, false), non_zero: false }, ty::TyNever => Univariant { variant: Struct::new(dl, false), non_zero: false },
// Potentially-fat pointers. // Potentially-fat pointers.
ty::TyBox(pointee) | ty::TyBox(pointee) |

View file

@ -1853,7 +1853,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
let result = match ty.sty { let result = match ty.sty {
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
TyArray(..) | TyClosure(..) | TyEmpty => { TyArray(..) | TyClosure(..) | TyNever => {
vec![] vec![]
} }

View file

@ -171,7 +171,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyInt(..) | // OutlivesScalar ty::TyInt(..) | // OutlivesScalar
ty::TyUint(..) | // OutlivesScalar ty::TyUint(..) | // OutlivesScalar
ty::TyFloat(..) | // OutlivesScalar ty::TyFloat(..) | // OutlivesScalar
ty::TyEmpty | // ... ty::TyNever | // ...
ty::TyEnum(..) | // OutlivesNominalType ty::TyEnum(..) | // OutlivesNominalType
ty::TyStruct(..) | // OutlivesNominalType ty::TyStruct(..) | // OutlivesNominalType
ty::TyBox(..) | // OutlivesNominalType (ish) ty::TyBox(..) | // OutlivesNominalType (ish)

View file

@ -453,7 +453,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
Ok(tcx.types.err) Ok(tcx.types.err)
} }
(&ty::TyEmpty, _) | (&ty::TyNever, _) |
(&ty::TyChar, _) | (&ty::TyChar, _) |
(&ty::TyBool, _) | (&ty::TyBool, _) |
(&ty::TyInt(_), _) | (&ty::TyInt(_), _) |

View file

@ -486,7 +486,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)), ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)),
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) | ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
ty::TyParam(..) | ty::TyEmpty => self.sty.clone(), ty::TyParam(..) | ty::TyNever => self.sty.clone(),
}; };
folder.tcx().mk_ty(sty) folder.tcx().mk_ty(sty)
} }
@ -515,7 +515,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyAnon(_, ref substs) => substs.visit_with(visitor), ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) | ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
ty::TyParam(..) | ty::TyEmpty => false, ty::TyParam(..) | ty::TyNever => false,
} }
} }

View file

@ -158,8 +158,8 @@ pub enum TypeVariants<'tcx> {
/// `|a| a`. /// `|a| a`.
TyClosure(DefId, ClosureSubsts<'tcx>), TyClosure(DefId, ClosureSubsts<'tcx>),
/// The empty type `!` /// The never type `!`
TyEmpty, TyNever,
/// A tuple type. For example, `(i32, bool)`. /// A tuple type. For example, `(i32, bool)`.
TyTuple(&'tcx [Ty<'tcx>]), TyTuple(&'tcx [Ty<'tcx>]),
@ -894,14 +894,22 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
} }
} }
pub fn is_empty(&self, cx: TyCtxt) -> bool { pub fn is_never(&self) -> bool {
// FIXME(#24885): be smarter here match self.sty {
TyNever => true,
_ => false,
}
}
pub fn is_uninhabited(&self, cx: TyCtxt) -> bool {
// FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made
// more complete.
match self.sty { match self.sty {
TyEnum(def, _) | TyStruct(def, _) => def.is_empty(), TyEnum(def, _) | TyStruct(def, _) => def.is_empty(),
TyEmpty => true, TyNever => true,
TyTuple(ref tys) => tys.iter().any(|ty| ty.is_empty(cx)), TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited(cx)),
// FIXME (canndrew): this line breaks core::fmt // FIXME (canndrew): this line breaks core::fmt
//TyRef(_, ref tm) => tm.ty.is_empty(cx), //TyRef(_, ref tm) => tm.ty.is_uninhabited(cx),
_ => false, _ => false,
} }
} }
@ -1225,7 +1233,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
TyArray(_, _) | TyArray(_, _) |
TySlice(_) | TySlice(_) |
TyRawPtr(_) | TyRawPtr(_) |
TyEmpty | TyNever |
TyTuple(_) | TyTuple(_) |
TyParam(_) | TyParam(_) |
TyInfer(_) | TyInfer(_) |

View file

@ -485,7 +485,7 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> {
self.def_id(data.trait_ref.def_id); self.def_id(data.trait_ref.def_id);
self.hash(data.item_name.as_str()); self.hash(data.item_name.as_str());
} }
TyEmpty | TyNever |
TyBool | TyBool |
TyChar | TyChar |
TyStr | TyStr |
@ -551,7 +551,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
// Fast-path for primitive types // Fast-path for primitive types
let result = match self.sty { let result = match self.sty {
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyEmpty | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyNever |
TyRawPtr(..) | TyFnDef(..) | TyFnPtr(_) | TyRef(_, TypeAndMut { TyRawPtr(..) | TyFnDef(..) | TyFnPtr(_) | TyRef(_, TypeAndMut {
mutbl: hir::MutImmutable, .. mutbl: hir::MutImmutable, ..
}) => Some(false), }) => Some(false),
@ -597,7 +597,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
let result = match self.sty { let result = match self.sty {
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
TyArray(..) | TyTuple(..) | TyClosure(..) | TyEmpty => Some(true), TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
TyStr | TyTrait(..) | TySlice(_) => Some(false), TyStr | TyTrait(..) | TySlice(_) => Some(false),

View file

@ -70,7 +70,7 @@ pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> {
fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) { fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
match parent_ty.sty { match parent_ty.sty {
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyEmpty | ty::TyError => { ty::TyStr | ty::TyInfer(_) | ty::TyParam(_) | ty::TyNever | ty::TyError => {
} }
ty::TyBox(ty) | ty::TyArray(ty, _) | ty::TySlice(ty) => { ty::TyBox(ty) | ty::TyArray(ty, _) | ty::TySlice(ty) => {
stack.push(ty); stack.push(ty);

View file

@ -321,7 +321,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
ty::TyFloat(..) | ty::TyFloat(..) |
ty::TyError | ty::TyError |
ty::TyStr | ty::TyStr |
ty::TyEmpty | ty::TyNever |
ty::TyParam(_) => { ty::TyParam(_) => {
// WfScalar, WfParameter, etc // WfScalar, WfParameter, etc
} }

View file

@ -14,7 +14,7 @@ use ty::subst::{self, Subst};
use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
use ty::{TyBool, TyChar, TyStruct, TyEnum}; use ty::{TyBool, TyChar, TyStruct, TyEnum};
use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
use ty::{TyParam, TyRawPtr, TyRef, TyEmpty, TyTuple}; use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
use ty::TyClosure; use ty::TyClosure;
use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer}; use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::{self, Ty, TyCtxt, TypeFoldable};
@ -422,8 +422,8 @@ impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> {
impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> { impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
ty::adjustment::AdjustEmptyToAny(ref target) => { ty::adjustment::AdjustNeverToAny(ref target) => {
write!(f, "AdjustEmptyToAny({:?})", target) write!(f, "AdjustNeverToAny({:?})", target)
} }
ty::adjustment::AdjustReifyFnPointer => { ty::adjustment::AdjustReifyFnPointer => {
write!(f, "AdjustReifyFnPointer") write!(f, "AdjustReifyFnPointer")
@ -843,7 +843,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
} }
write!(f, "{}", tm) write!(f, "{}", tm)
} }
TyEmpty => write!(f, "!"), TyNever => write!(f, "!"),
TyTuple(ref tys) => { TyTuple(ref tys) => {
write!(f, "(")?; write!(f, "(")?;
let mut tys = tys.iter(); let mut tys = tys.iter();

View file

@ -215,17 +215,17 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
// Check for empty enum, because is_useful only works on inhabited types. // Check for empty enum, because is_useful only works on inhabited types.
let pat_ty = cx.tcx.node_id_to_type(scrut.id); let pat_ty = cx.tcx.node_id_to_type(scrut.id);
if inlined_arms.is_empty() { if inlined_arms.is_empty() {
if !pat_ty.is_empty(cx.tcx) { if !pat_ty.is_uninhabited(cx.tcx) {
// We know the type is inhabited, so this must be wrong // We know the type is inhabited, so this must be wrong
let mut err = struct_span_err!(cx.tcx.sess, ex.span, E0002, let mut err = struct_span_err!(cx.tcx.sess, ex.span, E0002,
"non-exhaustive patterns: type {} is non-empty", "non-exhaustive patterns: type {} is inhabited",
pat_ty); pat_ty);
span_help!(&mut err, ex.span, span_help!(&mut err, ex.span,
"Please ensure that all possible cases are being handled; \ "Please ensure that all possible cases are being handled; \
possibly adding wildcards or more match arms."); possibly adding wildcards or more match arms.");
err.emit(); err.emit();
} }
// If the type *is* empty, it's vacuously exhaustive // If the type *is* uninhabited, it's vacuously exhaustive
return; return;
} }

View file

@ -523,7 +523,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
// Primitive types with a stable representation. // Primitive types with a stable representation.
ty::TyBool | ty::TyInt(..) | ty::TyUint(..) | ty::TyBool | ty::TyInt(..) | ty::TyUint(..) |
ty::TyFloat(..) | ty::TyEmpty => FfiSafe, ty::TyFloat(..) | ty::TyNever => FfiSafe,
ty::TyBox(..) => { ty::TyBox(..) => {
FfiUnsafe("found Rust type Box<_> in foreign module, \ FfiUnsafe("found Rust type Box<_> in foreign module, \

View file

@ -133,7 +133,7 @@ impl LateLintPass for UnusedResults {
let t = cx.tcx.expr_ty(&expr); let t = cx.tcx.expr_ty(&expr);
let warned = match t.sty { let warned = match t.sty {
ty::TyTuple(ref tys) if tys.is_empty() => return, ty::TyTuple(ref tys) if tys.is_empty() => return,
ty::TyEmpty => return, ty::TyNever => return,
ty::TyBool => return, ty::TyBool => return,
ty::TyStruct(def, _) | ty::TyStruct(def, _) |
ty::TyEnum(def, _) => { ty::TyEnum(def, _) => {

View file

@ -645,8 +645,8 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
}) })
} }
adjustment::AdjustEmptyToAny(ref ty) => { adjustment::AdjustNeverToAny(ref ty) => {
this.emit_enum_variant("AdjustEmptyToAny", 5, 1, |this| { this.emit_enum_variant("AdjustNeverToAny", 5, 1, |this| {
this.emit_enum_variant_arg(0, |this| Ok(this.emit_ty(ecx, ty))) this.emit_enum_variant_arg(0, |this| Ok(this.emit_ty(ecx, ty)))
}) })
} }
@ -1024,7 +1024,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
self.read_enum("AutoAdjustment", |this| { self.read_enum("AutoAdjustment", |this| {
let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer", let variants = ["AdjustReifyFnPointer", "AdjustUnsafeFnPointer",
"AdjustMutToConstPointer", "AdjustDerefRef", "AdjustMutToConstPointer", "AdjustDerefRef",
"AdjustEmptyToAny"]; "AdjustNeverToAny"];
this.read_enum_variant(&variants, |this, i| { this.read_enum_variant(&variants, |this, i| {
Ok(match i { Ok(match i {
1 => adjustment::AdjustReifyFnPointer, 1 => adjustment::AdjustReifyFnPointer,
@ -1042,7 +1042,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
Ok(this.read_ty(dcx)) Ok(this.read_ty(dcx))
}).unwrap(); }).unwrap();
adjustment::AdjustEmptyToAny(ty) adjustment::AdjustNeverToAny(ty)
} }
_ => bug!("bad enum variant for adjustment::AutoAdjustment") _ => bug!("bad enum variant for adjustment::AutoAdjustment")
}) })

View file

@ -311,7 +311,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
match self.next() { match self.next() {
'b' => return tcx.types.bool, 'b' => return tcx.types.bool,
'!' => return tcx.types.empty, '!' => return tcx.types.never,
'i' => { /* eat the s of is */ self.next(); return tcx.types.isize }, 'i' => { /* eat the s of is */ self.next(); return tcx.types.isize },
'u' => { /* eat the s of us */ self.next(); return tcx.types.usize }, 'u' => { /* eat the s of us */ self.next(); return tcx.types.usize },
'M' => { 'M' => {

View file

@ -74,7 +74,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
match t.sty { match t.sty {
ty::TyBool => { write!(w, "b"); } ty::TyBool => { write!(w, "b"); }
ty::TyChar => { write!(w, "c"); } ty::TyChar => { write!(w, "c"); }
ty::TyEmpty => { write!(w, "!"); } ty::TyNever => { write!(w, "!"); }
ty::TyInt(t) => { ty::TyInt(t) => {
match t { match t {
ast::IntTy::Is => write!(w, "is"), ast::IntTy::Is => write!(w, "is"),

View file

@ -96,7 +96,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::LogicalOp { .. } | ExprKind::LogicalOp { .. } |
ExprKind::Box { .. } | ExprKind::Box { .. } |
ExprKind::Cast { .. } | ExprKind::Cast { .. } |
ExprKind::EmptyToAny { .. } | ExprKind::NeverToAny { .. } |
ExprKind::ReifyFnPointer { .. } | ExprKind::ReifyFnPointer { .. } |
ExprKind::UnsafeFnPointer { .. } | ExprKind::UnsafeFnPointer { .. } |
ExprKind::Unsize { .. } | ExprKind::Unsize { .. } |

View file

@ -219,7 +219,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Block { .. } | ExprKind::Block { .. } |
ExprKind::Match { .. } | ExprKind::Match { .. } |
ExprKind::If { .. } | ExprKind::If { .. } |
ExprKind::EmptyToAny { .. } | ExprKind::NeverToAny { .. } |
ExprKind::Loop { .. } | ExprKind::Loop { .. } |
ExprKind::LogicalOp { .. } | ExprKind::LogicalOp { .. } |
ExprKind::Call { .. } | ExprKind::Call { .. } |

View file

@ -56,7 +56,7 @@ impl Category {
ExprKind::LogicalOp { .. } | ExprKind::LogicalOp { .. } |
ExprKind::If { .. } | ExprKind::If { .. } |
ExprKind::Match { .. } | ExprKind::Match { .. } |
ExprKind::EmptyToAny { .. } | ExprKind::NeverToAny { .. } |
ExprKind::Call { .. } => ExprKind::Call { .. } =>
Some(Category::Rvalue(RvalueFunc::Into)), Some(Category::Rvalue(RvalueFunc::Into)),

View file

@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Match { discriminant, arms } => { ExprKind::Match { discriminant, arms } => {
this.match_expr(destination, expr_span, block, discriminant, arms) this.match_expr(destination, expr_span, block, discriminant, arms)
} }
ExprKind::EmptyToAny { source } => { ExprKind::NeverToAny { source } => {
let source = this.hir.mirror(source); let source = this.hir.mirror(source);
let is_call = match source.kind { let is_call = match source.kind {
ExprKind::Call { .. } => true, ExprKind::Call { .. } => true,
@ -209,7 +209,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Call { ty, fun, args } => { ExprKind::Call { ty, fun, args } => {
let diverges = match ty.sty { let diverges = match ty.sty {
ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => { ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => {
f.sig.0.output.is_empty(this.hir.tcx()) // FIXME(canndrew): This is_never should probably be an is_uninhabited
f.sig.0.output.is_never()
} }
_ => false _ => false
}; };

View file

@ -60,13 +60,13 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() }, kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() },
}; };
} }
Some(&ty::adjustment::AdjustEmptyToAny(..)) => { Some(&ty::adjustment::AdjustNeverToAny(..)) => {
let adjusted_ty = cx.tcx.expr_ty_adjusted(self); let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
expr = Expr { expr = Expr {
temp_lifetime: temp_lifetime, temp_lifetime: temp_lifetime,
ty: adjusted_ty, ty: adjusted_ty,
span: self.span, span: self.span,
kind: ExprKind::EmptyToAny { source: expr.to_ref() }, kind: ExprKind::NeverToAny { source: expr.to_ref() },
}; };
} }
Some(&ty::adjustment::AdjustMutToConstPointer) => { Some(&ty::adjustment::AdjustMutToConstPointer) => {

View file

@ -139,7 +139,7 @@ pub enum ExprKind<'tcx> {
Cast { Cast {
source: ExprRef<'tcx>, source: ExprRef<'tcx>,
}, },
EmptyToAny { NeverToAny {
source: ExprRef<'tcx>, source: ExprRef<'tcx>,
}, },
ReifyFnPointer { ReifyFnPointer {

View file

@ -492,7 +492,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
} }
}, },
None => { None => {
if !sig.output.is_empty(tcx) { // FIXME(canndrew): This is_never should probably be an is_uninhabited
if !sig.output.is_never() {
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig); span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
} }
}, },

View file

@ -632,7 +632,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) { fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
match v.tcx.tables.borrow().adjustments.get(&e.id) { match v.tcx.tables.borrow().adjustments.get(&e.id) {
None | None |
Some(&ty::adjustment::AdjustEmptyToAny(..)) | Some(&ty::adjustment::AdjustNeverToAny(..)) |
Some(&ty::adjustment::AdjustReifyFnPointer) | Some(&ty::adjustment::AdjustReifyFnPointer) |
Some(&ty::adjustment::AdjustUnsafeFnPointer) | Some(&ty::adjustment::AdjustUnsafeFnPointer) |
Some(&ty::adjustment::AdjustMutToConstPointer) => {} Some(&ty::adjustment::AdjustMutToConstPointer) => {}

View file

@ -1593,7 +1593,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
} }
let t = node_id_type(bcx, discr_expr.id); let t = node_id_type(bcx, discr_expr.id);
let chk = if t.is_empty(tcx) { let chk = if t.is_uninhabited(tcx) {
Unreachable Unreachable
} else { } else {
Infallible Infallible

View file

@ -712,7 +712,8 @@ fn trans_call_inner<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
_ => {} _ => {}
} }
if output.is_empty(bcx.tcx()) { // FIXME(canndrew): This is_never should really be an is_uninhabited
if output.is_never() {
Unreachable(bcx); Unreachable(bcx);
} }

View file

@ -753,7 +753,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
ty::TyRef(..) | ty::TyRef(..) |
ty::TyFnDef(..) | ty::TyFnDef(..) |
ty::TyFnPtr(_) | ty::TyFnPtr(_) |
ty::TyEmpty | ty::TyNever |
ty::TyTrait(_) => { ty::TyTrait(_) => {
/* nothing to do */ /* nothing to do */
} }

View file

@ -558,7 +558,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
abi: Abi::C, abi: Abi::C,
sig: ty::Binder(ty::FnSig { sig: ty::Binder(ty::FnSig {
inputs: vec![tcx.mk_mut_ptr(tcx.types.u8)], inputs: vec![tcx.mk_mut_ptr(tcx.types.u8)],
output: tcx.types.empty, output: tcx.types.never,
variadic: false variadic: false
}), }),
})); }));

View file

@ -34,7 +34,7 @@ use type_of;
use value::Value; use value::Value;
use Disr; use Disr;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::adjustment::{AdjustEmptyToAny, AdjustDerefRef, AdjustReifyFnPointer}; use rustc::ty::adjustment::{AdjustNeverToAny, AdjustDerefRef, AdjustReifyFnPointer};
use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer}; use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::cast::{CastTy,IntTy}; use rustc::ty::cast::{CastTy,IntTy};
@ -348,7 +348,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
&cx.tcx().expr_ty_adjusted(e)); &cx.tcx().expr_ty_adjusted(e));
let opt_adj = cx.tcx().tables.borrow().adjustments.get(&e.id).cloned(); let opt_adj = cx.tcx().tables.borrow().adjustments.get(&e.id).cloned();
match opt_adj { match opt_adj {
Some(AdjustEmptyToAny(..)) => span_bug!(e.span, "const expression of type ! encountered"), Some(AdjustNeverToAny(..)) => span_bug!(e.span, "const expression of type ! encountered"),
Some(AdjustReifyFnPointer) => { Some(AdjustReifyFnPointer) => {
match ety.sty { match ety.sty {
ty::TyFnDef(def_id, substs, _) => { ty::TyFnDef(def_id, substs, _) => {

View file

@ -171,7 +171,7 @@ impl<'tcx> TypeMap<'tcx> {
unique_type_id.push('{'); unique_type_id.push('{');
match type_.sty { match type_.sty {
ty::TyEmpty | ty::TyNever |
ty::TyBool | ty::TyBool |
ty::TyChar | ty::TyChar |
ty::TyStr | ty::TyStr |
@ -695,7 +695,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let sty = &t.sty; let sty = &t.sty;
let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty { let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
ty::TyEmpty | ty::TyNever |
ty::TyBool | ty::TyBool |
ty::TyChar | ty::TyChar |
ty::TyInt(_) | ty::TyInt(_) |
@ -912,7 +912,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
debug!("basic_type_metadata: {:?}", t); debug!("basic_type_metadata: {:?}", t);
let (name, encoding) = match t.sty { let (name, encoding) = match t.sty {
ty::TyEmpty => ("!", DW_ATE_unsigned), ty::TyNever => ("!", DW_ATE_unsigned),
ty::TyTuple(ref elements) if elements.is_empty() => ty::TyTuple(ref elements) if elements.is_empty() =>
("()", DW_ATE_unsigned), ("()", DW_ATE_unsigned),
ty::TyBool => ("bool", DW_ATE_boolean), ty::TyBool => ("bool", DW_ATE_boolean),

View file

@ -40,7 +40,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
ty::TyBool => output.push_str("bool"), ty::TyBool => output.push_str("bool"),
ty::TyChar => output.push_str("char"), ty::TyChar => output.push_str("char"),
ty::TyStr => output.push_str("str"), ty::TyStr => output.push_str("str"),
ty::TyEmpty => output.push_str("!"), ty::TyNever => output.push_str("!"),
ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()), ty::TyInt(int_ty) => output.push_str(int_ty.ty_to_string()),
ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()), ty::TyUint(uint_ty) => output.push_str(uint_ty.ty_to_string()),
ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()), ty::TyFloat(float_ty) => output.push_str(float_ty.ty_to_string()),

View file

@ -111,7 +111,8 @@ pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
let fty = FnType::new(ccx, abi, &sig, &[]); let fty = FnType::new(ccx, abi, &sig, &[]);
let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx)); let llfn = declare_raw_fn(ccx, name, fty.cconv, fty.llvm_type(ccx));
if sig.output.is_empty(ccx.tcx()) { // FIXME(canndrew): This is_never should really be an is_uninhabited
if sig.output.is_never() {
llvm::Attribute::NoReturn.apply_llfn(Function, llfn); llvm::Attribute::NoReturn.apply_llfn(Function, llfn);
} }

View file

@ -69,7 +69,7 @@ use tvec;
use type_of; use type_of;
use value::Value; use value::Value;
use Disr; use Disr;
use rustc::ty::adjustment::{AdjustEmptyToAny, AdjustDerefRef, AdjustReifyFnPointer}; use rustc::ty::adjustment::{AdjustNeverToAny, AdjustDerefRef, AdjustReifyFnPointer};
use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer}; use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
use rustc::ty::adjustment::CustomCoerceUnsized; use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
@ -348,7 +348,7 @@ fn adjustment_required<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
} }
match adjustment { match adjustment {
AdjustEmptyToAny(..) => true, AdjustNeverToAny(..) => true,
AdjustReifyFnPointer => true, AdjustReifyFnPointer => true,
AdjustUnsafeFnPointer | AdjustMutToConstPointer => { AdjustUnsafeFnPointer | AdjustMutToConstPointer => {
// purely a type-level thing // purely a type-level thing
@ -381,7 +381,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debug!("unadjusted datum for expr {:?}: {:?} adjustment={:?}", debug!("unadjusted datum for expr {:?}: {:?} adjustment={:?}",
expr, datum, adjustment); expr, datum, adjustment);
match adjustment { match adjustment {
AdjustEmptyToAny(ref target) => { AdjustNeverToAny(ref target) => {
let mono_target = bcx.monomorphize(target); let mono_target = bcx.monomorphize(target);
let llty = type_of::type_of(bcx.ccx(), mono_target); let llty = type_of::type_of(bcx.ccx(), mono_target);
let dummy = C_undef(llty.ptr_to()); let dummy = C_undef(llty.ptr_to());

View file

@ -412,7 +412,7 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
ty::TyBool => output.push_str("bool"), ty::TyBool => output.push_str("bool"),
ty::TyChar => output.push_str("char"), ty::TyChar => output.push_str("char"),
ty::TyStr => output.push_str("str"), ty::TyStr => output.push_str("str"),
ty::TyEmpty => output.push_str("!"), ty::TyNever => output.push_str("!"),
ty::TyInt(ast::IntTy::Is) => output.push_str("isize"), ty::TyInt(ast::IntTy::Is) => output.push_str("isize"),
ty::TyInt(ast::IntTy::I8) => output.push_str("i8"), ty::TyInt(ast::IntTy::I8) => output.push_str("i8"),
ty::TyInt(ast::IntTy::I16) => output.push_str("i16"), ty::TyInt(ast::IntTy::I16) => output.push_str("i16"),

View file

@ -64,7 +64,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
ty::TyInt(t) => Type::int_from_ty(cx, t), ty::TyInt(t) => Type::int_from_ty(cx, t),
ty::TyUint(t) => Type::uint_from_ty(cx, t), ty::TyUint(t) => Type::uint_from_ty(cx, t),
ty::TyFloat(t) => Type::float_from_ty(cx, t), ty::TyFloat(t) => Type::float_from_ty(cx, t),
ty::TyEmpty => Type::nil(cx), ty::TyNever => Type::nil(cx),
ty::TyBox(ty) | ty::TyBox(ty) |
ty::TyRef(_, ty::TypeAndMut{ty, ..}) | ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
@ -250,7 +250,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
ty::TyInt(t) => Type::int_from_ty(cx, t), ty::TyInt(t) => Type::int_from_ty(cx, t),
ty::TyUint(t) => Type::uint_from_ty(cx, t), ty::TyUint(t) => Type::uint_from_ty(cx, t),
ty::TyFloat(t) => Type::float_from_ty(cx, t), ty::TyFloat(t) => Type::float_from_ty(cx, t),
ty::TyEmpty => Type::nil(cx), ty::TyNever => Type::nil(cx),
ty::TyEnum(def, ref substs) => { ty::TyEnum(def, ref substs) => {
// Only create the named struct, but don't fill it in. We // Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache. This // fill it in *after* placing it into the type cache. This

View file

@ -1700,8 +1700,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let t = self.ast_ty_to_ty(rscope1, &mt.ty); let t = self.ast_ty_to_ty(rscope1, &mt.ty);
tcx.mk_ref(tcx.mk_region(r), ty::TypeAndMut {ty: t, mutbl: mt.mutbl}) tcx.mk_ref(tcx.mk_region(r), ty::TypeAndMut {ty: t, mutbl: mt.mutbl})
} }
hir::TyEmpty => { hir::TyNever => {
tcx.types.empty tcx.types.never
}, },
hir::TyTup(ref fields) => { hir::TyTup(ref fields) => {
let flds = fields.iter() let flds = fields.iter()

View file

@ -68,8 +68,8 @@ use rustc::traits::{self, ObligationCause};
use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef}; use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer}; use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer}; use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
use rustc::ty::adjustment::AdjustEmptyToAny; use rustc::ty::adjustment::AdjustNeverToAny;
use rustc::ty::{self, TypeVariants, LvaluePreference, TypeAndMut, Ty}; use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty};
use rustc::ty::fold::TypeFoldable; use rustc::ty::fold::TypeFoldable;
use rustc::ty::error::TypeError; use rustc::ty::error::TypeError;
use rustc::ty::relate::RelateResult; use rustc::ty::relate::RelateResult;
@ -168,8 +168,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
return self.identity(b); return self.identity(b);
} }
if let TypeVariants::TyEmpty = a.sty { if a.is_never() {
return Ok((b, AdjustEmptyToAny(b))); return Ok((b, AdjustNeverToAny(b)));
} }
// Consider coercing the subtype to a DST // Consider coercing the subtype to a DST

View file

@ -433,7 +433,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
// We still need to ensure all referenced data is safe. // We still need to ensure all referenced data is safe.
match ty.sty { match ty.sty {
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) |
ty::TyFloat(_) | ty::TyStr | ty::TyEmpty => { ty::TyFloat(_) | ty::TyStr | ty::TyNever => {
// primitive - definitely safe // primitive - definitely safe
Ok(()) Ok(())
} }

View file

@ -106,7 +106,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
}; };
(n_tps, inputs, output) (n_tps, inputs, output)
} else if &name[..] == "abort" || &name[..] == "unreachable" { } else if &name[..] == "abort" || &name[..] == "unreachable" {
(0, Vec::new(), tcx.types.empty) (0, Vec::new(), tcx.types.never)
} else { } else {
let (n_tps, inputs, output) = match &name[..] { let (n_tps, inputs, output) = match &name[..] {
"breakpoint" => (0, Vec::new(), tcx.mk_nil()), "breakpoint" => (0, Vec::new(), tcx.mk_nil()),

View file

@ -93,7 +93,7 @@ use rustc::traits::{self, Reveal};
use rustc::ty::{GenericPredicates, TypeScheme}; use rustc::ty::{GenericPredicates, TypeScheme};
use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{ParamTy, ParameterEnvironment};
use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
use rustc::ty::{self, ToPolyTraitRef, Ty, TypeVariants, TyCtxt, Visibility}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility};
use rustc::ty::{MethodCall, MethodCallee}; use rustc::ty::{MethodCall, MethodCallee};
use rustc::ty::adjustment; use rustc::ty::adjustment;
use rustc::ty::fold::{BottomUpFolder, TypeFoldable}; use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
@ -1556,8 +1556,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
#[inline] #[inline]
pub fn write_ty_expr(&self, node_id: ast::NodeId, ty: Ty<'tcx>) { pub fn write_ty_expr(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
self.write_ty(node_id, ty); self.write_ty(node_id, ty);
if let TypeVariants::TyEmpty = ty.sty { if ty.is_never() {
self.write_adjustment(node_id, adjustment::AdjustEmptyToAny(self.next_diverging_ty_var())); self.write_adjustment(node_id, adjustment::AdjustNeverToAny(self.next_diverging_ty_var()));
} }
} }
@ -1732,8 +1732,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.write_ty(node_id, self.tcx.mk_nil()); self.write_ty(node_id, self.tcx.mk_nil());
} }
pub fn write_empty(&self, node_id: ast::NodeId) { pub fn write_never(&self, node_id: ast::NodeId) {
self.write_ty_expr(node_id, self.tcx.types.empty); self.write_ty_expr(node_id, self.tcx.types.never);
} }
pub fn write_error(&self, node_id: ast::NodeId) { pub fn write_error(&self, node_id: ast::NodeId) {
@ -1793,7 +1793,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> { pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> {
if let Some(&adjustment::AdjustEmptyToAny(ref t)) if let Some(&adjustment::AdjustNeverToAny(ref t))
= self.tables.borrow().adjustments.get(&ex.id) { = self.tables.borrow().adjustments.get(&ex.id) {
return t; return t;
} }
@ -1977,7 +1977,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if self.type_var_diverges(resolved) { if self.type_var_diverges(resolved) {
debug!("default_type_parameters: defaulting `{:?}` to `!` because it diverges", debug!("default_type_parameters: defaulting `{:?}` to `!` because it diverges",
resolved); resolved);
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.empty); self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.never);
} else { } else {
match self.type_is_unconstrained_numeric(resolved) { match self.type_is_unconstrained_numeric(resolved) {
UnconstrainedInt => { UnconstrainedInt => {
@ -2051,7 +2051,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
for ty in &unsolved_variables { for ty in &unsolved_variables {
let resolved = self.resolve_type_vars_if_possible(ty); let resolved = self.resolve_type_vars_if_possible(ty);
if self.type_var_diverges(resolved) { if self.type_var_diverges(resolved) {
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.empty); self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.never);
} else { } else {
match self.type_is_unconstrained_numeric(resolved) { match self.type_is_unconstrained_numeric(resolved) {
UnconstrainedInt | UnconstrainedFloat => { UnconstrainedInt | UnconstrainedFloat => {
@ -2109,7 +2109,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| { let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| {
for ty in &unbound_tyvars { for ty in &unbound_tyvars {
if self.type_var_diverges(ty) { if self.type_var_diverges(ty) {
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.empty); self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.never);
} else { } else {
match self.type_is_unconstrained_numeric(ty) { match self.type_is_unconstrained_numeric(ty) {
UnconstrainedInt => { UnconstrainedInt => {
@ -2205,7 +2205,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// reporting for more then one conflict. // reporting for more then one conflict.
for ty in &unbound_tyvars { for ty in &unbound_tyvars {
if self.type_var_diverges(ty) { if self.type_var_diverges(ty) {
self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.empty); self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx.types.never);
} else { } else {
match self.type_is_unconstrained_numeric(ty) { match self.type_is_unconstrained_numeric(ty) {
UnconstrainedInt => { UnconstrainedInt => {
@ -2610,9 +2610,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
if let Some(&arg_ty) = self.tables.borrow().node_types.get(&arg.id) { if let Some(&arg_ty) = self.tables.borrow().node_types.get(&arg.id) {
// FIXME(canndrew): This is_never should probably be an is_uninhabited
any_diverges = any_diverges || any_diverges = any_diverges ||
self.type_var_diverges(arg_ty) || self.type_var_diverges(arg_ty) ||
arg_ty.is_empty(self.tcx); arg_ty.is_never();
} }
} }
if any_diverges && !warned { if any_diverges && !warned {
@ -3485,8 +3486,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} }
self.write_nil(id); self.write_nil(id);
} }
hir::ExprBreak(_) => { self.write_empty(id); } hir::ExprBreak(_) => { self.write_never(id); }
hir::ExprAgain(_) => { self.write_empty(id); } hir::ExprAgain(_) => { self.write_never(id); }
hir::ExprRet(ref expr_opt) => { hir::ExprRet(ref expr_opt) => {
if let Some(ref e) = *expr_opt { if let Some(ref e) = *expr_opt {
self.check_expr_coercable_to_type(&e, self.ret_ty); self.check_expr_coercable_to_type(&e, self.ret_ty);
@ -3504,7 +3505,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
.emit(); .emit();
} }
} }
self.write_empty(id); self.write_never(id);
} }
hir::ExprAssign(ref lhs, ref rhs) => { hir::ExprAssign(ref lhs, ref rhs) => {
self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue); self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue);
@ -3546,7 +3547,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
hir::ExprLoop(ref body, _) => { hir::ExprLoop(ref body, _) => {
self.check_block_no_value(&body); self.check_block_no_value(&body);
if !may_break(tcx, expr.id, &body) { if !may_break(tcx, expr.id, &body) {
self.write_empty(id); self.write_never(id);
} else { } else {
self.write_nil(id); self.write_nil(id);
} }
@ -4002,9 +4003,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
"unreachable statement".to_string()); "unreachable statement".to_string());
warned = true; warned = true;
} }
// FIXME(canndrew): This is_never should probably be an is_uninhabited
any_diverges = any_diverges || any_diverges = any_diverges ||
self.type_var_diverges(s_ty) || self.type_var_diverges(s_ty) ||
s_ty.is_empty(self.tcx); s_ty.is_never();
any_err = any_err || s_ty.references_error(); any_err = any_err || s_ty.references_error();
} }
match blk.expr { match blk.expr {

View file

@ -51,7 +51,7 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
let id = self.id; let id = self.id;
let span = self.span; let span = self.span;
self.inherited.enter(|inh| { self.inherited.enter(|inh| {
let fcx = FnCtxt::new(&inh, inh.ccx.tcx.types.empty, id); let fcx = FnCtxt::new(&inh, inh.ccx.tcx.types.never, id);
let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
ccx: fcx.ccx, ccx: fcx.ccx,
code: code code: code

View file

@ -378,8 +378,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
Some(adjustment) => { Some(adjustment) => {
let resolved_adjustment = match adjustment { let resolved_adjustment = match adjustment {
adjustment::AdjustEmptyToAny(ty) => { adjustment::AdjustNeverToAny(ty) => {
adjustment::AdjustEmptyToAny(self.resolve(&ty, reason)) adjustment::AdjustNeverToAny(self.resolve(&ty, reason))
} }
adjustment::AdjustReifyFnPointer => { adjustment::AdjustReifyFnPointer => {

View file

@ -24,7 +24,7 @@ use rustc::ty::{ImplOrTraitItemId, ConstTraitItemId};
use rustc::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment}; use rustc::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
use rustc::ty::{Ty, TyBool, TyChar, TyEnum, TyError}; use rustc::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
use rustc::ty::{TyParam, TyRawPtr}; use rustc::ty::{TyParam, TyRawPtr};
use rustc::ty::{TyRef, TyStruct, TyTrait, TyEmpty, TyTuple}; use rustc::ty::{TyRef, TyStruct, TyTrait, TyNever, TyTuple};
use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt}; use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr}; use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
use rustc::ty::{TyProjection, TyAnon}; use rustc::ty::{TyProjection, TyAnon};
@ -84,7 +84,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
TyStr | TyArray(..) | TySlice(..) | TyFnDef(..) | TyFnPtr(_) | TyStr | TyArray(..) | TySlice(..) | TyFnDef(..) | TyFnPtr(_) |
TyTuple(..) | TyParam(..) | TyError | TyEmpty | TyTuple(..) | TyParam(..) | TyError | TyNever |
TyRawPtr(_) | TyRef(_, _) | TyProjection(..) => { TyRawPtr(_) | TyRef(_, _) | TyProjection(..) => {
None None
} }

View file

@ -322,7 +322,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
match ty.sty { match ty.sty {
ty::TyBool | ty::TyBool |
ty::TyChar | ty::TyInt(_) | ty::TyUint(_) | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) |
ty::TyFloat(_) | ty::TyStr | ty::TyEmpty => { ty::TyFloat(_) | ty::TyStr | ty::TyNever => {
/* leaf type -- noop */ /* leaf type -- noop */
} }

View file

@ -1459,8 +1459,7 @@ pub enum Type {
Tuple(Vec<Type>), Tuple(Vec<Type>),
Vector(Box<Type>), Vector(Box<Type>),
FixedVector(Box<Type>, String), FixedVector(Box<Type>, String),
/// aka TyBot Never,
Bottom,
Unique(Box<Type>), Unique(Box<Type>),
RawPointer(Mutability, Box<Type>), RawPointer(Mutability, Box<Type>),
BorrowedRef { BorrowedRef {
@ -1671,7 +1670,7 @@ impl Clean<Type> for hir::Ty {
fn clean(&self, cx: &DocContext) -> Type { fn clean(&self, cx: &DocContext) -> Type {
use rustc::hir::*; use rustc::hir::*;
match self.node { match self.node {
TyEmpty => Bottom, TyNever => Never,
TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)), TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
TyRptr(ref l, ref m) => TyRptr(ref l, ref m) =>
BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx), BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
@ -1780,7 +1779,7 @@ impl Clean<Type> for hir::Ty {
impl<'tcx> Clean<Type> for ty::Ty<'tcx> { impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
fn clean(&self, cx: &DocContext) -> Type { fn clean(&self, cx: &DocContext) -> Type {
match self.sty { match self.sty {
ty::TyEmpty => Bottom, ty::TyNever => Never,
ty::TyBool => Primitive(Bool), ty::TyBool => Primitive(Bool),
ty::TyChar => Primitive(Char), ty::TyChar => Primitive(Char),
ty::TyInt(ast::IntTy::Is) => Primitive(Isize), ty::TyInt(ast::IntTy::Is) => Primitive(Isize),

View file

@ -492,7 +492,7 @@ impl fmt::Display for clean::Type {
primitive_link(f, clean::PrimitiveType::Array, primitive_link(f, clean::PrimitiveType::Array,
&format!("; {}]", Escape(s))) &format!("; {}]", Escape(s)))
} }
clean::Bottom => f.write_str("!"), clean::Never => f.write_str("!"),
clean::RawPointer(m, ref t) => { clean::RawPointer(m, ref t) => {
match **t { match **t {
clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {

View file

@ -1358,8 +1358,8 @@ pub enum TyKind {
Rptr(Option<Lifetime>, MutTy), Rptr(Option<Lifetime>, MutTy),
/// A bare function (e.g. `fn(usize) -> bool`) /// A bare function (e.g. `fn(usize) -> bool`)
BareFn(P<BareFnTy>), BareFn(P<BareFnTy>),
/// The empty type (`!`) /// The never type (`!`)
Empty, Never,
/// A tuple (`(A, B, C, D,...)`) /// A tuple (`(A, B, C, D,...)`)
Tup(Vec<P<Ty>> ), Tup(Vec<P<Ty>> ),
/// A path (`module::module::...::Type`), optionally /// A path (`module::module::...::Type`), optionally

View file

@ -287,7 +287,7 @@ declare_features! (
(active, relaxed_adts, "1.12.0", Some(35626)), (active, relaxed_adts, "1.12.0", Some(35626)),
// The `!` type // The `!` type
(active, bang_type, "1.13.0", Some(35121)) (active, never_type, "1.13.0", Some(35121))
); );
declare_features! ( declare_features! (
@ -966,8 +966,8 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
gate_feature_post!(&self, conservative_impl_trait, ty.span, gate_feature_post!(&self, conservative_impl_trait, ty.span,
"`impl Trait` is experimental"); "`impl Trait` is experimental");
} }
ast::TyKind::Empty => { ast::TyKind::Never => {
gate_feature_post!(&self, bang_type, ty.span, gate_feature_post!(&self, never_type, ty.span,
"The `!` type is experimental"); "The `!` type is experimental");
}, },
_ => {} _ => {}
@ -978,7 +978,7 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
fn visit_fn_ret_ty(&mut self, ret_ty: &ast::FunctionRetTy) { fn visit_fn_ret_ty(&mut self, ret_ty: &ast::FunctionRetTy) {
if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty { if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty {
match output_ty.node { match output_ty.node {
ast::TyKind::Empty => return, ast::TyKind::Never => return,
_ => (), _ => (),
}; };
visit::walk_ty(self, output_ty) visit::walk_ty(self, output_ty)

View file

@ -373,7 +373,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
decl: fld.fold_fn_decl(decl) decl: fld.fold_fn_decl(decl)
})) }))
} }
TyKind::Empty => node, TyKind::Never => node,
TyKind::Tup(tys) => TyKind::Tup(tys.move_map(|ty| fld.fold_ty(ty))), TyKind::Tup(tys) => TyKind::Tup(tys.move_map(|ty| fld.fold_ty(ty))),
TyKind::Paren(ty) => TyKind::Paren(fld.fold_ty(ty)), TyKind::Paren(ty) => TyKind::Paren(fld.fold_ty(ty)),
TyKind::Path(qself, path) => { TyKind::Path(qself, path) => {

View file

@ -1396,7 +1396,7 @@ impl<'a> Parser<'a> {
TyKind::Tup(ts) TyKind::Tup(ts)
} }
} else if self.eat(&token::Not) { } else if self.eat(&token::Not) {
TyKind::Empty TyKind::Never
} else if self.check(&token::BinOp(token::Star)) { } else if self.check(&token::BinOp(token::Star)) {
// STAR POINTER (bare pointer?) // STAR POINTER (bare pointer?)
self.bump(); self.bump();

View file

@ -976,7 +976,7 @@ impl<'a> State<'a> {
try!(self.print_opt_lifetime(lifetime)); try!(self.print_opt_lifetime(lifetime));
try!(self.print_mt(mt)); try!(self.print_mt(mt));
} }
ast::TyKind::Empty => { ast::TyKind::Never => {
word(&mut self.s, "!")?; word(&mut self.s, "!")?;
}, },
ast::TyKind::Tup(ref elts) => { ast::TyKind::Tup(ref elts) => {

View file

@ -323,7 +323,7 @@ pub fn walk_ty<V: Visitor>(visitor: &mut V, typ: &Ty) {
walk_list!(visitor, visit_lifetime, opt_lifetime); walk_list!(visitor, visit_lifetime, opt_lifetime);
visitor.visit_ty(&mutable_type.ty) visitor.visit_ty(&mutable_type.ty)
} }
TyKind::Empty => {}, TyKind::Never => {},
TyKind::Tup(ref tuple_element_types) => { TyKind::Tup(ref tuple_element_types) => {
walk_list!(visitor, visit_ty, tuple_element_types); walk_list!(visitor, visit_ty, tuple_element_types);
} }

View file

@ -8,9 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![feature(bang_type)] #![feature(never_type)]
// error-pattern:explicit // error-pattern:explicit
fn main() { fn main() {