1
Fork 0

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 `!`
macro_rules! not_stage0 {
() => {
#[unstable(feature = "bang_type", issue = "35121")]
#[unstable(feature = "never_type", issue = "35121")]
impl PartialEq for ! {
fn eq(&self, _: &!) -> bool {
*self
}
}
#[unstable(feature = "bang_type", issue = "35121")]
#[unstable(feature = "never_type", issue = "35121")]
impl Eq for ! {}
#[unstable(feature = "bang_type", issue = "35121")]
#[unstable(feature = "never_type", issue = "35121")]
impl PartialOrd for ! {
fn partial_cmp(&self, _: &!) -> Option<Ordering> {
*self
}
}
#[unstable(feature = "bang_type", issue = "35121")]
#[unstable(feature = "never_type", issue = "35121")]
impl Ord for ! {
fn cmp(&self, _: &!) -> Ordering {
*self

View file

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

View file

@ -89,7 +89,7 @@
#![feature(question_mark)]
// NOTE: remove the cfg_attr next snapshot
#![cfg_attr(not(stage0), feature(bang_type))]
#![cfg_attr(not(stage0), feature(never_type))]
#[macro_use]
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 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()
} else {
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))),
TyPath(qself, path) => {
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);
visitor.visit_ty(&mutable_type.ty)
}
TyEmpty => {},
TyNever => {},
TyTup(ref 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),
}))
}
Empty => hir::TyEmpty,
Never => hir::TyNever,
Tup(ref tys) => hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty)).collect()),
Paren(ref ty) => {
return self.lower_ty(ty);

View file

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

View file

@ -504,7 +504,7 @@ impl<'a> State<'a> {
self.print_opt_lifetime(lifetime)?;
self.print_mt(mt)?;
}
hir::TyEmpty => {
hir::TyNever => {
word(&mut self.s, "!")?;
},
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::TyStruct(..) |
ty::TyClosure(..) |
ty::TyEmpty |
ty::TyNever |
ty::TyTuple(..) |
ty::TyProjection(..) |
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());
if let Some(adjustment) = adj {
match adjustment {
adjustment::AdjustEmptyToAny(..) |
adjustment::AdjustNeverToAny(..) |
adjustment::AdjustReifyFnPointer |
adjustment::AdjustUnsafeFnPointer |
adjustment::AdjustMutToConstPointer => {

View file

@ -1111,8 +1111,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
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) &&
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 {
self.s.exit_ln
} else {
@ -1125,7 +1126,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprMethodCall(_, _, ref args) => {
let method_call = ty::MethodCall::expr(expr.id);
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
} else {
succ

View file

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

View file

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

View file

@ -212,7 +212,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyProjection(..) => Some(13),
ty::TyParam(..) => Some(14),
ty::TyAnon(..) => Some(15),
ty::TyEmpty => Some(16),
ty::TyNever => Some(16),
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::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyRawPtr(..) |
ty::TyChar | ty::TyBox(_) | ty::TyRef(..) |
ty::TyArray(..) | ty::TyClosure(..) | ty::TyEmpty |
ty::TyArray(..) | ty::TyClosure(..) | ty::TyNever |
ty::TyError => {
// safe for everything
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::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) |
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 }) => {
Where(ty::Binder(Vec::new()))
}
@ -1886,7 +1886,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
ty::TyError |
ty::TyInfer(ty::IntVar(_)) |
ty::TyInfer(ty::FloatVar(_)) |
ty::TyEmpty |
ty::TyNever |
ty::TyChar => {
Vec::new()
}

View file

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

View file

@ -185,7 +185,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
// Scalar and unique types are sendable, and durable
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 => {
TC::None
}

View file

@ -190,7 +190,7 @@ pub struct CommonTypes<'tcx> {
pub u64: Ty<'tcx>,
pub f32: Ty<'tcx>,
pub f64: Ty<'tcx>,
pub empty: Ty<'tcx>,
pub never: Ty<'tcx>,
pub err: Ty<'tcx>,
}
@ -257,7 +257,7 @@ impl<'tcx> CommonTypes<'tcx> {
CommonTypes {
bool: mk(TyBool),
char: mk(TyChar),
empty: mk(TyEmpty),
never: mk(TyNever),
err: mk(TyError),
isize: mk(TyInt(ast::IntTy::Is)),
i8: mk(TyInt(ast::IntTy::I8)),
@ -977,7 +977,7 @@ macro_rules! sty_debug_print {
for &Interned(t) in tcx.interners.type_.borrow().iter() {
let variant = match t.sty {
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::$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 {
match self.sty {
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::TyEnum(def, _) => format!("enum `{}`", tcx.item_path_str(def.did)),

View file

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

View file

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

View file

@ -349,7 +349,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
ty::TyAnon(..) |
ty::TyInfer(_) |
ty::TyError |
ty::TyEmpty |
ty::TyNever |
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::TyFnPtr(_) => Scalar { value: Pointer, non_zero: true },
// The empty type.
ty::TyEmpty => Univariant { variant: Struct::new(dl, false), non_zero: false },
// The never type.
ty::TyNever => Univariant { variant: Struct::new(dl, false), non_zero: false },
// Potentially-fat pointers.
ty::TyBox(pointee) |

View file

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

View file

@ -171,7 +171,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyInt(..) | // OutlivesScalar
ty::TyUint(..) | // OutlivesScalar
ty::TyFloat(..) | // OutlivesScalar
ty::TyEmpty | // ...
ty::TyNever | // ...
ty::TyEnum(..) | // OutlivesNominalType
ty::TyStruct(..) | // OutlivesNominalType
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)
}
(&ty::TyEmpty, _) |
(&ty::TyNever, _) |
(&ty::TyChar, _) |
(&ty::TyBool, _) |
(&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::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
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)
}
@ -515,7 +515,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::TyAnon(_, ref substs) => substs.visit_with(visitor),
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
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`.
TyClosure(DefId, ClosureSubsts<'tcx>),
/// The empty type `!`
TyEmpty,
/// The never type `!`
TyNever,
/// A tuple type. For example, `(i32, bool)`.
TyTuple(&'tcx [Ty<'tcx>]),
@ -894,14 +894,22 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
}
pub fn is_empty(&self, cx: TyCtxt) -> bool {
// FIXME(#24885): be smarter here
pub fn is_never(&self) -> bool {
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 {
TyEnum(def, _) | TyStruct(def, _) => def.is_empty(),
TyEmpty => true,
TyTuple(ref tys) => tys.iter().any(|ty| ty.is_empty(cx)),
TyNever => true,
TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited(cx)),
// FIXME (canndrew): this line breaks core::fmt
//TyRef(_, ref tm) => tm.ty.is_empty(cx),
//TyRef(_, ref tm) => tm.ty.is_uninhabited(cx),
_ => false,
}
}
@ -1225,7 +1233,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
TyArray(_, _) |
TySlice(_) |
TyRawPtr(_) |
TyEmpty |
TyNever |
TyTuple(_) |
TyParam(_) |
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.hash(data.item_name.as_str());
}
TyEmpty |
TyNever |
TyBool |
TyChar |
TyStr |
@ -551,7 +551,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
// Fast-path for primitive types
let result = match self.sty {
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyEmpty |
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyNever |
TyRawPtr(..) | TyFnDef(..) | TyFnPtr(_) | TyRef(_, TypeAndMut {
mutbl: hir::MutImmutable, ..
}) => Some(false),
@ -597,7 +597,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
let result = match self.sty {
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
TyArray(..) | TyTuple(..) | TyClosure(..) | TyEmpty => Some(true),
TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
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>) {
match parent_ty.sty {
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) => {
stack.push(ty);

View file

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

View file

@ -14,7 +14,7 @@ use ty::subst::{self, Subst};
use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
use ty::{TyBool, TyChar, TyStruct, TyEnum};
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::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
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> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::adjustment::AdjustEmptyToAny(ref target) => {
write!(f, "AdjustEmptyToAny({:?})", target)
ty::adjustment::AdjustNeverToAny(ref target) => {
write!(f, "AdjustNeverToAny({:?})", target)
}
ty::adjustment::AdjustReifyFnPointer => {
write!(f, "AdjustReifyFnPointer")
@ -843,7 +843,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
}
write!(f, "{}", tm)
}
TyEmpty => write!(f, "!"),
TyNever => write!(f, "!"),
TyTuple(ref tys) => {
write!(f, "(")?;
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.
let pat_ty = cx.tcx.node_id_to_type(scrut.id);
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
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);
span_help!(&mut err, ex.span,
"Please ensure that all possible cases are being handled; \
possibly adding wildcards or more match arms.");
err.emit();
}
// If the type *is* empty, it's vacuously exhaustive
// If the type *is* uninhabited, it's vacuously exhaustive
return;
}

View file

@ -523,7 +523,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
// Primitive types with a stable representation.
ty::TyBool | ty::TyInt(..) | ty::TyUint(..) |
ty::TyFloat(..) | ty::TyEmpty => FfiSafe,
ty::TyFloat(..) | ty::TyNever => FfiSafe,
ty::TyBox(..) => {
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 warned = match t.sty {
ty::TyTuple(ref tys) if tys.is_empty() => return,
ty::TyEmpty => return,
ty::TyNever => return,
ty::TyBool => return,
ty::TyStruct(def, _) |
ty::TyEnum(def, _) => {

View file

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

View file

@ -311,7 +311,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
let tcx = self.tcx;
match self.next() {
'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 },
'u' => { /* eat the s of us */ self.next(); return tcx.types.usize },
'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 {
ty::TyBool => { write!(w, "b"); }
ty::TyChar => { write!(w, "c"); }
ty::TyEmpty => { write!(w, "!"); }
ty::TyNever => { write!(w, "!"); }
ty::TyInt(t) => {
match t {
ast::IntTy::Is => write!(w, "is"),

View file

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

View file

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

View file

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

View file

@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Match { discriminant, arms } => {
this.match_expr(destination, expr_span, block, discriminant, arms)
}
ExprKind::EmptyToAny { source } => {
ExprKind::NeverToAny { source } => {
let source = this.hir.mirror(source);
let is_call = match source.kind {
ExprKind::Call { .. } => true,
@ -209,7 +209,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
ExprKind::Call { ty, fun, args } => {
let diverges = match ty.sty {
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
};

View file

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

View file

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

View file

@ -492,7 +492,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
}
},
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);
}
},

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) {
match v.tcx.tables.borrow().adjustments.get(&e.id) {
None |
Some(&ty::adjustment::AdjustEmptyToAny(..)) |
Some(&ty::adjustment::AdjustNeverToAny(..)) |
Some(&ty::adjustment::AdjustReifyFnPointer) |
Some(&ty::adjustment::AdjustUnsafeFnPointer) |
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 chk = if t.is_empty(tcx) {
let chk = if t.is_uninhabited(tcx) {
Unreachable
} else {
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);
}

View file

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

View file

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

View file

@ -34,7 +34,7 @@ use type_of;
use value::Value;
use Disr;
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::{self, Ty, TyCtxt};
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));
let opt_adj = cx.tcx().tables.borrow().adjustments.get(&e.id).cloned();
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) => {
match ety.sty {
ty::TyFnDef(def_id, substs, _) => {

View file

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

View file

@ -69,7 +69,7 @@ use tvec;
use type_of;
use value::Value;
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::CustomCoerceUnsized;
use rustc::ty::{self, Ty, TyCtxt};
@ -348,7 +348,7 @@ fn adjustment_required<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
match adjustment {
AdjustEmptyToAny(..) => true,
AdjustNeverToAny(..) => true,
AdjustReifyFnPointer => true,
AdjustUnsafeFnPointer | AdjustMutToConstPointer => {
// purely a type-level thing
@ -381,7 +381,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debug!("unadjusted datum for expr {:?}: {:?} adjustment={:?}",
expr, datum, adjustment);
match adjustment {
AdjustEmptyToAny(ref target) => {
AdjustNeverToAny(ref target) => {
let mono_target = bcx.monomorphize(target);
let llty = type_of::type_of(bcx.ccx(), mono_target);
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::TyChar => output.push_str("char"),
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::I8) => output.push_str("i8"),
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::TyUint(t) => Type::uint_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::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::TyUint(t) => Type::uint_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) => {
// Only create the named struct, but don't fill it in. We
// 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);
tcx.mk_ref(tcx.mk_region(r), ty::TypeAndMut {ty: t, mutbl: mt.mutbl})
}
hir::TyEmpty => {
tcx.types.empty
hir::TyNever => {
tcx.types.never
},
hir::TyTup(ref fields) => {
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::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
use rustc::ty::adjustment::AdjustEmptyToAny;
use rustc::ty::{self, TypeVariants, LvaluePreference, TypeAndMut, Ty};
use rustc::ty::adjustment::AdjustNeverToAny;
use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::error::TypeError;
use rustc::ty::relate::RelateResult;
@ -168,8 +168,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
return self.identity(b);
}
if let TypeVariants::TyEmpty = a.sty {
return Ok((b, AdjustEmptyToAny(b)));
if a.is_never() {
return Ok((b, AdjustNeverToAny(b)));
}
// 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.
match ty.sty {
ty::TyBool | ty::TyChar | ty::TyInt(_) | ty::TyUint(_) |
ty::TyFloat(_) | ty::TyStr | ty::TyEmpty => {
ty::TyFloat(_) | ty::TyStr | ty::TyNever => {
// primitive - definitely safe
Ok(())
}

View file

@ -106,7 +106,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
};
(n_tps, inputs, output)
} else if &name[..] == "abort" || &name[..] == "unreachable" {
(0, Vec::new(), tcx.types.empty)
(0, Vec::new(), tcx.types.never)
} else {
let (n_tps, inputs, output) = match &name[..] {
"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::{ParamTy, ParameterEnvironment};
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::adjustment;
use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
@ -1556,8 +1556,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
#[inline]
pub fn write_ty_expr(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
self.write_ty(node_id, ty);
if let TypeVariants::TyEmpty = ty.sty {
self.write_adjustment(node_id, adjustment::AdjustEmptyToAny(self.next_diverging_ty_var()));
if ty.is_never() {
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());
}
pub fn write_empty(&self, node_id: ast::NodeId) {
self.write_ty_expr(node_id, self.tcx.types.empty);
pub fn write_never(&self, node_id: ast::NodeId) {
self.write_ty_expr(node_id, self.tcx.types.never);
}
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> {
if let Some(&adjustment::AdjustEmptyToAny(ref t))
if let Some(&adjustment::AdjustNeverToAny(ref t))
= self.tables.borrow().adjustments.get(&ex.id) {
return t;
}
@ -1977,7 +1977,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if self.type_var_diverges(resolved) {
debug!("default_type_parameters: defaulting `{:?}` to `!` because it 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 {
match self.type_is_unconstrained_numeric(resolved) {
UnconstrainedInt => {
@ -2051,7 +2051,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
for ty in &unsolved_variables {
let resolved = self.resolve_type_vars_if_possible(ty);
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 {
match self.type_is_unconstrained_numeric(resolved) {
UnconstrainedInt | UnconstrainedFloat => {
@ -2109,7 +2109,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| {
for ty in &unbound_tyvars {
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 {
match self.type_is_unconstrained_numeric(ty) {
UnconstrainedInt => {
@ -2205,7 +2205,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// reporting for more then one conflict.
for ty in &unbound_tyvars {
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 {
match self.type_is_unconstrained_numeric(ty) {
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) {
// FIXME(canndrew): This is_never should probably be an is_uninhabited
any_diverges = any_diverges ||
self.type_var_diverges(arg_ty) ||
arg_ty.is_empty(self.tcx);
arg_ty.is_never();
}
}
if any_diverges && !warned {
@ -3485,8 +3486,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
self.write_nil(id);
}
hir::ExprBreak(_) => { self.write_empty(id); }
hir::ExprAgain(_) => { self.write_empty(id); }
hir::ExprBreak(_) => { self.write_never(id); }
hir::ExprAgain(_) => { self.write_never(id); }
hir::ExprRet(ref expr_opt) => {
if let Some(ref e) = *expr_opt {
self.check_expr_coercable_to_type(&e, self.ret_ty);
@ -3504,7 +3505,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
.emit();
}
}
self.write_empty(id);
self.write_never(id);
}
hir::ExprAssign(ref lhs, ref rhs) => {
self.check_expr_with_lvalue_pref(&lhs, PreferMutLvalue);
@ -3546,7 +3547,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
hir::ExprLoop(ref body, _) => {
self.check_block_no_value(&body);
if !may_break(tcx, expr.id, &body) {
self.write_empty(id);
self.write_never(id);
} else {
self.write_nil(id);
}
@ -4002,9 +4003,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
"unreachable statement".to_string());
warned = true;
}
// FIXME(canndrew): This is_never should probably be an is_uninhabited
any_diverges = any_diverges ||
self.type_var_diverges(s_ty) ||
s_ty.is_empty(self.tcx);
s_ty.is_never();
any_err = any_err || s_ty.references_error();
}
match blk.expr {

View file

@ -51,7 +51,7 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
let id = self.id;
let span = self.span;
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 {
ccx: fcx.ccx,
code: code

View file

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

View file

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

View file

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

View file

@ -1459,8 +1459,7 @@ pub enum Type {
Tuple(Vec<Type>),
Vector(Box<Type>),
FixedVector(Box<Type>, String),
/// aka TyBot
Bottom,
Never,
Unique(Box<Type>),
RawPointer(Mutability, Box<Type>),
BorrowedRef {
@ -1671,7 +1670,7 @@ impl Clean<Type> for hir::Ty {
fn clean(&self, cx: &DocContext) -> Type {
use rustc::hir::*;
match self.node {
TyEmpty => Bottom,
TyNever => Never,
TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)),
TyRptr(ref l, ref m) =>
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> {
fn clean(&self, cx: &DocContext) -> Type {
match self.sty {
ty::TyEmpty => Bottom,
ty::TyNever => Never,
ty::TyBool => Primitive(Bool),
ty::TyChar => Primitive(Char),
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,
&format!("; {}]", Escape(s)))
}
clean::Bottom => f.write_str("!"),
clean::Never => f.write_str("!"),
clean::RawPointer(m, ref t) => {
match **t {
clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {

View file

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

View file

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

View file

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

View file

@ -976,7 +976,7 @@ impl<'a> State<'a> {
try!(self.print_opt_lifetime(lifetime));
try!(self.print_mt(mt));
}
ast::TyKind::Empty => {
ast::TyKind::Never => {
word(&mut self.s, "!")?;
},
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);
visitor.visit_ty(&mutable_type.ty)
}
TyKind::Empty => {},
TyKind::Never => {},
TyKind::Tup(ref 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
// except according to those terms.
#![feature(bang_type)]
#![feature(never_type)]
// error-pattern:explicit
fn main() {