From 69bb5fa85203e264387806bbb05acaffb1e95559 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Tue, 13 Sep 2016 16:30:57 +0800 Subject: [PATCH 1/9] Expand is_uninhabited for ! and tuples --- src/librustc/ty/sty.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 81896ecfb5341..af45a323eee61 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -929,16 +929,14 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn is_uninhabited(&self, _cx: TyCtxt) -> bool { + 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 { TyAdt(def, _) => def.is_empty(), - // FIXME(canndrew): There's no reason why these can't be uncommented, they're tested - // and they don't break anything. But I'm keeping my changes small for now. - //TyNever => true, - //TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited(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_uninhabited(cx), From d6482510f4ac179506370f421b2c3a3802f574f9 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Wed, 14 Sep 2016 23:58:58 +0800 Subject: [PATCH 2/9] Expand `is_uninhabited` to recurse into datatypes --- src/librustc/ty/mod.rs | 45 +++++++++++++++++++++++++++++++++++++----- src/librustc/ty/sty.rs | 15 ++++++++++++-- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e94e93158c47a..5737f776422d7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -16,6 +16,7 @@ pub use self::IntVarValue::*; pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; +use std::collections::{hash_map, HashMap}; use dep_graph::{self, DepNode}; use hir::map as ast_map; use middle; @@ -1389,6 +1390,20 @@ impl<'tcx> serialize::UseSpecializedEncodable for AdtDef<'tcx> { impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {} +impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> { + #[inline] + pub fn is_uninhabited_recurse(&'tcx self, + visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + cx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>) -> bool { + match visited.entry((self.did, substs)) { + hash_map::Entry::Occupied(_) => return true, + hash_map::Entry::Vacant(ve) => ve.insert(()), + }; + self.variants.iter().all(|v| v.is_uninhabited_recurse(visited, cx, substs, self.is_union())) + } +} + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum AdtKind { Struct, Union, Enum } @@ -1531,11 +1546,6 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> { self.variants.iter().flat_map(VariantDefData::fields_iter) } - #[inline] - pub fn is_empty(&self) -> bool { - self.variants.is_empty() - } - #[inline] pub fn is_univariant(&self) -> bool { self.variants.len() == 1 @@ -1795,6 +1805,21 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> { } } +impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> { + #[inline] + pub fn is_uninhabited_recurse(&'tcx self, + visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + cx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>, + is_union: bool) -> bool { + if is_union { + self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, cx, substs)) + } else { + self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, cx, substs)) + } + } +} + impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> { pub fn new(did: DefId, name: Name, @@ -1820,6 +1845,16 @@ impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> { } } +impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> { + #[inline] + pub fn is_uninhabited_recurse(&'tcx self, + visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + substs: &'tcx Substs<'tcx>) -> bool { + self.ty(tcx, substs).is_uninhabited_recurse(visited, tcx) + } +} + /// Records the substitutions used to translate the polytype for an /// item into the monotype of an item reference. #[derive(Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index af45a323eee61..53230eaf59dd3 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -21,6 +21,7 @@ use util::common::ErrorReported; use collections::enum_set::{self, EnumSet, CLike}; use std::fmt; use std::ops; +use std::collections::HashMap; use syntax::abi; use syntax::ast::{self, Name}; use syntax::symbol::{keywords, InternedString}; @@ -929,14 +930,24 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn is_uninhabited(&self, cx: TyCtxt) -> bool { + pub fn is_uninhabited(&self, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { + let mut visited = HashMap::new(); + self.is_uninhabited_recurse(&mut visited, cx) + } + + pub fn is_uninhabited_recurse(&self, + visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { // FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made // more complete. match self.sty { - TyAdt(def, _) => def.is_empty(), + TyAdt(def, substs) => { + def.is_uninhabited_recurse(visited, cx, substs) + }, TyNever => true, TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited(cx)), + TyArray(ty, len) => len > 0 && ty.is_uninhabited(cx), // FIXME(canndrew): this line breaks core::fmt //TyRef(_, ref tm) => tm.ty.is_uninhabited(cx), From 75140512ebe0138d630e4af52216352300d12d08 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Thu, 15 Sep 2016 01:10:53 +0800 Subject: [PATCH 3/9] Fix previous commit --- src/librustc/ty/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 5737f776422d7..68440a2c8d85b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1393,7 +1393,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {} impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> { #[inline] pub fn is_uninhabited_recurse(&'tcx self, - visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, cx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>) -> bool { match visited.entry((self.did, substs)) { From f1bdd4fae21e3053cedaa850691edd7a25a62dd2 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Thu, 15 Sep 2016 01:11:11 +0800 Subject: [PATCH 4/9] Expand is_uninhabited for references --- src/libcore/fmt/mod.rs | 8 +++++--- src/librustc/ty/sty.rs | 7 +++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 2d75a8ec420b1..9fcccacdbe137 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -178,8 +178,9 @@ enum Void {} issue = "0")] #[doc(hidden)] pub struct ArgumentV1<'a> { - value: &'a Void, - formatter: fn(&Void, &mut Formatter) -> Result, + _ph: PhantomData<&'a ()>, + value: *const Void, + formatter: fn(*const Void, &mut Formatter) -> Result, } #[unstable(feature = "fmt_internals", reason = "internal to format_args!", @@ -203,6 +204,7 @@ impl<'a> ArgumentV1<'a> { f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> { unsafe { ArgumentV1 { + _ph: PhantomData, formatter: mem::transmute(f), value: mem::transmute(x) } @@ -218,7 +220,7 @@ impl<'a> ArgumentV1<'a> { fn as_usize(&self) -> Option { if self.formatter as usize == ArgumentV1::show_usize as usize { - Some(unsafe { *(self.value as *const _ as *const usize) }) + Some(unsafe { *(self.value as *const usize) }) } else { None } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 53230eaf59dd3..39461dc4f74f5 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -946,11 +946,10 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { }, TyNever => true, - TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited(cx)), - TyArray(ty, len) => len > 0 && ty.is_uninhabited(cx), + TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, cx)), + TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, cx), + TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, cx), - // FIXME(canndrew): this line breaks core::fmt - //TyRef(_, ref tm) => tm.ty.is_uninhabited(cx), _ => false, } } From 5b20c6aec716abd1b1e8cd8750ae0d106db5f616 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Thu, 15 Sep 2016 01:41:45 +0800 Subject: [PATCH 5/9] Recursive types are always non-empty --- src/librustc/ty/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 68440a2c8d85b..f4a9087641851 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1397,7 +1397,7 @@ impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> { cx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>) -> bool { match visited.entry((self.did, substs)) { - hash_map::Entry::Occupied(_) => return true, + hash_map::Entry::Occupied(_) => return false, hash_map::Entry::Vacant(ve) => ve.insert(()), }; self.variants.iter().all(|v| v.is_uninhabited_recurse(visited, cx, substs, self.is_union())) From a6cc398207009884a2885855e79ba424c2f4c303 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Wed, 9 Nov 2016 17:55:11 +0800 Subject: [PATCH 6/9] Revert libcore changes, redefine Void instead --- src/libcore/fmt/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 9fcccacdbe137..c5116b996dd87 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -166,7 +166,9 @@ pub struct Formatter<'a> { // NB. Argument is essentially an optimized partially applied formatting function, // equivalent to `exists T.(&T, fn(&T, &mut Formatter) -> Result`. -enum Void {} +struct Void { + _private: (), +} /// This struct represents the generic "argument" which is taken by the Xprintf /// family of functions. It contains a function to format the given value. At @@ -178,9 +180,8 @@ enum Void {} issue = "0")] #[doc(hidden)] pub struct ArgumentV1<'a> { - _ph: PhantomData<&'a ()>, - value: *const Void, - formatter: fn(*const Void, &mut Formatter) -> Result, + value: &'a Void, + formatter: fn(&Void, &mut Formatter) -> Result, } #[unstable(feature = "fmt_internals", reason = "internal to format_args!", @@ -204,7 +205,6 @@ impl<'a> ArgumentV1<'a> { f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> { unsafe { ArgumentV1 { - _ph: PhantomData, formatter: mem::transmute(f), value: mem::transmute(x) } @@ -220,7 +220,7 @@ impl<'a> ArgumentV1<'a> { fn as_usize(&self) -> Option { if self.formatter as usize == ArgumentV1::show_usize as usize { - Some(unsafe { *(self.value as *const usize) }) + Some(unsafe { *(self.value as *const _ as *const usize) }) } else { None } From d756f61a5a7ab84d58fdaa9d53d84f6dad29f8db Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Wed, 9 Nov 2016 17:55:57 +0800 Subject: [PATCH 7/9] Make is_uninhabited respect privacy --- src/librustc/ty/mod.rs | 14 ++++++++++---- src/librustc/ty/sty.rs | 19 ++++++++++--------- src/librustc_const_eval/check_match.rs | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f4a9087641851..88eb4ec1014cb 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1394,13 +1394,16 @@ impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> { #[inline] pub fn is_uninhabited_recurse(&'tcx self, visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>) -> bool { match visited.entry((self.did, substs)) { hash_map::Entry::Occupied(_) => return false, hash_map::Entry::Vacant(ve) => ve.insert(()), }; - self.variants.iter().all(|v| v.is_uninhabited_recurse(visited, cx, substs, self.is_union())) + self.variants.iter().all(|v| { + v.is_uninhabited_recurse(visited, block, cx, substs, self.is_union()) + }) } } @@ -1809,13 +1812,14 @@ impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> { #[inline] pub fn is_uninhabited_recurse(&'tcx self, visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>, is_union: bool) -> bool { if is_union { - self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, cx, substs)) + self.fields.iter().all(|f| f.is_uninhabited_recurse(visited, block, cx, substs)) } else { - self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, cx, substs)) + self.fields.iter().any(|f| f.is_uninhabited_recurse(visited, block, cx, substs)) } } } @@ -1849,9 +1853,11 @@ impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> { #[inline] pub fn is_uninhabited_recurse(&'tcx self, visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + block: Option, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>) -> bool { - self.ty(tcx, substs).is_uninhabited_recurse(visited, tcx) + block.map_or(true, |b| self.vis.is_accessible_from(b, &tcx.map)) && + self.ty(tcx, substs).is_uninhabited_recurse(visited, block, tcx) } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 39461dc4f74f5..4e54e3a3630dd 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -23,7 +23,7 @@ use std::fmt; use std::ops; use std::collections::HashMap; use syntax::abi; -use syntax::ast::{self, Name}; +use syntax::ast::{self, Name, NodeId}; use syntax::symbol::{keywords, InternedString}; use serialize; @@ -930,25 +930,26 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } } - pub fn is_uninhabited(&self, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { + /// Checks whether a type is uninhabited. + /// If `block` is `Some(id)` it also checks that the uninhabited-ness is visible from `id`. + pub fn is_uninhabited(&self, block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { let mut visited = HashMap::new(); - self.is_uninhabited_recurse(&mut visited, cx) + self.is_uninhabited_recurse(&mut visited, block, cx) } pub fn is_uninhabited_recurse(&self, visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { - // FIXME(#24885): be smarter here, the AdtDefData::is_empty method could easily be made - // more complete. match self.sty { TyAdt(def, substs) => { - def.is_uninhabited_recurse(visited, cx, substs) + def.is_uninhabited_recurse(visited, block, cx, substs) }, TyNever => true, - TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, cx)), - TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, cx), - TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, cx), + TyTuple(ref tys) => tys.iter().any(|ty| ty.is_uninhabited_recurse(visited, block, cx)), + TyArray(ty, len) => len > 0 && ty.is_uninhabited_recurse(visited, block, cx), + TyRef(_, ref tm) => tm.ty.is_uninhabited_recurse(visited, block, cx), _ => false, } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index f63a27e0d7563..3c94d7d6fd5d1 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -204,7 +204,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Check for empty enum, because is_useful only works on inhabited types. let pat_ty = self.tcx.tables().node_id_to_type(scrut.id); if inlined_arms.is_empty() { - if !pat_ty.is_uninhabited(self.tcx) { + if !pat_ty.is_uninhabited(Some(scrut.id), self.tcx) { // We know the type is inhabited, so this must be wrong let mut err = create_e0004(self.tcx.sess, span, format!("non-exhaustive patterns: type {} \ From 2afec4dad1e80b3e53256306822f7849b7b9d128 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Tue, 22 Nov 2016 14:39:56 +0800 Subject: [PATCH 8/9] Use FxHashSet instead of HashMap --- src/librustc/ty/mod.rs | 14 ++++++-------- src/librustc/ty/sty.rs | 6 +++--- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 88eb4ec1014cb..d3864539c75a8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -16,7 +16,6 @@ pub use self::IntVarValue::*; pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; -use std::collections::{hash_map, HashMap}; use dep_graph::{self, DepNode}; use hir::map as ast_map; use middle; @@ -31,7 +30,7 @@ use ty::subst::{Subst, Substs}; use ty::walk::TypeWalker; use util::common::MemoizationMap; use util::nodemap::NodeSet; -use util::nodemap::FxHashMap; +use util::nodemap::{FxHashMap, FxHashSet}; use serialize::{self, Encodable, Encoder}; use std::borrow::Cow; @@ -1393,13 +1392,12 @@ impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {} impl<'a, 'gcx, 'tcx> AdtDefData<'tcx, 'static> { #[inline] pub fn is_uninhabited_recurse(&'tcx self, - visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>) -> bool { - match visited.entry((self.did, substs)) { - hash_map::Entry::Occupied(_) => return false, - hash_map::Entry::Vacant(ve) => ve.insert(()), + if !visited.insert((self.did, substs)) { + return false; }; self.variants.iter().all(|v| { v.is_uninhabited_recurse(visited, block, cx, substs, self.is_union()) @@ -1811,7 +1809,7 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> { impl<'a, 'gcx, 'tcx> VariantDefData<'tcx, 'static> { #[inline] pub fn is_uninhabited_recurse(&'tcx self, - visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>, @@ -1852,7 +1850,7 @@ impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> { impl<'a, 'gcx, 'tcx> FieldDefData<'tcx, 'static> { #[inline] pub fn is_uninhabited_recurse(&'tcx self, - visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, block: Option, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &'tcx Substs<'tcx>) -> bool { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 4e54e3a3630dd..cb3176cce10bd 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -21,10 +21,10 @@ use util::common::ErrorReported; use collections::enum_set::{self, EnumSet, CLike}; use std::fmt; use std::ops; -use std::collections::HashMap; use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::symbol::{keywords, InternedString}; +use util::nodemap::FxHashSet; use serialize; @@ -933,12 +933,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { /// Checks whether a type is uninhabited. /// If `block` is `Some(id)` it also checks that the uninhabited-ness is visible from `id`. pub fn is_uninhabited(&self, block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { - let mut visited = HashMap::new(); + let mut visited = FxHashSet::default(); self.is_uninhabited_recurse(&mut visited, block, cx) } pub fn is_uninhabited_recurse(&self, - visited: &mut HashMap<(DefId, &'tcx Substs<'tcx>), ()>, + visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>, block: Option, cx: TyCtxt<'a, 'gcx, 'tcx>) -> bool { match self.sty { From 2121118f5401d84975f7910e0b71b32e74b990ec Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Wed, 23 Nov 2016 17:13:12 +0800 Subject: [PATCH 9/9] Revert libcore changes --- src/libcore/fmt/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index c5116b996dd87..2d75a8ec420b1 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -166,9 +166,7 @@ pub struct Formatter<'a> { // NB. Argument is essentially an optimized partially applied formatting function, // equivalent to `exists T.(&T, fn(&T, &mut Formatter) -> Result`. -struct Void { - _private: (), -} +enum Void {} /// This struct represents the generic "argument" which is taken by the Xprintf /// family of functions. It contains a function to format the given value. At