From 5d56e1daed3aab8149ecbf69baf5bc1785f08627 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Tue, 5 Apr 2016 14:06:20 +0200 Subject: [PATCH 01/14] Specialize equality for [T] and comparison for [u8] Where T is a type that can be compared for equality bytewise, we can use memcmp. We can also use memcmp for PartialOrd, Ord for [u8] and by extension &str. This is an improvement for example for the comparison [u8] == [u8] that used to emit a loop that compared the slices byte by byte. One worry here could be that this introduces function calls to memcmp in contexts where it should really inline the comparison or even optimize it out, but llvm takes care of recognizing memcmp specifically. --- src/libcore/lib.rs | 1 + src/libcore/slice.rs | 167 +++++++++++++++++++++++++++++++++++------ src/libcore/str/mod.rs | 25 +----- 3 files changed, 147 insertions(+), 46 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 648b652772a..fa5e90562d8 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -75,6 +75,7 @@ #![feature(unwind_attributes)] #![feature(repr_simd, platform_intrinsics)] #![feature(rustc_attrs)] +#![feature(specialization)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(question_mark)] diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index aa555b44e89..e9cf650af70 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1630,12 +1630,59 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] { } // -// Boilerplate traits +// Comparison traits // +extern { + /// Call implementation provided memcmp + /// + /// Interprets the data as u8. + /// + /// Return 0 for equal, < 0 for less than and > 0 for greater + /// than. + // FIXME(#32610): Return type should be c_int + fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32; +} + #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq<[B]> for [A] where A: PartialEq { fn eq(&self, other: &[B]) -> bool { + SlicePartialEq::equal(self, other) + } + + fn ne(&self, other: &[B]) -> bool { + SlicePartialEq::not_equal(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for [T] {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for [T] { + fn cmp(&self, other: &[T]) -> Ordering { + SliceOrd::compare(self, other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for [T] { + fn partial_cmp(&self, other: &[T]) -> Option { + SlicePartialOrd::partial_compare(self, other) + } +} + +// intermediate trait for specialization of slice's PartialEq +trait SlicePartialEq { + fn equal(&self, other: &[B]) -> bool; + fn not_equal(&self, other: &[B]) -> bool; +} + +// Generic slice equality +impl SlicePartialEq for [A] + where A: PartialEq +{ + default fn equal(&self, other: &[B]) -> bool { if self.len() != other.len() { return false; } @@ -1648,7 +1695,8 @@ impl PartialEq<[B]> for [A] where A: PartialEq { true } - fn ne(&self, other: &[B]) -> bool { + + default fn not_equal(&self, other: &[B]) -> bool { if self.len() != other.len() { return true; } @@ -1663,12 +1711,69 @@ impl PartialEq<[B]> for [A] where A: PartialEq { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for [T] {} +// Use memcmp for bytewise equality when the types allow +impl SlicePartialEq for [A] + where A: PartialEq + BytewiseEquality +{ + fn equal(&self, other: &[A]) -> bool { + if self.len() != other.len() { + return false; + } + unsafe { + let size = mem::size_of_val(self); + memcmp(self.as_ptr() as *const u8, + other.as_ptr() as *const u8, size) == 0 + } + } -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for [T] { - fn cmp(&self, other: &[T]) -> Ordering { + fn not_equal(&self, other: &[A]) -> bool { + !self.equal(other) + } +} + +// intermediate trait for specialization of slice's PartialOrd +trait SlicePartialOrd { + fn partial_compare(&self, other: &[B]) -> Option; +} + +impl SlicePartialOrd for [A] + where A: PartialOrd +{ + default fn partial_compare(&self, other: &[A]) -> Option { + let l = cmp::min(self.len(), other.len()); + + // Slice to the loop iteration range to enable bound check + // elimination in the compiler + let lhs = &self[..l]; + let rhs = &other[..l]; + + for i in 0..l { + match lhs[i].partial_cmp(&rhs[i]) { + Some(Ordering::Equal) => (), + non_eq => return non_eq, + } + } + + self.len().partial_cmp(&other.len()) + } +} + +impl SlicePartialOrd for [u8] { + #[inline] + fn partial_compare(&self, other: &[u8]) -> Option { + Some(SliceOrd::compare(self, other)) + } +} + +// intermediate trait for specialization of slice's Ord +trait SliceOrd { + fn compare(&self, other: &[B]) -> Ordering; +} + +impl SliceOrd for [A] + where A: Ord +{ + default fn compare(&self, other: &[A]) -> Ordering { let l = cmp::min(self.len(), other.len()); // Slice to the loop iteration range to enable bound check @@ -1687,23 +1792,37 @@ impl Ord for [T] { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for [T] { - fn partial_cmp(&self, other: &[T]) -> Option { - let l = cmp::min(self.len(), other.len()); - - // Slice to the loop iteration range to enable bound check - // elimination in the compiler - let lhs = &self[..l]; - let rhs = &other[..l]; - - for i in 0..l { - match lhs[i].partial_cmp(&rhs[i]) { - Some(Ordering::Equal) => (), - non_eq => return non_eq, - } +// memcmp compares a sequence of unsigned bytes lexicographically. +// this matches the order we want for [u8], but no others (not even [i8]). +impl SliceOrd for [u8] { + #[inline] + fn compare(&self, other: &[u8]) -> Ordering { + let order = unsafe { + memcmp(self.as_ptr(), other.as_ptr(), + cmp::min(self.len(), other.len())) + }; + if order == 0 { + self.len().cmp(&other.len()) + } else if order < 0 { + Less + } else { + Greater } - - self.len().partial_cmp(&other.len()) } } + +/// Trait implemented for types that can be compared for equality using +/// their bytewise representation +trait BytewiseEquality { } + +macro_rules! impl_marker_for { + ($traitname:ident, $($ty:ty)*) => { + $( + impl $traitname for $ty { } + )* + } +} + +impl_marker_for!(BytewiseEquality, + u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool); + diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d5a5e2b4741..305546df5be 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1150,16 +1150,7 @@ Section: Comparing strings #[lang = "str_eq"] #[inline] fn eq_slice(a: &str, b: &str) -> bool { - a.len() == b.len() && unsafe { cmp_slice(a, b, a.len()) == 0 } -} - -/// Bytewise slice comparison. -/// NOTE: This uses the system's memcmp, which is currently dramatically -/// faster than comparing each byte in a loop. -#[inline] -unsafe fn cmp_slice(a: &str, b: &str, len: usize) -> i32 { - extern { fn memcmp(s1: *const i8, s2: *const i8, n: usize) -> i32; } - memcmp(a.as_ptr() as *const i8, b.as_ptr() as *const i8, len) + a.as_bytes() == b.as_bytes() } /* @@ -1328,8 +1319,7 @@ Section: Trait implementations */ mod traits { - use cmp::{self, Ordering, Ord, PartialEq, PartialOrd, Eq}; - use cmp::Ordering::{Less, Greater}; + use cmp::{Ord, Ordering, PartialEq, PartialOrd, Eq}; use iter::Iterator; use option::Option; use option::Option::Some; @@ -1340,16 +1330,7 @@ mod traits { impl Ord for str { #[inline] fn cmp(&self, other: &str) -> Ordering { - let cmp = unsafe { - super::cmp_slice(self, other, cmp::min(self.len(), other.len())) - }; - if cmp == 0 { - self.len().cmp(&other.len()) - } else if cmp < 0 { - Less - } else { - Greater - } + self.as_bytes().cmp(other.as_bytes()) } } From 28c4d12c031aba96acf72d30dfaa22a51fcf719e Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Tue, 5 Apr 2016 14:06:20 +0200 Subject: [PATCH 02/14] Add test for [u8]'s Ord (and fix the old test for ord) The old test for Ord used no asserts, and appeared to have a wrong test. (!). --- src/libcollectionstest/slice.rs | 42 ++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/libcollectionstest/slice.rs b/src/libcollectionstest/slice.rs index ca2ee0c512b..236c151891d 100644 --- a/src/libcollectionstest/slice.rs +++ b/src/libcollectionstest/slice.rs @@ -574,18 +574,48 @@ fn test_slice_2() { assert_eq!(v[1], 3); } +macro_rules! assert_order { + (Greater, $a:expr, $b:expr) => { + assert_eq!($a.cmp($b), Greater); + assert!($a > $b); + }; + (Less, $a:expr, $b:expr) => { + assert_eq!($a.cmp($b), Less); + assert!($a < $b); + }; + (Equal, $a:expr, $b:expr) => { + assert_eq!($a.cmp($b), Equal); + assert_eq!($a, $b); + } +} + #[test] -fn test_total_ord() { +fn test_total_ord_u8() { + let c = &[1u8, 2, 3]; + assert_order!(Greater, &[1u8, 2, 3, 4][..], &c[..]); + let c = &[1u8, 2, 3, 4]; + assert_order!(Less, &[1u8, 2, 3][..], &c[..]); + let c = &[1u8, 2, 3, 6]; + assert_order!(Equal, &[1u8, 2, 3, 6][..], &c[..]); + let c = &[1u8, 2, 3, 4, 5, 6]; + assert_order!(Less, &[1u8, 2, 3, 4, 5, 5, 5, 5][..], &c[..]); + let c = &[1u8, 2, 3, 4]; + assert_order!(Greater, &[2u8, 2][..], &c[..]); +} + + +#[test] +fn test_total_ord_i32() { let c = &[1, 2, 3]; - [1, 2, 3, 4][..].cmp(c) == Greater; + assert_order!(Greater, &[1, 2, 3, 4][..], &c[..]); let c = &[1, 2, 3, 4]; - [1, 2, 3][..].cmp(c) == Less; + assert_order!(Less, &[1, 2, 3][..], &c[..]); let c = &[1, 2, 3, 6]; - [1, 2, 3, 4][..].cmp(c) == Equal; + assert_order!(Equal, &[1, 2, 3, 6][..], &c[..]); let c = &[1, 2, 3, 4, 5, 6]; - [1, 2, 3, 4, 5, 5, 5, 5][..].cmp(c) == Less; + assert_order!(Less, &[1, 2, 3, 4, 5, 5, 5, 5][..], &c[..]); let c = &[1, 2, 3, 4]; - [2, 2][..].cmp(c) == Greater; + assert_order!(Greater, &[2, 2][..], &c[..]); } #[test] From af047d9c10be73ca9f450b2e3aa2c5c62483981c Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 5 Apr 2016 14:00:17 +0100 Subject: [PATCH 03/14] Fix infinite loop in Arc::downgrade --- src/liballoc/arc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 055029dddcd..e1f698cb484 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -263,6 +263,7 @@ impl Arc { loop { // check if the weak counter is currently "locked"; if so, spin. if cur == usize::MAX { + cur = this.inner().weak.load(Relaxed); continue; } From 9ba3d5e9212bb67166d137efd58fcf5d06906c2a Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Tue, 5 Apr 2016 08:38:48 -0700 Subject: [PATCH 04/14] Reinstate fast_reject for overlap checking The initial implementation of specialization did not use the `fast_reject` mechanism when checking for overlap, which caused a serious performance regression in some cases. This commit modifies the specialization graph to use simplified types for fast rejection when possible, and along the way refactors the logic for building the specialization graph. Closes #32499 --- .../traits/specialize/specialization_graph.rs | 201 +++++++++++++----- src/librustc/ty/trait_def.rs | 27 ++- 2 files changed, 160 insertions(+), 68 deletions(-) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index eaafeb1a969..9584c5ea193 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -18,8 +18,9 @@ use middle::def_id::DefId; use infer; use traits::{self, ProjectionMode}; use ty::{self, TyCtxt, ImplOrTraitItem, TraitDef, TypeFoldable}; +use ty::fast_reject::{self, SimplifiedType}; use syntax::ast::Name; -use util::nodemap::DefIdMap; +use util::nodemap::{DefIdMap, FnvHashMap}; /// A per-trait graph of impls in specialization order. At the moment, this /// graph forms a tree rooted with the trait itself, with all other nodes @@ -42,7 +43,124 @@ pub struct Graph { parent: DefIdMap, // the "root" impls are found by looking up the trait's def_id. - children: DefIdMap>, + children: DefIdMap, +} + +/// Children of a given impl, grouped into blanket/non-blanket varieties as is +/// done in `TraitDef`. +struct Children { + // Impls of a trait (or specializations of a given impl). To allow for + // quicker lookup, the impls are indexed by a simplified version of their + // `Self` type: impls with a simplifiable `Self` are stored in + // `nonblanket_impls` keyed by it, while all other impls are stored in + // `blanket_impls`. + // + // A similar division is used within `TraitDef`, but the lists there collect + // together *all* the impls for a trait, and are populated prior to building + // the specialization graph. + + /// Impls of the trait. + nonblanket_impls: FnvHashMap>, + + /// Blanket impls associated with the trait. + blanket_impls: Vec, +} + +/// The result of attempting to insert an impl into a group of children. +enum InsertResult<'a, 'tcx: 'a> { + /// The impl was inserted as a new child in this group of children. + BecameNewSibling, + + /// The impl replaced an existing impl that specializes it. + Replaced(DefId), + + /// The impl is a specialization of an existing child. + ShouldRecurseOn(DefId), + + /// The impl has an unresolvable overlap with an existing child (neither + /// specializes the other). + Overlapped(Overlap<'a, 'tcx>), +} + +impl Children { + fn new() -> Children { + Children { + nonblanket_impls: FnvHashMap(), + blanket_impls: vec![], + } + } + + /// Insert an impl into this set of children without comparing to any existing impls + fn insert_blindly(&mut self, tcx: &TyCtxt, impl_def_id: DefId) { + let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + if let Some(sty) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + self.nonblanket_impls.entry(sty).or_insert(vec![]).push(impl_def_id) + } else { + self.blanket_impls.push(impl_def_id) + } + } + + /// Attempt to insert an impl into this set of children, while comparing for + /// specialiation relationships. + fn insert<'a, 'tcx>(&mut self, + tcx: &'a TyCtxt<'tcx>, + impl_def_id: DefId, + simplified_self: Option) + -> InsertResult<'a, 'tcx> + { + for slot in match simplified_self { + Some(sty) => self.filtered_mut(sty), + None => self.iter_mut(), + } { + let possible_sibling = *slot; + + let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::Topmost); + let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); + + if let Some(impl_header) = overlap { + let le = specializes(tcx, impl_def_id, possible_sibling); + let ge = specializes(tcx, possible_sibling, impl_def_id); + + if le && !ge { + debug!("descending as child of TraitRef {:?}", + tcx.impl_trait_ref(possible_sibling).unwrap()); + + // the impl specializes possible_sibling + return InsertResult::ShouldRecurseOn(possible_sibling); + } else if ge && !le { + debug!("placing as parent of TraitRef {:?}", + tcx.impl_trait_ref(possible_sibling).unwrap()); + + // possible_sibling specializes the impl + *slot = impl_def_id; + return InsertResult::Replaced(possible_sibling); + } else { + // overlap, but no specialization; error out + return InsertResult::Overlapped(Overlap { + with_impl: possible_sibling, + on_trait_ref: impl_header.trait_ref.unwrap(), + in_context: infcx, + }); + } + } + } + + // no overlap with any potential siblings, so add as a new sibling + debug!("placing as new sibling"); + self.insert_blindly(tcx, impl_def_id); + InsertResult::BecameNewSibling + } + + fn iter_mut<'a>(&'a mut self) -> Box + 'a> { + let nonblanket = self.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter_mut()); + Box::new(self.blanket_impls.iter_mut().chain(nonblanket)) + } + + fn filtered_mut<'a>(&'a mut self, sty: SimplifiedType) + -> Box + 'a> { + let nonblanket = self.nonblanket_impls.entry(sty).or_insert(vec![]).iter_mut(); + Box::new(self.blanket_impls.iter_mut().chain(nonblanket)) + } } impl Graph { @@ -78,78 +196,53 @@ impl Graph { trait_ref, impl_def_id, trait_def_id); self.parent.insert(impl_def_id, trait_def_id); - self.children.entry(trait_def_id).or_insert(vec![]).push(impl_def_id); + self.children.entry(trait_def_id).or_insert(Children::new()) + .insert_blindly(tcx, impl_def_id); return Ok(()); } let mut parent = trait_def_id; + let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false); - // Ugly hack around borrowck limitations. Assigned only in the case - // where we bump downward an existing node in the graph. - let child_to_insert; + // Descend the specialization tree, where `parent` is the current parent node + loop { + use self::InsertResult::*; - 'descend: loop { - let mut possible_siblings = self.children.entry(parent).or_insert(vec![]); + let insert_result = self.children.entry(parent).or_insert(Children::new()) + .insert(tcx, impl_def_id, simplified); - for slot in possible_siblings.iter_mut() { - let possible_sibling = *slot; - - let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, ProjectionMode::Topmost); - let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); - - if let Some(impl_header) = overlap { - let le = specializes(tcx, impl_def_id, possible_sibling); - let ge = specializes(tcx, possible_sibling, impl_def_id); - - if le && !ge { - debug!("descending as child of TraitRef {:?}", - tcx.impl_trait_ref(possible_sibling).unwrap()); - - // the impl specializes possible_sibling - parent = possible_sibling; - continue 'descend; - } else if ge && !le { - debug!("placing as parent of TraitRef {:?}", - tcx.impl_trait_ref(possible_sibling).unwrap()); - - // possible_sibling specializes the impl - *slot = impl_def_id; - self.parent.insert(impl_def_id, parent); - self.parent.insert(possible_sibling, impl_def_id); - // we have to defer the insertion, because we can't - // relinquish the borrow of `self.children` - child_to_insert = possible_sibling; - break 'descend; - } else { - // overlap, but no specialization; error out - return Err(Overlap { - with_impl: possible_sibling, - on_trait_ref: impl_header.trait_ref.unwrap(), - in_context: infcx, - }); - } + match insert_result { + BecameNewSibling => { + break; + } + Replaced(new_child) => { + self.parent.insert(new_child, impl_def_id); + let mut new_children = Children::new(); + new_children.insert_blindly(tcx, new_child); + self.children.insert(impl_def_id, new_children); + break; + } + ShouldRecurseOn(new_parent) => { + parent = new_parent; + } + Overlapped(error) => { + return Err(error); } } - - // no overlap with any potential siblings, so add as a new sibling - debug!("placing as new sibling"); - self.parent.insert(impl_def_id, parent); - possible_siblings.push(impl_def_id); - return Ok(()); } - self.children.insert(impl_def_id, vec![child_to_insert]); + self.parent.insert(impl_def_id, parent); Ok(()) } /// Insert cached metadata mapping from a child impl back to its parent. - pub fn record_impl_from_cstore(&mut self, parent: DefId, child: DefId) { + pub fn record_impl_from_cstore(&mut self, tcx: &TyCtxt, parent: DefId, child: DefId) { if self.parent.insert(child, parent).is_some() { panic!("When recording an impl from the crate store, information about its parent \ was already present."); } - self.children.entry(parent).or_insert(vec![]).push(child); + self.children.entry(parent).or_insert(Children::new()).insert_blindly(tcx, child); } /// The parent of a given impl, which is the def id of the trait when the diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 3ebf2ba4c84..51f330686db 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -15,7 +15,7 @@ use ty; use ty::fast_reject; use ty::{Ty, TyCtxt, TraitRef}; use std::borrow::{Borrow}; -use std::cell::{Cell, Ref, RefCell}; +use std::cell::{Cell, RefCell}; use syntax::ast::Name; use rustc_front::hir; use util::nodemap::FnvHashMap; @@ -43,10 +43,17 @@ pub struct TraitDef<'tcx> { /// for resolving `X::Foo` type markers. pub associated_type_names: Vec, - // Impls of this trait. To allow for quicker lookup, the impls are indexed - // by a simplified version of their Self type: impls with a simplifiable - // Self are stored in nonblanket_impls keyed by it, while all other impls - // are stored in blanket_impls. + // Impls of a trait. To allow for quicker lookup, the impls are indexed by a + // simplified version of their `Self` type: impls with a simplifiable `Self` + // are stored in `nonblanket_impls` keyed by it, while all other impls are + // stored in `blanket_impls`. + // + // A similar division is used within `specialization_graph`, but the ones + // here are (1) stored as a flat list for the trait and (2) populated prior + // to -- and used while -- determining specialization order. + // + // FIXME: solve the reentrancy issues and remove these lists in favor of the + // ones in `specialization_graph`. // // These lists are tracked by `DepNode::TraitImpls`; we don't use // a DepTrackingMap but instead have the `TraitDef` insert the @@ -184,7 +191,7 @@ impl<'tcx> TraitDef<'tcx> { // if the impl is non-local, it's placed directly into the // specialization graph using parent information drawn from metadata. self.specialization_graph.borrow_mut() - .record_impl_from_cstore(parent_impl, impl_def_id) + .record_impl_from_cstore(tcx, parent_impl, impl_def_id) } } @@ -261,14 +268,6 @@ impl<'tcx> TraitDef<'tcx> { } } } - - pub fn borrow_impl_lists<'s>(&'s self, tcx: &TyCtxt<'tcx>) - -> (Ref<'s, Vec>, - Ref<'s, FnvHashMap>>) { - self.read_trait_impls(tcx); - (self.blanket_impls.borrow(), self.nonblanket_impls.borrow()) - } - } bitflags! { From 4883824dc575eb2068d8b1208bc02ee02d16ec7f Mon Sep 17 00:00:00 2001 From: JP Sugarbroad Date: Tue, 5 Apr 2016 17:06:10 -0700 Subject: [PATCH 05/14] Fix typos in atomic compare_exchange. --- src/libcore/sync/atomic.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index d2e98a795d9..483c3822df6 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -327,7 +327,7 @@ impl AtomicBool { /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this /// operation. The first describes the required ordering if the operation succeeds while the /// second describes the required ordering when the operation fails. The failure ordering can't - /// be `Acquire` or `AcqRel` and must be equivalent or weaker than the success ordering. + /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering. /// /// # Examples /// @@ -376,7 +376,7 @@ impl AtomicBool { /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory /// ordering of this operation. The first describes the required ordering if the operation /// succeeds while the second describes the required ordering when the operation fails. The - /// failure ordering can't be `Acquire` or `AcqRel` and must be equivalent or weaker than the + /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the /// success ordering. /// /// # Examples @@ -663,7 +663,7 @@ impl AtomicIsize { /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this /// operation. The first describes the required ordering if the operation succeeds while the /// second describes the required ordering when the operation fails. The failure ordering can't - /// be `Acquire` or `AcqRel` and must be equivalent or weaker than the success ordering. + /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering. /// /// # Examples /// @@ -705,7 +705,7 @@ impl AtomicIsize { /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory /// ordering of this operation. The first describes the required ordering if the operation /// succeeds while the second describes the required ordering when the operation fails. The - /// failure ordering can't be `Acquire` or `AcqRel` and must be equivalent or weaker than the + /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the /// success ordering. /// /// # Examples @@ -939,7 +939,7 @@ impl AtomicUsize { /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this /// operation. The first describes the required ordering if the operation succeeds while the /// second describes the required ordering when the operation fails. The failure ordering can't - /// be `Acquire` or `AcqRel` and must be equivalent or weaker than the success ordering. + /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering. /// /// # Examples /// @@ -981,7 +981,7 @@ impl AtomicUsize { /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory /// ordering of this operation. The first describes the required ordering if the operation /// succeeds while the second describes the required ordering when the operation fails. The - /// failure ordering can't be `Acquire` or `AcqRel` and must be equivalent or weaker than the + /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the /// success ordering. /// /// # Examples @@ -1223,7 +1223,7 @@ impl AtomicPtr { /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this /// operation. The first describes the required ordering if the operation succeeds while the /// second describes the required ordering when the operation fails. The failure ordering can't - /// be `Acquire` or `AcqRel` and must be equivalent or weaker than the success ordering. + /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering. /// /// # Examples /// @@ -1270,7 +1270,7 @@ impl AtomicPtr { /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory /// ordering of this operation. The first describes the required ordering if the operation /// succeeds while the second describes the required ordering when the operation fails. The - /// failure ordering can't be `Acquire` or `AcqRel` and must be equivalent or weaker than the + /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the /// success ordering. /// /// # Examples @@ -1396,8 +1396,8 @@ unsafe fn atomic_compare_exchange(dst: *mut T, (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new), (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new), - (_, Release) => panic!("there is no such thing as an acquire/release failure ordering"), - (_, AcqRel) => panic!("there is no such thing as a release failure ordering"), + (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), + (_, Release) => panic!("there is no such thing as a release failure ordering"), _ => panic!("a failure ordering can't be stronger than a success ordering"), }; if ok { @@ -1446,8 +1446,8 @@ unsafe fn atomic_compare_exchange_weak(dst: *mut T, (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new), (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new), (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new), - (_, Release) => panic!("there is no such thing as an acquire/release failure ordering"), - (_, AcqRel) => panic!("there is no such thing as a release failure ordering"), + (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"), + (_, Release) => panic!("there is no such thing as a release failure ordering"), _ => panic!("a failure ordering can't be stronger than a success ordering"), }; if ok { From a6c27be0b1074684ae918ab7132bbeb8f75d4f2a Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Wed, 6 Apr 2016 12:19:19 +0200 Subject: [PATCH 06/14] slice: Use doc(hidden) on private traits This should avoid the trait impls showing up in rustdoc. --- src/libcore/slice.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index e9cf650af70..25082eed2fe 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1672,6 +1672,7 @@ impl PartialOrd for [T] { } } +#[doc(hidden)] // intermediate trait for specialization of slice's PartialEq trait SlicePartialEq { fn equal(&self, other: &[B]) -> bool; @@ -1731,6 +1732,7 @@ impl SlicePartialEq for [A] } } +#[doc(hidden)] // intermediate trait for specialization of slice's PartialOrd trait SlicePartialOrd { fn partial_compare(&self, other: &[B]) -> Option; @@ -1765,6 +1767,7 @@ impl SlicePartialOrd for [u8] { } } +#[doc(hidden)] // intermediate trait for specialization of slice's Ord trait SliceOrd { fn compare(&self, other: &[B]) -> Ordering; @@ -1811,6 +1814,7 @@ impl SliceOrd for [u8] { } } +#[doc(hidden)] /// Trait implemented for types that can be compared for equality using /// their bytewise representation trait BytewiseEquality { } From 20ee53c2f1570eac8b3221865d83bfa5993f6a70 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 7 Apr 2016 00:42:29 +0000 Subject: [PATCH 07/14] Improve path resolution diagnostics --- src/librustc_resolve/lib.rs | 131 ++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 98e40d73133..e8adb1d94ba 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1716,9 +1716,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { match self.resolve_crate_relative_path(prefix.span, &prefix.segments, TypeNS) { - Some(def) => + Ok(def) => self.record_def(item.id, PathResolution::new(def, 0)), - None => { + Err(true) => self.record_def(item.id, err_path_resolution()), + Err(false) => { resolve_error(self, prefix.span, ResolutionError::FailedToResolve( @@ -1837,7 +1838,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trait_path: &Path, path_depth: usize) -> Result { - if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS) { + self.resolve_path(id, trait_path, path_depth, TypeNS).and_then(|path_res| { if let Def::Trait(_) = path_res.base_def { debug!("(resolving trait) found trait def: {:?}", path_res); Ok(path_res) @@ -1857,9 +1858,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } err.emit(); - Err(()) + Err(true) } - } else { + }).map_err(|error_reported| { + if error_reported { return } // find possible candidates let trait_name = trait_path.segments.last().unwrap().identifier.name; @@ -1882,8 +1884,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ); resolve_error(self, trait_path.span, error); - Err(()) - } + }) } fn resolve_generics(&mut self, generics: &Generics) { @@ -1892,15 +1893,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &hir::WherePredicate::BoundPredicate(_) | &hir::WherePredicate::RegionPredicate(_) => {} &hir::WherePredicate::EqPredicate(ref eq_pred) => { - let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS); - if let Some(PathResolution { base_def: Def::TyParam(..), .. }) = path_res { - self.record_def(eq_pred.id, path_res.unwrap()); - } else { - resolve_error(self, - eq_pred.span, - ResolutionError::UndeclaredAssociatedType); + self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS).and_then(|path_res| { + if let PathResolution { base_def: Def::TyParam(..), .. } = path_res { + Ok(self.record_def(eq_pred.id, path_res)) + } else { + Err(false) + } + }).map_err(|error_reported| { self.record_def(eq_pred.id, err_path_resolution()); - } + if error_reported { return } + resolve_error(self, eq_pred.span, ResolutionError::UndeclaredAssociatedType); + }).unwrap_or(()); } } } @@ -2170,21 +2173,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This is a path in the type namespace. Walk through scopes // looking for it. - match resolution { - Some(def) => { - // Write the result into the def map. - debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}", - path_names_to_string(path, 0), - ty.id, - def); - self.record_def(ty.id, def); - } - None => { - self.record_def(ty.id, err_path_resolution()); - - // Keep reporting some errors even if they're ignored above. - self.resolve_path(ty.id, path, 0, TypeNS); + if let Some(def) = resolution { + // Write the result into the def map. + debug!("(resolving type) writing resolution for `{}` (id {}) = {:?}", + path_names_to_string(path, 0), ty.id, def); + self.record_def(ty.id, def); + } else { + self.record_def(ty.id, err_path_resolution()); + // Keep reporting some errors even if they're ignored above. + if let Err(true) = self.resolve_path(ty.id, path, 0, TypeNS) { + // `resolve_path` already reported the error + } else { let kind = if maybe_qself.is_some() { "associated type" } else { @@ -2483,11 +2483,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PatKind::Struct(ref path, _, _) => { match self.resolve_path(pat_id, path, 0, TypeNS) { - Some(definition) => { + Ok(definition) => { self.record_def(pattern.id, definition); } - result => { - debug!("(resolving pattern) didn't find struct def: {:?}", result); + Err(true) => self.record_def(pattern.id, err_path_resolution()), + Err(false) => { resolve_error( self, path.span, @@ -2554,14 +2554,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let mut resolution = self.with_no_errors(|this| { - this.resolve_path(id, path, 0, namespace) + this.resolve_path(id, path, 0, namespace).ok() }); for depth in 1..max_assoc_types { if resolution.is_some() { break; } self.with_no_errors(|this| { - resolution = this.resolve_path(id, path, depth, TypeNS); + resolution = this.resolve_path(id, path, depth, TypeNS).ok(); }); } if let Some(Def::Mod(_)) = resolution.map(|r| r.base_def) { @@ -2574,7 +2574,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Skips `path_depth` trailing segments, which is also reflected in the /// returned value. See `middle::def::PathResolution` for more info. fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace) - -> Option { + -> Result { let span = path.span; let segments = &path.segments[..path.segments.len() - path_depth]; @@ -2613,14 +2613,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // // Such behavior is required for backward compatibility. // The same fallback is used when `a` resolves to nothing. - let unqualified_def = resolve_identifier_with_fallback(self, true); - return unqualified_def.and_then(|def| self.adjust_local_def(def, span)).map(mk_res); + let def = resolve_identifier_with_fallback(self, true).ok_or(false); + return def.and_then(|def| self.adjust_local_def(def, span).ok_or(true)).map(mk_res); } let unqualified_def = resolve_identifier_with_fallback(self, false); let def = self.resolve_module_relative_path(span, segments, namespace); match (def, unqualified_def) { - (Some(d), Some(ref ud)) if d == ud.def => { + (Ok(d), Some(ref ud)) if d == ud.def => { self.session .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, id, @@ -2741,7 +2741,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span: Span, segments: &[hir::PathSegment], namespace: Namespace) - -> Option { + -> Result { let module_path = segments.split_last() .unwrap() .1 @@ -2762,9 +2762,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); - return None; + return Err(true); } - Indeterminate => return None, + Indeterminate => return Err(false), Success(resulting_module) => { containing_module = resulting_module; } @@ -2775,7 +2775,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result.success().map(|binding| { self.check_privacy(containing_module, name, binding, span); binding.def().unwrap() - }) + }).ok_or(false) } /// Invariant: This must be called only during main resolution, not during @@ -2784,7 +2784,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span: Span, segments: &[hir::PathSegment], namespace: Namespace) - -> Option { + -> Result { let module_path = segments.split_last() .unwrap() .1 @@ -2810,10 +2810,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }; resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); - return None; + return Err(true); } - Indeterminate => return None, + Indeterminate => return Err(false), Success(resulting_module) => { containing_module = resulting_module; @@ -2825,7 +2825,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { result.success().map(|binding| { self.check_privacy(containing_module, name, binding, span); binding.def().unwrap() - }) + }).ok_or(false) } fn with_no_errors(&mut self, f: F) -> T @@ -3040,25 +3040,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); self.record_def(expr.id, err_path_resolution()); - match type_res.map(|r| r.base_def) { - Some(Def::Struct(..)) => { - let mut err = resolve_struct_error(self, - expr.span, - ResolutionError::StructVariantUsedAsFunction(&path_name)); - let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", - path_name); - if self.emit_errors { - err.fileline_help(expr.span, &msg); - } else { - err.span_help(expr.span, &msg); - } - err.emit(); + if let Ok(Def::Struct(..)) = type_res.map(|r| r.base_def) { + let error_variant = ResolutionError::StructVariantUsedAsFunction(&path_name); + let mut err = resolve_struct_error(self, expr.span, error_variant); + + let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?", + path_name); + + if self.emit_errors { + err.fileline_help(expr.span, &msg); + } else { + err.span_help(expr.span, &msg); } - _ => { - // Keep reporting some errors even if they're ignored above. - self.resolve_path(expr.id, path, 0, ValueNS); - + err.emit(); + } else { + // Keep reporting some errors even if they're ignored above. + if let Err(true) = self.resolve_path(expr.id, path, 0, ValueNS) { + // `resolve_path` already reported the error + } else { let mut method_scope = false; self.value_ribs.iter().rev().all(|rib| { method_scope = match rib.kind { @@ -3132,8 +3132,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // check to ensure that the path is actually a structure; that // is checked later during typeck. match self.resolve_path(expr.id, path, 0, TypeNS) { - Some(definition) => self.record_def(expr.id, definition), - None => { + Ok(definition) => self.record_def(expr.id, definition), + Err(true) => self.record_def(expr.id, err_path_resolution()), + Err(false) => { debug!("(resolving expression) didn't find struct def",); resolve_error(self, From ffbbf241868588c5ca3880ed023e97aa806ea1d3 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 26 Mar 2016 00:35:59 +0000 Subject: [PATCH 08/14] Refactor away `hir::Visibility::inherit_from` --- src/librustc/hir/mod.rs | 9 --------- src/librustc_typeck/collect.rs | 24 +++++++----------------- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index edb9b783527..2bf279601c8 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1437,15 +1437,6 @@ pub enum Visibility { Inherited, } -impl Visibility { - pub fn inherit_from(&self, parent_visibility: Visibility) -> Visibility { - match self { - &Inherited => parent_visibility, - &Public => *self, - } - } -} - #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct StructField { pub span: Span, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9d76b4c5284..a27f507170b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -738,17 +738,6 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone()); - // If there is a trait reference, treat the methods as always public. - // This is to work around some incorrect behavior in privacy checking: - // when the method belongs to a trait, it should acquire the privacy - // from the trait, not the impl. Forcing the visibility to be public - // makes things sorta work. - let parent_visibility = if opt_trait_ref.is_some() { - hir::Public - } else { - it.vis - }; - // Convert all the associated consts. // Also, check if there are any duplicate associated items let mut seen_type_items = FnvHashSet(); @@ -771,9 +760,12 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { generics: ty_generics.clone(), ty: ty, }); + // Trait-associated constants are always public. + let visibility = + if opt_trait_ref.is_some() { hir::Public } else { impl_item.vis }; convert_associated_const(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, - impl_item.vis.inherit_from(parent_visibility), + visibility, impl_item.defaultness, ty, true /* has_value */); } @@ -797,11 +789,9 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { for impl_item in impl_items { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { - // if the method specifies a visibility, use that, otherwise - // inherit the visibility from the impl (so `foo` in `pub impl - // { fn foo(); }` is public, but private in `impl { fn - // foo(); }`). - let method_vis = impl_item.vis.inherit_from(parent_visibility); + // Trait methods are always public. + let method_vis = + if opt_trait_ref.is_some() { hir::Public } else { impl_item.vis }; convert_method(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, method_vis, From bb66d91c98d83ac5fc453f120ef4a810bc8939a5 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Fri, 25 Mar 2016 06:08:11 +0000 Subject: [PATCH 09/14] Make `hir::Visibility` non-copyable and add `ty::Visibility` --- src/librustc/hir/intravisit.rs | 8 +-- src/librustc/hir/map/blocks.rs | 8 +-- src/librustc/hir/map/mod.rs | 2 +- src/librustc/hir/mod.rs | 2 +- src/librustc/hir/print.rs | 62 ++++++++++----------- src/librustc/middle/cstore.rs | 6 +- src/librustc/ty/mod.rs | 33 ++++++++--- src/librustc_metadata/csearch.rs | 5 +- src/librustc_metadata/decoder.rs | 26 ++++----- src/librustc_metadata/encoder.rs | 44 +++++++++------ src/librustc_privacy/lib.rs | 40 ++++++------- src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_typeck/check/method/mod.rs | 4 +- src/librustc_typeck/check/method/probe.rs | 4 +- src/librustc_typeck/check/mod.rs | 10 ++-- src/librustc_typeck/collect.rs | 31 ++++++----- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 14 +++-- src/librustdoc/html/format.rs | 12 ++-- src/librustdoc/html/render.rs | 22 ++++---- src/librustdoc/visit_ast.rs | 24 ++++---- 21 files changed, 200 insertions(+), 165 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index d34d66918ca..55fd58da866 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -37,10 +37,10 @@ use std::u32; #[derive(Copy, Clone, PartialEq, Eq)] pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() - ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, Visibility, &'a [Attribute]), + ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, &'a Visibility, &'a [Attribute]), /// fn foo(&self) - Method(Name, &'a MethodSig, Option, &'a [Attribute]), + Method(Name, &'a MethodSig, Option<&'a Visibility>, &'a [Attribute]), /// |x, y| {} Closure(&'a [Attribute]), @@ -324,7 +324,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { unsafety, constness, abi, - item.vis, + &item.vis, &item.attrs), declaration, body, @@ -672,7 +672,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt ImplItemKind::Method(ref sig, ref body) => { visitor.visit_fn(FnKind::Method(impl_item.name, sig, - Some(impl_item.vis), + Some(&impl_item.vis), &impl_item.attrs), &sig.decl, body, diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 7b1c692d54b..8c626226bd3 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -113,7 +113,7 @@ struct ItemFnParts<'a> { unsafety: ast::Unsafety, constness: ast::Constness, abi: abi::Abi, - vis: ast::Visibility, + vis: &'a ast::Visibility, generics: &'a ast::Generics, body: &'a Block, id: NodeId, @@ -208,7 +208,7 @@ impl<'a> FnLikeNode<'a> { M: FnOnce(NodeId, Name, &'a ast::MethodSig, - Option, + Option<&'a ast::Visibility>, &'a ast::Block, Span, &'a [Attribute]) @@ -226,7 +226,7 @@ impl<'a> FnLikeNode<'a> { body: &block, generics: generics, abi: abi, - vis: i.vis, + vis: &i.vis, constness: constness, span: i.span, attrs: &i.attrs, @@ -242,7 +242,7 @@ impl<'a> FnLikeNode<'a> { map::NodeImplItem(ii) => { match ii.node { ast::ImplItemKind::Method(ref sig, ref body) => { - method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span, &ii.attrs) + method(ii.id, ii.name, sig, Some(&ii.vis), body, ii.span, &ii.attrs) } _ => { bug!("impl method FnLikeNode that is not fn-like") diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index e1b7afda58b..16dc48d4220 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -430,7 +430,7 @@ impl<'ast> Map<'ast> { /// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no /// module parent is in this map. - fn get_module_parent(&self, id: NodeId) -> NodeId { + pub fn get_module_parent(&self, id: NodeId) -> NodeId { match self.walk_parent_nodes(id, |node| match *node { NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true, _ => false, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2bf279601c8..8e748875b93 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1431,7 +1431,7 @@ pub struct PolyTraitRef { pub span: Span, } -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Visibility { Public, Inherited, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index cd2dfd44639..7affb129313 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -294,7 +294,7 @@ pub fn fun_to_string(decl: &hir::FnDecl, Some(name), generics, opt_explicit_self, - hir::Inherited)?; + &hir::Inherited)?; s.end()?; // Close the head box s.end() // Close the outer box }) @@ -322,8 +322,8 @@ pub fn arg_to_string(arg: &hir::Arg) -> String { to_string(|s| s.print_arg(arg, false)) } -pub fn visibility_qualified(vis: hir::Visibility, s: &str) -> String { - match vis { +pub fn visibility_qualified(vis: &hir::Visibility, s: &str) -> String { + match *vis { hir::Public => format!("pub {}", s), hir::Inherited => s.to_string(), } @@ -573,13 +573,13 @@ impl<'a> State<'a> { Some(item.name), generics, None, - item.vis)?; + &item.vis)?; self.end()?; // end head-ibox word(&mut self.s, ";")?; self.end() // end the outer fn box } hir::ForeignItemStatic(ref t, m) => { - self.head(&visibility_qualified(item.vis, "static"))?; + self.head(&visibility_qualified(&item.vis, "static"))?; if m { self.word_space("mut")?; } @@ -597,7 +597,7 @@ impl<'a> State<'a> { name: ast::Name, ty: &hir::Ty, default: Option<&hir::Expr>, - vis: hir::Visibility) + vis: &hir::Visibility) -> io::Result<()> { word(&mut self.s, &visibility_qualified(vis, ""))?; self.word_space("const")?; @@ -648,7 +648,7 @@ impl<'a> State<'a> { self.ann.pre(self, NodeItem(item))?; match item.node { hir::ItemExternCrate(ref optional_path) => { - self.head(&visibility_qualified(item.vis, "extern crate"))?; + self.head(&visibility_qualified(&item.vis, "extern crate"))?; if let Some(p) = *optional_path { let val = p.as_str(); if val.contains("-") { @@ -666,14 +666,14 @@ impl<'a> State<'a> { self.end()?; // end outer head-block } hir::ItemUse(ref vp) => { - self.head(&visibility_qualified(item.vis, "use"))?; + self.head(&visibility_qualified(&item.vis, "use"))?; self.print_view_path(&vp)?; word(&mut self.s, ";")?; self.end()?; // end inner head-block self.end()?; // end outer head-block } hir::ItemStatic(ref ty, m, ref expr) => { - self.head(&visibility_qualified(item.vis, "static"))?; + self.head(&visibility_qualified(&item.vis, "static"))?; if m == hir::MutMutable { self.word_space("mut")?; } @@ -689,7 +689,7 @@ impl<'a> State<'a> { self.end()?; // end the outer cbox } hir::ItemConst(ref ty, ref expr) => { - self.head(&visibility_qualified(item.vis, "const"))?; + self.head(&visibility_qualified(&item.vis, "const"))?; self.print_name(item.name)?; self.word_space(":")?; self.print_type(&ty)?; @@ -710,12 +710,12 @@ impl<'a> State<'a> { Some(item.name), typarams, None, - item.vis)?; + &item.vis)?; word(&mut self.s, " ")?; self.print_block_with_attrs(&body, &item.attrs)?; } hir::ItemMod(ref _mod) => { - self.head(&visibility_qualified(item.vis, "mod"))?; + self.head(&visibility_qualified(&item.vis, "mod"))?; self.print_name(item.name)?; self.nbsp()?; self.bopen()?; @@ -732,7 +732,7 @@ impl<'a> State<'a> { hir::ItemTy(ref ty, ref params) => { self.ibox(indent_unit)?; self.ibox(0)?; - self.word_nbsp(&visibility_qualified(item.vis, "type"))?; + self.word_nbsp(&visibility_qualified(&item.vis, "type"))?; self.print_name(item.name)?; self.print_generics(params)?; self.end()?; // end the inner ibox @@ -745,16 +745,16 @@ impl<'a> State<'a> { self.end()?; // end the outer ibox } hir::ItemEnum(ref enum_definition, ref params) => { - self.print_enum_def(enum_definition, params, item.name, item.span, item.vis)?; + self.print_enum_def(enum_definition, params, item.name, item.span, &item.vis)?; } hir::ItemStruct(ref struct_def, ref generics) => { - self.head(&visibility_qualified(item.vis, "struct"))?; + self.head(&visibility_qualified(&item.vis, "struct"))?; self.print_struct(struct_def, generics, item.name, item.span, true)?; } hir::ItemDefaultImpl(unsafety, ref trait_ref) => { self.head("")?; - self.print_visibility(item.vis)?; + self.print_visibility(&item.vis)?; self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; self.print_trait_ref(trait_ref)?; @@ -771,7 +771,7 @@ impl<'a> State<'a> { ref ty, ref impl_items) => { self.head("")?; - self.print_visibility(item.vis)?; + self.print_visibility(&item.vis)?; self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; @@ -809,7 +809,7 @@ impl<'a> State<'a> { } hir::ItemTrait(unsafety, ref generics, ref bounds, ref trait_items) => { self.head("")?; - self.print_visibility(item.vis)?; + self.print_visibility(&item.vis)?; self.print_unsafety(unsafety)?; self.word_nbsp("trait")?; self.print_name(item.name)?; @@ -867,7 +867,7 @@ impl<'a> State<'a> { generics: &hir::Generics, name: ast::Name, span: codemap::Span, - visibility: hir::Visibility) + visibility: &hir::Visibility) -> io::Result<()> { self.head(&visibility_qualified(visibility, "enum"))?; self.print_name(name)?; @@ -895,8 +895,8 @@ impl<'a> State<'a> { self.bclose(span) } - pub fn print_visibility(&mut self, vis: hir::Visibility) -> io::Result<()> { - match vis { + pub fn print_visibility(&mut self, vis: &hir::Visibility) -> io::Result<()> { + match *vis { hir::Public => self.word_nbsp("pub"), hir::Inherited => Ok(()), } @@ -915,7 +915,7 @@ impl<'a> State<'a> { if struct_def.is_tuple() { self.popen()?; self.commasep(Inconsistent, struct_def.fields(), |s, field| { - s.print_visibility(field.vis)?; + s.print_visibility(&field.vis)?; s.maybe_print_comment(field.span.lo)?; s.print_type(&field.ty) })?; @@ -937,7 +937,7 @@ impl<'a> State<'a> { self.hardbreak_if_not_bol()?; self.maybe_print_comment(field.span.lo)?; self.print_outer_attributes(&field.attrs)?; - self.print_visibility(field.vis)?; + self.print_visibility(&field.vis)?; self.print_name(field.name)?; self.word_nbsp(":")?; self.print_type(&field.ty)?; @@ -964,7 +964,7 @@ impl<'a> State<'a> { pub fn print_method_sig(&mut self, name: ast::Name, m: &hir::MethodSig, - vis: hir::Visibility) + vis: &hir::Visibility) -> io::Result<()> { self.print_fn(&m.decl, m.unsafety, @@ -986,13 +986,13 @@ impl<'a> State<'a> { self.print_associated_const(ti.name, &ty, default.as_ref().map(|expr| &**expr), - hir::Inherited)?; + &hir::Inherited)?; } hir::MethodTraitItem(ref sig, ref body) => { if body.is_some() { self.head("")?; } - self.print_method_sig(ti.name, sig, hir::Inherited)?; + self.print_method_sig(ti.name, sig, &hir::Inherited)?; if let Some(ref body) = *body { self.nbsp()?; self.print_block_with_attrs(body, &ti.attrs)?; @@ -1021,11 +1021,11 @@ impl<'a> State<'a> { match ii.node { hir::ImplItemKind::Const(ref ty, ref expr) => { - self.print_associated_const(ii.name, &ty, Some(&expr), ii.vis)?; + self.print_associated_const(ii.name, &ty, Some(&expr), &ii.vis)?; } hir::ImplItemKind::Method(ref sig, ref body) => { self.head("")?; - self.print_method_sig(ii.name, sig, ii.vis)?; + self.print_method_sig(ii.name, sig, &ii.vis)?; self.nbsp()?; self.print_block_with_attrs(body, &ii.attrs)?; } @@ -1910,7 +1910,7 @@ impl<'a> State<'a> { name: Option, generics: &hir::Generics, opt_explicit_self: Option<&hir::ExplicitSelf_>, - vis: hir::Visibility) + vis: &hir::Visibility) -> io::Result<()> { self.print_fn_header_info(unsafety, constness, abi, vis)?; @@ -2267,7 +2267,7 @@ impl<'a> State<'a> { name, &generics, opt_explicit_self, - hir::Inherited)?; + &hir::Inherited)?; self.end() } @@ -2347,7 +2347,7 @@ impl<'a> State<'a> { unsafety: hir::Unsafety, constness: hir::Constness, abi: Abi, - vis: hir::Visibility) + vis: &hir::Visibility) -> io::Result<()> { word(&mut self.s, &visibility_qualified(vis, ""))?; self.print_unsafety(unsafety)?; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 1f6328187a5..d3db0804c24 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -116,7 +116,7 @@ pub const LOCAL_CRATE: ast::CrateNum = 0; pub struct ChildItem { pub def: DefLike, pub name: ast::Name, - pub vis: hir::Visibility + pub vis: ty::Visibility, } pub enum FoundAst<'ast> { @@ -157,7 +157,7 @@ pub trait CrateStore<'tcx> : Any { // item info fn stability(&self, def: DefId) -> Option; fn deprecation(&self, def: DefId) -> Option; - fn visibility(&self, def: DefId) -> hir::Visibility; + fn visibility(&self, def: DefId) -> ty::Visibility; fn closure_kind(&self, tcx: &TyCtxt<'tcx>, def_id: DefId) -> ty::ClosureKind; fn closure_ty(&self, tcx: &TyCtxt<'tcx>, def_id: DefId) @@ -334,7 +334,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // item info fn stability(&self, def: DefId) -> Option { bug!("stability") } fn deprecation(&self, def: DefId) -> Option { bug!("deprecation") } - fn visibility(&self, def: DefId) -> hir::Visibility { bug!("visibility") } + fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") } fn closure_kind(&self, tcx: &TyCtxt<'tcx>, def_id: DefId) -> ty::ClosureKind { bug!("closure_kind") } fn closure_ty(&self, tcx: &TyCtxt<'tcx>, def_id: DefId) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 444fea0918f..d5409e05246 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -232,7 +232,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> { } } - pub fn vis(&self) -> hir::Visibility { + pub fn vis(&self) -> Visibility { match *self { ConstTraitItem(ref associated_const) => associated_const.vis, MethodTraitItem(ref method) => method.vis, @@ -273,6 +273,25 @@ impl ImplOrTraitItemId { } } +#[derive(Clone, Debug, PartialEq, Eq, Copy)] +pub enum Visibility { + /// Visible everywhere (including in other crates). + Public, + /// Visible only in the given crate-local module. + Restricted(NodeId), + /// Not visible anywhere in the local crate. This is the visibility of private external items. + PrivateExternal, +} + +impl Visibility { + pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: &TyCtxt) -> Self { + match *visibility { + hir::Public => Visibility::Public, + hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)), + } + } +} + #[derive(Clone, Debug)] pub struct Method<'tcx> { pub name: Name, @@ -280,7 +299,7 @@ pub struct Method<'tcx> { pub predicates: GenericPredicates<'tcx>, pub fty: BareFnTy<'tcx>, pub explicit_self: ExplicitSelfCategory, - pub vis: hir::Visibility, + pub vis: Visibility, pub defaultness: hir::Defaultness, pub def_id: DefId, pub container: ImplOrTraitItemContainer, @@ -292,7 +311,7 @@ impl<'tcx> Method<'tcx> { predicates: GenericPredicates<'tcx>, fty: BareFnTy<'tcx>, explicit_self: ExplicitSelfCategory, - vis: hir::Visibility, + vis: Visibility, defaultness: hir::Defaultness, def_id: DefId, container: ImplOrTraitItemContainer) @@ -336,7 +355,7 @@ impl<'tcx> Hash for Method<'tcx> { pub struct AssociatedConst<'tcx> { pub name: Name, pub ty: Ty<'tcx>, - pub vis: hir::Visibility, + pub vis: Visibility, pub defaultness: hir::Defaultness, pub def_id: DefId, pub container: ImplOrTraitItemContainer, @@ -347,7 +366,7 @@ pub struct AssociatedConst<'tcx> { pub struct AssociatedType<'tcx> { pub name: Name, pub ty: Option>, - pub vis: hir::Visibility, + pub vis: Visibility, pub defaultness: hir::Defaultness, pub def_id: DefId, pub container: ImplOrTraitItemContainer, @@ -1419,7 +1438,7 @@ pub struct FieldDefData<'tcx, 'container: 'tcx> { /// are not real items, and don't have entries in tcache etc. pub did: DefId, pub name: Name, - pub vis: hir::Visibility, + pub vis: Visibility, /// TyIVar is used here to allow for variance (see the doc at /// AdtDefData). /// @@ -1704,7 +1723,7 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> { impl<'tcx, 'container> FieldDefData<'tcx, 'container> { pub fn new(did: DefId, name: Name, - vis: hir::Visibility) -> Self { + vis: Visibility) -> Self { FieldDefData { did: did, name: name, diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 0b90ad5b4e2..8e7be0e3a0f 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -48,7 +48,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { decoder::get_deprecation(&cdata, def.index) } - fn visibility(&self, def: DefId) -> hir::Visibility { + fn visibility(&self, def: DefId) -> ty::Visibility { let cdata = self.get_crate_data(def.krate); decoder::get_visibility(&cdata, def.index) } @@ -536,7 +536,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { let mut visible_parent_map = self.visible_parent_map.borrow_mut(); if !visible_parent_map.is_empty() { return visible_parent_map; } - use rustc::hir; use rustc::middle::cstore::{CrateStore, ChildItem}; use std::collections::vec_deque::VecDeque; use std::collections::hash_map::Entry; @@ -552,7 +551,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { let mut bfs_queue = &mut VecDeque::new(); let mut add_child = |bfs_queue: &mut VecDeque<_>, child: ChildItem, parent: DefId| { let child = match child.def { - DefLike::DlDef(def) if child.vis == hir::Public => def.def_id(), + DefLike::DlDef(def) if child.vis == ty::Visibility::Public => def.def_id(), _ => return, }; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6b53edbbff1..a0881f1153e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -140,13 +140,13 @@ fn item_family(item: rbml::Doc) -> Family { } } -fn item_visibility(item: rbml::Doc) -> hir::Visibility { +fn item_visibility(item: rbml::Doc) -> ty::Visibility { match reader::maybe_get_doc(item, tag_items_data_item_visibility) { - None => hir::Public, + None => ty::Visibility::Public, Some(visibility_doc) => { match reader::doc_as_u8(visibility_doc) as char { - 'y' => hir::Public, - 'i' => hir::Inherited, + 'y' => ty::Visibility::Public, + 'i' => ty::Visibility::PrivateExternal, _ => bug!("unknown visibility character") } } @@ -541,7 +541,7 @@ pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option { }) } -pub fn get_visibility(cdata: Cmd, id: DefIndex) -> hir::Visibility { +pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility { item_visibility(cdata.lookup_item(id)) } @@ -639,7 +639,7 @@ fn each_child_of_item_or_crate(intr: Rc, item_doc: rbml::Doc, mut get_crate_data: G, mut callback: F) where - F: FnMut(DefLike, ast::Name, hir::Visibility), + F: FnMut(DefLike, ast::Name, ty::Visibility), G: FnMut(ast::CrateNum) -> Rc, { // Iterate over all children. @@ -723,7 +723,7 @@ fn each_child_of_item_or_crate(intr: Rc, let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id); // These items have a public visibility because they're part of // a public re-export. - callback(def_like, token::intern(name), hir::Public); + callback(def_like, token::intern(name), ty::Visibility::Public); } } } @@ -734,7 +734,7 @@ pub fn each_child_of_item(intr: Rc, id: DefIndex, get_crate_data: G, callback: F) where - F: FnMut(DefLike, ast::Name, hir::Visibility), + F: FnMut(DefLike, ast::Name, ty::Visibility), G: FnMut(ast::CrateNum) -> Rc, { // Find the item. @@ -755,7 +755,7 @@ pub fn each_top_level_item_of_crate(intr: Rc, cdata: Cmd, get_crate_data: G, callback: F) where - F: FnMut(DefLike, ast::Name, hir::Visibility), + F: FnMut(DefLike, ast::Name, ty::Visibility), G: FnMut(ast::CrateNum) -> Rc, { let root_doc = rbml::Doc::new(cdata.data()); @@ -1138,11 +1138,11 @@ pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap hir::Visibility { +fn struct_field_family_to_visibility(family: Family) -> ty::Visibility { match family { - PublicField => hir::Public, - InheritedField => hir::Inherited, - _ => bug!() + PublicField => ty::Visibility::Public, + InheritedField => ty::Visibility::PrivateExternal, + _ => bug!() } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d45650159e3..69f61cf97c0 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -249,7 +249,7 @@ fn encode_struct_fields(rbml_w: &mut Encoder, fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, rbml_w: &mut Encoder, did: DefId, - vis: hir::Visibility, + vis: &hir::Visibility, index: &mut CrateIndex<'tcx>) { debug!("encode_enum_variant_info(did={:?})", did); let repr_hints = ecx.tcx.lookup_repr_hints(did); @@ -355,7 +355,7 @@ fn encode_info_for_mod(ecx: &EncodeContext, attrs: &[ast::Attribute], id: NodeId, name: Name, - vis: hir::Visibility) { + vis: &hir::Visibility) { rbml_w.start_tag(tag_items_data_item); encode_def_id_and_key(ecx, rbml_w, ecx.tcx.map.local_def_id(id)); encode_family(rbml_w, 'm'); @@ -383,7 +383,7 @@ fn encode_info_for_mod(ecx: &EncodeContext, encode_deprecation(rbml_w, depr); // Encode the reexports of this module, if this module is public. - if vis == hir::Public { + if *vis == hir::Public { debug!("(encoding info for module) encoding reexports for {}", id); encode_reexports(ecx, rbml_w, id); } @@ -393,21 +393,31 @@ fn encode_info_for_mod(ecx: &EncodeContext, } fn encode_struct_field_family(rbml_w: &mut Encoder, - visibility: hir::Visibility) { - encode_family(rbml_w, match visibility { - hir::Public => 'g', - hir::Inherited => 'N' - }); + visibility: ty::Visibility) { + encode_family(rbml_w, if visibility.is_public() { 'g' } else { 'N' }); } -fn encode_visibility(rbml_w: &mut Encoder, visibility: hir::Visibility) { - let ch = match visibility { - hir::Public => 'y', - hir::Inherited => 'i', - }; +fn encode_visibility(rbml_w: &mut Encoder, visibility: T) { + let ch = if visibility.is_public() { 'y' } else { 'i' }; rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8); } +trait HasVisibility: Sized { + fn is_public(self) -> bool; +} + +impl<'a> HasVisibility for &'a hir::Visibility { + fn is_public(self) -> bool { + *self == hir::Public + } +} + +impl HasVisibility for ty::Visibility { + fn is_public(self) -> bool { + self == ty::Visibility::Public + } +} + fn encode_constness(rbml_w: &mut Encoder, constness: hir::Constness) { rbml_w.start_tag(tag_items_data_item_constness); let ch = match constness { @@ -861,7 +871,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, debug!("encoding info for item at {}", tcx.sess.codemap().span_to_string(item.span)); - let vis = item.vis; + let vis = &item.vis; let def_id = ecx.tcx.map.local_def_id(item.id); let stab = stability::lookup_stability(tcx, ecx.tcx.map.local_def_id(item.id)); let depr = stability::lookup_deprecation(tcx, ecx.tcx.map.local_def_id(item.id)); @@ -932,7 +942,7 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, &item.attrs, item.id, item.name, - item.vis); + &item.vis); } hir::ItemForeignMod(ref fm) => { index.record(def_id, rbml_w); @@ -1336,7 +1346,7 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, index.record(def_id, rbml_w); rbml_w.start_tag(tag_items_data_item); encode_def_id_and_key(ecx, rbml_w, def_id); - encode_visibility(rbml_w, nitem.vis); + encode_visibility(rbml_w, &nitem.vis); match nitem.node { hir::ForeignItemFn(ref fndecl, _) => { encode_family(rbml_w, FN_FAMILY); @@ -1443,7 +1453,7 @@ fn encode_info_for_items<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, &[], CRATE_NODE_ID, syntax::parse::token::intern(&ecx.link_meta.crate_name), - hir::Public); + &hir::Public); krate.visit_all_items(&mut EncodeVisitor { index: &mut index, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 8840bd42717..63a5dc71b8f 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -383,11 +383,11 @@ struct PrivacyVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { fn item_is_visible(&self, did: DefId) -> bool { - let visibility = match self.tcx.map.as_local_node_id(did) { - Some(node_id) => self.tcx.map.expect_item(node_id).vis, - None => self.tcx.sess.cstore.visibility(did), + let is_public = match self.tcx.map.as_local_node_id(did) { + Some(node_id) => self.tcx.map.expect_item(node_id).vis == hir::Public, + None => self.tcx.sess.cstore.visibility(did) == ty::Visibility::Public, }; - visibility == hir::Public || self.private_accessible(did) + is_public || self.private_accessible(did) } /// True if `did` is private-accessible @@ -401,7 +401,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // Checks that a field is in scope. fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) { if def.adt_kind() == ty::AdtKind::Struct && - field.vis != hir::Public && !self.private_accessible(def.did) { + field.vis != ty::Visibility::Public && !self.private_accessible(def.did) { span_err!(self.tcx.sess, span, E0451, "field `{}` of struct `{}` is private", field.name, self.tcx.item_path_str(def.did)); } @@ -464,7 +464,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { _ => expr_ty }.ty_adt_def().unwrap(); let any_priv = def.struct_variant().fields.iter().any(|f| { - f.vis != hir::Public && !self.private_accessible(def.did) + f.vis != ty::Visibility::Public && !self.private_accessible(def.did) }); if any_priv { span_err!(self.tcx.sess, expr.span, E0450, @@ -548,8 +548,8 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { /// Such qualifiers can be set by syntax extensions even if the parser doesn't allow them, /// so we check things like variant fields too. fn check_sane_privacy(&self, item: &hir::Item) { - let check_inherited = |sp, vis, note: &str| { - if vis != hir::Inherited { + let check_inherited = |sp, vis: &hir::Visibility, note: &str| { + if *vis != hir::Inherited { let mut err = struct_span_err!(self.tcx.sess, sp, E0449, "unnecessary visibility qualifier"); if !note.is_empty() { @@ -561,29 +561,29 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { match item.node { hir::ItemImpl(_, _, _, Some(..), _, ref impl_items) => { - check_inherited(item.span, item.vis, + check_inherited(item.span, &item.vis, "visibility qualifiers have no effect on trait impls"); for impl_item in impl_items { - check_inherited(impl_item.span, impl_item.vis, + check_inherited(impl_item.span, &impl_item.vis, "visibility qualifiers have no effect on trait impl items"); } } hir::ItemImpl(_, _, _, None, _, _) => { - check_inherited(item.span, item.vis, + check_inherited(item.span, &item.vis, "place qualifiers on individual methods instead"); } hir::ItemDefaultImpl(..) => { - check_inherited(item.span, item.vis, + check_inherited(item.span, &item.vis, "visibility qualifiers have no effect on trait impls"); } hir::ItemForeignMod(..) => { - check_inherited(item.span, item.vis, + check_inherited(item.span, &item.vis, "place qualifiers on individual functions instead"); } hir::ItemEnum(ref def, _) => { for variant in &def.variants { for field in variant.node.data.fields() { - check_inherited(field.span, field.vis, + check_inherited(field.span, &field.vis, "visibility qualifiers have no effect on variant fields"); } } @@ -659,8 +659,8 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } } - fn item_is_public(&self, id: &ast::NodeId, vis: hir::Visibility) -> bool { - self.access_levels.is_reachable(*id) || vis == hir::Public + fn item_is_public(&self, id: &ast::NodeId, vis: &hir::Visibility) -> bool { + self.access_levels.is_reachable(*id) || *vis == hir::Public } } @@ -789,7 +789,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> match impl_item.node { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) - if self.item_is_public(&impl_item.id, impl_item.vis) => + if self.item_is_public(&impl_item.id, &impl_item.vis) => { intravisit::walk_impl_item(self, impl_item) } @@ -831,14 +831,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> for impl_item in impl_items { match impl_item.node { hir::ImplItemKind::Const(..) => { - if self.item_is_public(&impl_item.id, impl_item.vis) { + if self.item_is_public(&impl_item.id, &impl_item.vis) { found_pub_static = true; intravisit::walk_impl_item(self, impl_item); } } hir::ImplItemKind::Method(ref sig, _) => { if sig.explicit_self.node == hir::SelfStatic && - self.item_is_public(&impl_item.id, impl_item.vis) { + self.item_is_public(&impl_item.id, &impl_item.vis) { found_pub_static = true; intravisit::walk_impl_item(self, impl_item); } @@ -858,7 +858,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> hir::ItemTy(..) => return, // not at all public, so we don't care - _ if !self.item_is_public(&item.id, item.vis) => { + _ if !self.item_is_public(&item.id, &item.vis) => { return; } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a422b09f96b..003450cd6fd 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -26,7 +26,7 @@ use rustc::middle::cstore::{CrateStore, ChildItem, DlDef}; use rustc::lint; use rustc::hir::def::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; -use rustc::ty::VariantKind; +use rustc::ty::{self, VariantKind}; use syntax::ast::Name; use syntax::attr::AttrMetaMethods; @@ -434,7 +434,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> { } let name = xcdef.name; - let is_public = xcdef.vis == hir::Public || parent.is_trait(); + let is_public = xcdef.vis == ty::Visibility::Public || parent.is_trait(); let mut modifiers = DefModifiers::empty(); if is_public { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 3f069a68316..f684f70565d 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -16,7 +16,7 @@ use hir::def::Def; use hir::def_id::DefId; use rustc::ty::subst; use rustc::traits; -use rustc::ty::{self, TyCtxt, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; +use rustc::ty::{self, TyCtxt, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable, Visibility}; use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; use rustc::infer; @@ -343,7 +343,7 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, let def = pick.item.def(); if let probe::InherentImplPick = pick.kind { - if pick.item.vis() != hir::Public && !fcx.private_item_is_visible(def.def_id()) { + if pick.item.vis() != Visibility::Public && !fcx.private_item_is_visible(def.def_id()) { let msg = format!("{} `{}` is private", def.kind_name(), &method_name.as_str()); fcx.tcx().sess.span_err(span, &msg); } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 7d98eac30c5..bf6394a03d0 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -20,7 +20,7 @@ use hir::def::Def; use rustc::ty::subst; use rustc::ty::subst::Subst; use rustc::traits; -use rustc::ty::{self, NoPreference, Ty, TyCtxt, ToPolyTraitRef, TraitRef, TypeFoldable}; +use rustc::ty::{self, NoPreference, Ty, TyCtxt, ToPolyTraitRef, TraitRef, TypeFoldable, Visibility}; use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin}; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; @@ -412,7 +412,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { return self.record_static_candidate(ImplSource(impl_def_id)); } - if item.vis() != hir::Public && !self.fcx.private_item_is_visible(item.def_id()) { + if item.vis() != Visibility::Public && !self.fcx.private_item_is_visible(item.def_id()) { self.private_candidate = Some(item.def()); return } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e7159e65eeb..0e2bf89947f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -95,7 +95,7 @@ use rustc::traits::{self, report_fulfillment_errors, ProjectionMode}; use rustc::ty::{GenericPredicates, TypeScheme}; use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; -use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt}; +use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility}; use rustc::ty::{MethodCall, MethodCallee}; use rustc::ty::adjustment; use rustc::ty::error::TypeError; @@ -125,8 +125,7 @@ use syntax::ptr::P; use syntax::util::lev_distance::find_best_match_for_name; use rustc::hir::intravisit::{self, Visitor}; -use rustc::hir; -use rustc::hir::{Visibility, PatKind}; +use rustc::hir::{self, PatKind}; use rustc::hir::print as pprust; use rustc_back::slice; use rustc_const_eval::eval_repeat_count; @@ -2967,7 +2966,8 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, debug!("struct named {:?}", base_t); if let Some(field) = base_def.struct_variant().find_field_named(field.node) { let field_ty = fcx.field_ty(expr.span, field, substs); - if field.vis == hir::Public || fcx.private_item_is_visible(base_def.did) { + if field.vis == Visibility::Public || + fcx.private_item_is_visible(base_def.did) { return Some(field_ty); } private_candidate = Some((base_def.did, field_ty)); @@ -3079,7 +3079,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, debug!("tuple struct named {:?}", base_t); if let Some(field) = base_def.struct_variant().fields.get(idx.node) { let field_ty = fcx.field_ty(expr.span, field, substs); - if field.vis == hir::Public || fcx.private_item_is_visible(base_def.did) { + if field.vis == Visibility::Public || fcx.private_item_is_visible(base_def.did) { return Some(field_ty); } private_candidate = Some((base_def.did, field_ty)); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a27f507170b..2e1a6846843 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -532,7 +532,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, container: ImplOrTraitItemContainer, name: ast::Name, id: ast::NodeId, - vis: hir::Visibility, + vis: &hir::Visibility, sig: &hir::MethodSig, defaultness: hir::Defaultness, untransformed_rcvr_ty: Ty<'tcx>, @@ -555,7 +555,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty_generic_predicates, fty, explicit_self_category, - vis, + ty::Visibility::from_hir(vis, id, ccx.tcx), defaultness, def_id, container); @@ -602,7 +602,7 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, container: ImplOrTraitItemContainer, name: ast::Name, id: ast::NodeId, - vis: hir::Visibility, + vis: &hir::Visibility, defaultness: hir::Defaultness, ty: ty::Ty<'tcx>, has_value: bool) @@ -614,7 +614,7 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let associated_const = Rc::new(ty::AssociatedConst { name: name, - vis: vis, + vis: ty::Visibility::from_hir(vis, id, ccx.tcx), defaultness: defaultness, def_id: ccx.tcx.map.local_def_id(id), container: container, @@ -629,13 +629,13 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, container: ImplOrTraitItemContainer, name: ast::Name, id: ast::NodeId, - vis: hir::Visibility, + vis: &hir::Visibility, defaultness: hir::Defaultness, ty: Option>) { let associated_type = Rc::new(ty::AssociatedType { name: name, - vis: vis, + vis: ty::Visibility::from_hir(vis, id, ccx.tcx), defaultness: defaultness, ty: ty, def_id: ccx.tcx.map.local_def_id(id), @@ -761,8 +761,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { ty: ty, }); // Trait-associated constants are always public. - let visibility = - if opt_trait_ref.is_some() { hir::Public } else { impl_item.vis }; + let public = &hir::Public; + let visibility = if opt_trait_ref.is_some() { public } else { &impl_item.vis }; convert_associated_const(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, visibility, @@ -782,7 +782,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty); convert_associated_type(ccx, ImplContainer(def_id), - impl_item.name, impl_item.id, impl_item.vis, + impl_item.name, impl_item.id, &impl_item.vis, impl_item.defaultness, Some(typ)); } } @@ -790,8 +790,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { for impl_item in impl_items { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { // Trait methods are always public. - let method_vis = - if opt_trait_ref.is_some() { hir::Public } else { impl_item.vis }; + let public = &hir::Public; + let method_vis = if opt_trait_ref.is_some() { public } else { &impl_item.vis }; convert_method(ccx, ImplContainer(def_id), impl_item.name, impl_item.id, method_vis, @@ -829,7 +829,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { container, trait_item.name, trait_item.id, - hir::Public, + &hir::Public, hir::Defaultness::Default, ty, default.is_some()) @@ -847,7 +847,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { container, trait_item.name, trait_item.id, - hir::Public, + &hir::Public, hir::Defaultness::Default, typ); } @@ -860,7 +860,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { container, trait_item.name, trait_item.id, - hir::Inherited, + &hir::Inherited, sig, hir::Defaultness::Default, tcx.mk_self_type(), @@ -977,6 +977,7 @@ fn convert_struct_variant<'tcx>(tcx: &TyCtxt<'tcx>, disr_val: ty::Disr, def: &hir::VariantData) -> ty::VariantDefData<'tcx, 'tcx> { let mut seen_fields: FnvHashMap = FnvHashMap(); + let node_id = tcx.map.as_local_node_id(did).unwrap(); let fields = def.fields().iter().map(|f| { let fid = tcx.map.local_def_id(f.id); let dup_span = seen_fields.get(&f.name).cloned(); @@ -990,7 +991,7 @@ fn convert_struct_variant<'tcx>(tcx: &TyCtxt<'tcx>, seen_fields.insert(f.name, f.span); } - ty::FieldDefData::new(fid, f.name, f.vis) + ty::FieldDefData::new(fid, f.name, ty::Visibility::from_hir(&f.vis, node_id, tcx)) }).collect(); ty::VariantDefData { did: did, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 8c65eb8dbd3..85097549826 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -361,7 +361,7 @@ pub fn build_impl(cx: &DocContext, }) } ty::MethodTraitItem(method) => { - if method.vis != hir::Public && associated_trait.is_none() { + if method.vis != ty::Visibility::Public && associated_trait.is_none() { return None } let mut item = method.clean(cx); @@ -471,7 +471,7 @@ fn build_module(cx: &DocContext, tcx: &TyCtxt, cstore::DlDef(Def::ForeignMod(did)) => { fill_in(cx, tcx, did, items); } - cstore::DlDef(def) if item.vis == hir::Public => { + cstore::DlDef(def) if item.vis == ty::Visibility::Public => { if !visited.insert(def) { continue } if let Some(i) = try_inline_def(cx, tcx, def) { items.extend(i) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4895022cfac..673aa17ecd1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1754,7 +1754,7 @@ impl Clean for hir::StructField { name: Some(self.name).clean(cx), attrs: self.attrs.clean(cx), source: self.span.clean(cx), - visibility: Some(self.vis), + visibility: self.vis.clean(cx), stability: get_stability(cx, cx.map.local_def_id(self.id)), deprecation: get_deprecation(cx, cx.map.local_def_id(self.id)), def_id: cx.map.local_def_id(self.id), @@ -1771,7 +1771,7 @@ impl<'tcx> Clean for ty::FieldDefData<'tcx, 'static> { name: Some(self.name).clean(cx), attrs: attr_map.get(&self.did).unwrap_or(&Vec::new()).clean(cx), source: Span::empty(), - visibility: Some(self.vis), + visibility: self.vis.clean(cx), stability: get_stability(cx, self.did), deprecation: get_deprecation(cx, self.did), def_id: self.did, @@ -1784,7 +1784,13 @@ pub type Visibility = hir::Visibility; impl Clean> for hir::Visibility { fn clean(&self, _: &DocContext) -> Option { - Some(*self) + Some(self.clone()) + } +} + +impl Clean> for ty::Visibility { + fn clean(&self, _: &DocContext) -> Option { + Some(if *self == ty::Visibility::Public { hir::Public } else { hir::Inherited }) } } @@ -1902,7 +1908,7 @@ impl<'tcx> Clean for ty::VariantDefData<'tcx, 'static> { source: Span::empty(), name: Some(field.name.clean(cx)), attrs: cx.tcx().get_attrs(field.did).clean(cx), - visibility: Some(field.vis), + visibility: field.vis.clean(cx), def_id: field.did, stability: get_stability(cx, field.did), deprecation: get_deprecation(cx, field.did), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index a43711a3273..ce20ad05acb 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -31,7 +31,7 @@ use html::render::{cache, CURRENT_LOCATION_KEY}; /// Helper to render an optional visibility with a space after it (if the /// visibility is preset) #[derive(Copy, Clone)] -pub struct VisSpace(pub Option); +pub struct VisSpace<'a>(pub &'a Option); /// Similarly to VisSpace, this structure is used to render a function style with a /// space after it. #[derive(Copy, Clone)] @@ -56,9 +56,9 @@ pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]); pub struct CommaSep<'a, T: 'a>(pub &'a [T]); pub struct AbiSpace(pub Abi); -impl VisSpace { - pub fn get(&self) -> Option { - let VisSpace(v) = *self; v +impl<'a> VisSpace<'a> { + pub fn get(self) -> &'a Option { + let VisSpace(v) = self; v } } @@ -636,9 +636,9 @@ impl<'a> fmt::Display for Method<'a> { } } -impl fmt::Display for VisSpace { +impl<'a> fmt::Display for VisSpace<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.get() { + match *self.get() { Some(hir::Public) => write!(f, "pub "), Some(hir::Inherited) | None => Ok(()) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3352e74c4c3..c5850089578 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1714,13 +1714,13 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, match *src { Some(ref src) => { write!(w, "{}extern crate {} as {};", - VisSpace(myitem.visibility), + VisSpace(&myitem.visibility), src, name)? } None => { write!(w, "{}extern crate {};", - VisSpace(myitem.visibility), name)? + VisSpace(&myitem.visibility), name)? } } write!(w, "")?; @@ -1728,7 +1728,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, clean::ImportItem(ref import) => { write!(w, "{}{}", - VisSpace(myitem.visibility), *import)?; + VisSpace(&myitem.visibility), *import)?; } _ => { @@ -1831,7 +1831,7 @@ fn item_constant(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, c: &clean::Constant) -> fmt::Result { write!(w, "
{vis}const \
                {name}: {typ}{init}
", - vis = VisSpace(it.visibility), + vis = VisSpace(&it.visibility), name = it.name.as_ref().unwrap(), typ = c.type_, init = Initializer(&c.expr))?; @@ -1842,7 +1842,7 @@ fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, s: &clean::Static) -> fmt::Result { write!(w, "
{vis}static {mutability}\
                {name}: {typ}{init}
", - vis = VisSpace(it.visibility), + vis = VisSpace(&it.visibility), mutability = MutableSpace(s.mutability), name = it.name.as_ref().unwrap(), typ = s.type_, @@ -1859,7 +1859,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, }; write!(w, "
{vis}{constness}{unsafety}{abi}fn \
                {name}{generics}{decl}{where_clause}
", - vis = VisSpace(it.visibility), + vis = VisSpace(&it.visibility), constness = ConstnessSpace(vis_constness), unsafety = UnsafetySpace(f.unsafety), abi = AbiSpace(f.abi), @@ -1887,7 +1887,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, // Output the trait definition write!(w, "
{}{}trait {}{}{}{} ",
-           VisSpace(it.visibility),
+           VisSpace(&it.visibility),
            UnsafetySpace(t.unsafety),
            it.name.as_ref().unwrap(),
            t.generics,
@@ -2214,7 +2214,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     write!(w, "
")?;
     render_attributes(w, it)?;
     write!(w, "{}enum {}{}{}",
-           VisSpace(it.visibility),
+           VisSpace(&it.visibility),
            it.name.as_ref().unwrap(),
            e.generics,
            WhereClause(&e.generics))?;
@@ -2326,7 +2326,7 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
                  tab: &str,
                  structhead: bool) -> fmt::Result {
     write!(w, "{}{}{}",
-           VisSpace(it.visibility),
+           VisSpace(&it.visibility),
            if structhead {"struct "} else {""},
            it.name.as_ref().unwrap())?;
     if let Some(g) = g {
@@ -2338,7 +2338,7 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
             for field in fields {
                 if let clean::StructFieldItem(ref ty) = field.inner {
                     write!(w, "    {}{}: {},\n{}",
-                           VisSpace(field.visibility),
+                           VisSpace(&field.visibility),
                            field.name.as_ref().unwrap(),
                            *ty,
                            tab)?;
@@ -2361,7 +2361,7 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
                         write!(w, "_")?
                     }
                     clean::StructFieldItem(ref ty) => {
-                        write!(w, "{}{}", VisSpace(field.visibility), *ty)?
+                        write!(w, "{}{}", VisSpace(&field.visibility), *ty)?
                     }
                     _ => unreachable!()
                 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 45c7969ef7c..5c36c38abc5 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -101,7 +101,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             id: item.id,
             struct_type: struct_type,
             name: name,
-            vis: item.vis,
+            vis: item.vis.clone(),
             stab: self.stability(item.id),
             depr: self.deprecation(item.id),
             attrs: item.attrs.clone(),
@@ -125,7 +125,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 def: v.node.data.clone(),
                 whence: v.span,
             }).collect(),
-            vis: it.vis,
+            vis: it.vis.clone(),
             stab: self.stability(it.id),
             depr: self.deprecation(it.id),
             generics: params.clone(),
@@ -144,7 +144,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         debug!("Visiting fn");
         Function {
             id: item.id,
-            vis: item.vis,
+            vis: item.vis.clone(),
             stab: self.stability(item.id),
             depr: self.deprecation(item.id),
             attrs: item.attrs.clone(),
@@ -166,7 +166,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         om.where_outer = span;
         om.where_inner = m.inner;
         om.attrs = attrs;
-        om.vis = vis;
+        om.vis = vis.clone();
         om.stab = self.stability(id);
         om.depr = self.deprecation(id);
         om.id = id;
@@ -299,7 +299,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 om.extern_crates.push(ExternCrate {
                     name: name,
                     path: p.map(|x|x.to_string()),
-                    vis: item.vis,
+                    vis: item.vis.clone(),
                     attrs: item.attrs.clone(),
                     whence: item.span,
                 })
@@ -324,7 +324,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.imports.push(Import {
                     id: item.id,
-                    vis: item.vis,
+                    vis: item.vis.clone(),
                     attrs: item.attrs.clone(),
                     node: node,
                     whence: item.span,
@@ -333,7 +333,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             hir::ItemMod(ref m) => {
                 om.mods.push(self.visit_mod_contents(item.span,
                                                      item.attrs.clone(),
-                                                     item.vis,
+                                                     item.vis.clone(),
                                                      item.id,
                                                      m,
                                                      Some(name)));
@@ -353,7 +353,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     id: item.id,
                     attrs: item.attrs.clone(),
                     whence: item.span,
-                    vis: item.vis,
+                    vis: item.vis.clone(),
                     stab: self.stability(item.id),
                     depr: self.deprecation(item.id),
                 };
@@ -368,7 +368,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     name: name,
                     attrs: item.attrs.clone(),
                     whence: item.span,
-                    vis: item.vis,
+                    vis: item.vis.clone(),
                     stab: self.stability(item.id),
                     depr: self.deprecation(item.id),
                 };
@@ -382,7 +382,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     name: name,
                     attrs: item.attrs.clone(),
                     whence: item.span,
-                    vis: item.vis,
+                    vis: item.vis.clone(),
                     stab: self.stability(item.id),
                     depr: self.deprecation(item.id),
                 };
@@ -398,7 +398,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     id: item.id,
                     attrs: item.attrs.clone(),
                     whence: item.span,
-                    vis: item.vis,
+                    vis: item.vis.clone(),
                     stab: self.stability(item.id),
                     depr: self.deprecation(item.id),
                 };
@@ -415,7 +415,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     attrs: item.attrs.clone(),
                     id: item.id,
                     whence: item.span,
-                    vis: item.vis,
+                    vis: item.vis.clone(),
                     stab: self.stability(item.id),
                     depr: self.deprecation(item.id),
                 };

From 0d34c5dd8a03fc18e43c7ec279169681eaa2ec4e Mon Sep 17 00:00:00 2001
From: Jeffrey Seyfried 
Date: Thu, 31 Mar 2016 07:03:00 +0000
Subject: [PATCH 10/14] Use the node id from the `Restricted` variant when
 checking accessibility in `typeck` and in `privacy::PrivacyVisitor`.

---
 src/librustc/hir/map/mod.rs               | 12 ------------
 src/librustc/ty/mod.rs                    | 20 +++++++++++++++++++
 src/librustc_privacy/lib.rs               | 24 ++++++++---------------
 src/librustc_typeck/check/method/mod.rs   |  4 ++--
 src/librustc_typeck/check/method/probe.rs |  4 ++--
 src/librustc_typeck/check/mod.rs          | 12 ++----------
 6 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 16dc48d4220..fc1c4aeb226 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -440,18 +440,6 @@ impl<'ast> Map<'ast> {
         }
     }
 
-    pub fn private_item_is_visible_from(&self, item: NodeId, block: NodeId) -> bool {
-        // A private item is visible from everything in its nearest module parent.
-        let visibility = self.get_module_parent(item);
-        let mut block_ancestor = self.get_module_parent(block);
-        loop {
-            if block_ancestor == visibility { return true }
-            let block_ancestor_parent = self.get_module_parent(block_ancestor);
-            if block_ancestor_parent == block_ancestor { return false }
-            block_ancestor = block_ancestor_parent;
-        }
-    }
-
     /// Returns the nearest enclosing scope. A scope is an item or block.
     /// FIXME it is not clear to me that all items qualify as scopes - statics
     /// and associated types probably shouldn't, for example. Behaviour in this
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index d5409e05246..c3e1f38180a 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -290,6 +290,26 @@ impl Visibility {
             hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
         }
     }
+
+    /// Returns true if an item with this visibility is accessible from the given block.
+    pub fn is_accessible_from(self, block: NodeId, map: &ast_map::Map) -> bool {
+        let restriction = match self {
+            // Public items are visible everywhere.
+            Visibility::Public => return true,
+            // Private items from other crates are visible nowhere.
+            Visibility::PrivateExternal => return false,
+            // Restricted items are visible in an arbitrary local module.
+            Visibility::Restricted(module) => module,
+        };
+
+        let mut block_ancestor = map.get_module_parent(block);
+        loop {
+            if block_ancestor == restriction { return true }
+            let block_ancestor_parent = map.get_module_parent(block_ancestor);
+            if block_ancestor_parent == block_ancestor { return false }
+            block_ancestor = block_ancestor_parent;
+        }
+    }
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 63a5dc71b8f..3b9dc4a4814 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -382,26 +382,18 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
-    fn item_is_visible(&self, did: DefId) -> bool {
-        let is_public = match self.tcx.map.as_local_node_id(did) {
-            Some(node_id) => self.tcx.map.expect_item(node_id).vis == hir::Public,
-            None => self.tcx.sess.cstore.visibility(did) == ty::Visibility::Public,
-        };
-        is_public || self.private_accessible(did)
-    }
-
-    /// True if `did` is private-accessible
-    fn private_accessible(&self, did: DefId) -> bool {
+    fn item_is_accessible(&self, did: DefId) -> bool {
         match self.tcx.map.as_local_node_id(did) {
-            Some(node_id) => self.tcx.map.private_item_is_visible_from(node_id, self.curitem),
-            None => false,
-        }
+            Some(node_id) =>
+                ty::Visibility::from_hir(&self.tcx.map.expect_item(node_id).vis, node_id, self.tcx),
+            None => self.tcx.sess.cstore.visibility(did),
+        }.is_accessible_from(self.curitem, &self.tcx.map)
     }
 
     // Checks that a field is in scope.
     fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) {
         if def.adt_kind() == ty::AdtKind::Struct &&
-                field.vis != ty::Visibility::Public && !self.private_accessible(def.did) {
+           !field.vis.is_accessible_from(self.curitem, &self.tcx.map) {
             span_err!(self.tcx.sess, span, E0451, "field `{}` of struct `{}` is private",
                       field.name, self.tcx.item_path_str(def.did));
         }
@@ -412,7 +404,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
         match self.tcx.impl_or_trait_item(method_def_id).container() {
             // Trait methods are always all public. The only controlling factor
             // is whether the trait itself is accessible or not.
-            ty::TraitContainer(trait_def_id) if !self.item_is_visible(trait_def_id) => {
+            ty::TraitContainer(trait_def_id) if !self.item_is_accessible(trait_def_id) => {
                 let msg = format!("source trait `{}` is private",
                                   self.tcx.item_path_str(trait_def_id));
                 self.tcx.sess.span_err(span, &msg);
@@ -464,7 +456,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                         _ => expr_ty
                     }.ty_adt_def().unwrap();
                     let any_priv = def.struct_variant().fields.iter().any(|f| {
-                        f.vis != ty::Visibility::Public && !self.private_accessible(def.did)
+                        !f.vis.is_accessible_from(self.curitem, &self.tcx.map)
                     });
                     if any_priv {
                         span_err!(self.tcx.sess, expr.span, E0450,
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index f684f70565d..31d95af4fbb 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -16,7 +16,7 @@ use hir::def::Def;
 use hir::def_id::DefId;
 use rustc::ty::subst;
 use rustc::traits;
-use rustc::ty::{self, TyCtxt, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable, Visibility};
+use rustc::ty::{self, TyCtxt, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
 use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
 use rustc::infer;
 
@@ -343,7 +343,7 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let def = pick.item.def();
 
     if let probe::InherentImplPick = pick.kind {
-        if pick.item.vis() != Visibility::Public && !fcx.private_item_is_visible(def.def_id()) {
+        if !pick.item.vis().is_accessible_from(fcx.body_id, &fcx.tcx().map) {
             let msg = format!("{} `{}` is private", def.kind_name(), &method_name.as_str());
             fcx.tcx().sess.span_err(span, &msg);
         }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index bf6394a03d0..0ffbbfea84e 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -20,7 +20,7 @@ use hir::def::Def;
 use rustc::ty::subst;
 use rustc::ty::subst::Subst;
 use rustc::traits;
-use rustc::ty::{self, NoPreference, Ty, TyCtxt, ToPolyTraitRef, TraitRef, TypeFoldable, Visibility};
+use rustc::ty::{self, NoPreference, Ty, TyCtxt, ToPolyTraitRef, TraitRef, TypeFoldable};
 use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin};
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
@@ -412,7 +412,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             return self.record_static_candidate(ImplSource(impl_def_id));
         }
 
-        if item.vis() != Visibility::Public && !self.fcx.private_item_is_visible(item.def_id()) {
+        if !item.vis().is_accessible_from(self.fcx.body_id, &self.tcx().map) {
             self.private_candidate = Some(item.def());
             return
         }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 0e2bf89947f..45877d7099b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2054,13 +2054,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
         }
     }
-
-    fn private_item_is_visible(&self, def_id: DefId) -> bool {
-        match self.tcx().map.as_local_node_id(def_id) {
-            Some(node_id) => self.tcx().map.private_item_is_visible_from(node_id, self.body_id),
-            None => false, // Private items from other crates are never visible
-        }
-    }
 }
 
 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
@@ -2966,8 +2959,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     debug!("struct named {:?}",  base_t);
                     if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
                         let field_ty = fcx.field_ty(expr.span, field, substs);
-                        if field.vis == Visibility::Public ||
-                           fcx.private_item_is_visible(base_def.did) {
+                        if field.vis.is_accessible_from(fcx.body_id, &fcx.tcx().map) {
                             return Some(field_ty);
                         }
                         private_candidate = Some((base_def.did, field_ty));
@@ -3079,7 +3071,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 debug!("tuple struct named {:?}",  base_t);
                 if let Some(field) = base_def.struct_variant().fields.get(idx.node) {
                     let field_ty = fcx.field_ty(expr.span, field, substs);
-                    if field.vis == Visibility::Public || fcx.private_item_is_visible(base_def.did) {
+                    if field.vis.is_accessible_from(fcx.body_id, &fcx.tcx().map) {
                         return Some(field_ty);
                     }
                     private_candidate = Some((base_def.did, field_ty));

From 35204025be872e5c15334e73fa1d488aaa3d69f5 Mon Sep 17 00:00:00 2001
From: Jeffrey Seyfried 
Date: Fri, 1 Apr 2016 20:16:31 +0000
Subject: [PATCH 11/14] Improve `PrivateItemsInPublicInterfacesVisitor`

---
 src/librustc/ty/mod.rs      |  13 ++-
 src/librustc_privacy/lib.rs | 181 +++++++++++++++++++-----------------
 2 files changed, 109 insertions(+), 85 deletions(-)

diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index c3e1f38180a..47e8f91b48c 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -302,7 +302,7 @@ impl Visibility {
             Visibility::Restricted(module) => module,
         };
 
-        let mut block_ancestor = map.get_module_parent(block);
+        let mut block_ancestor = block;
         loop {
             if block_ancestor == restriction { return true }
             let block_ancestor_parent = map.get_module_parent(block_ancestor);
@@ -310,6 +310,17 @@ impl Visibility {
             block_ancestor = block_ancestor_parent;
         }
     }
+
+    /// Returns true if this visibility is at least as accessible as the given visibility
+    pub fn is_at_least(self, vis: Visibility, map: &ast_map::Map) -> bool {
+        let vis_restriction = match vis {
+            Visibility::Public => return self == Visibility::Public,
+            Visibility::PrivateExternal => return true,
+            Visibility::Restricted(module) => module,
+        };
+
+        self.is_accessible_from(vis_restriction, map)
+    }
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 3b9dc4a4814..a6ce4cc3ee4 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -936,27 +936,41 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
 
 struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
     tcx: &'a TyCtxt<'tcx>,
-    // Do not report an error when a private type is found
-    is_quiet: bool,
-    // Is private component found?
-    is_public: bool,
+    /// The visitor checks that each component type is at least this visible
+    required_visibility: ty::Visibility,
+    /// The visibility of the least visible component that has been visited
+    min_visibility: ty::Visibility,
     old_error_set: &'a NodeSet,
 }
 
 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
-    // Check if the type alias contain private types when substituted
-    fn is_public_type_alias(&self, item: &hir::Item, path: &hir::Path) -> bool {
+    fn new(tcx: &'a TyCtxt<'tcx>, old_error_set: &'a NodeSet) -> Self {
+        SearchInterfaceForPrivateItemsVisitor {
+            tcx: tcx,
+            min_visibility: ty::Visibility::Public,
+            required_visibility: ty::Visibility::PrivateExternal,
+            old_error_set: old_error_set,
+        }
+    }
+}
+
+impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
+    // Return the visibility of the type alias's least visible component type when substituted
+    fn substituted_alias_visibility(&self, item: &hir::Item, path: &hir::Path)
+                                    -> Option {
         // We substitute type aliases only when determining impl publicity
         // FIXME: This will probably change and all type aliases will be substituted,
         // requires an amendment to RFC 136.
-        if !self.is_quiet {
-            return false
+        if self.required_visibility != ty::Visibility::PrivateExternal {
+            return None;
         }
         // Type alias is considered public if the aliased type is
         // public, even if the type alias itself is private. So, something
         // like `type A = u8; pub fn f() -> A {...}` doesn't cause an error.
         if let hir::ItemTy(ref ty, ref generics) = item.node {
-            let mut check = SearchInterfaceForPrivateItemsVisitor { is_public: true, ..*self };
+            let mut check = SearchInterfaceForPrivateItemsVisitor {
+                min_visibility: ty::Visibility::Public, ..*self
+            };
             check.visit_ty(ty);
             // If a private type alias with default type parameters is used in public
             // interface we must ensure, that the defaults are public if they are actually used.
@@ -970,26 +984,23 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
                     check.visit_ty(default_ty);
                 }
             }
-            check.is_public
+            Some(check.min_visibility)
         } else {
-            false
+            None
         }
     }
 }
 
 impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, ty: &hir::Ty) {
-        if self.is_quiet && !self.is_public {
-            // We are in quiet mode and a private type is already found, no need to proceed
-            return
-        }
         if let hir::TyPath(_, ref path) = ty.node {
             let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
             match def {
                 Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
                     // Public
                 }
-                Def::AssociatedTy(..) if self.is_quiet => {
+                Def::AssociatedTy(..)
+                    if self.required_visibility == ty::Visibility::PrivateExternal => {
                     // Conservatively approximate the whole type alias as public without
                     // recursing into its components when determining impl publicity.
                     // For example, `impl ::Alias {...}` may be a public impl
@@ -1003,21 +1014,24 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
                     // Non-local means public (private items can't leave their crate, modulo bugs)
                     if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
                         let item = self.tcx.map.expect_item(node_id);
-                        if item.vis != hir::Public && !self.is_public_type_alias(item, path) {
-                            if !self.is_quiet {
-                                if self.old_error_set.contains(&ty.id) {
-                                    span_err!(self.tcx.sess, ty.span, E0446,
-                                              "private type in public interface");
-                                } else {
-                                    self.tcx.sess.add_lint (
-                                        lint::builtin::PRIVATE_IN_PUBLIC,
-                                        node_id,
-                                        ty.span,
-                                        format!("private type in public interface"),
-                                    );
-                                }
+                        let vis = match self.substituted_alias_visibility(item, path) {
+                            Some(vis) => vis,
+                            None => ty::Visibility::from_hir(&item.vis, node_id, &self.tcx),
+                        };
+
+                        if !vis.is_at_least(self.min_visibility, &self.tcx.map) {
+                            self.min_visibility = vis;
+                        }
+                        if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
+                            if self.old_error_set.contains(&ty.id) {
+                                span_err!(self.tcx.sess, ty.span, E0446,
+                                          "private type in public interface");
+                            } else {
+                                self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
+                                                       node_id,
+                                                       ty.span,
+                                                       format!("private type in public interface"));
                             }
-                            self.is_public = false;
                         }
                     }
                 }
@@ -1029,28 +1043,26 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
     }
 
     fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) {
-        if self.is_quiet && !self.is_public {
-            // We are in quiet mode and a private type is already found, no need to proceed
-            return
-        }
         // Non-local means public (private items can't leave their crate, modulo bugs)
         let def_id = self.tcx.trait_ref_to_def_id(trait_ref);
         if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
             let item = self.tcx.map.expect_item(node_id);
-            if item.vis != hir::Public {
-                if !self.is_quiet {
-                    if self.old_error_set.contains(&trait_ref.ref_id) {
-                        span_err!(self.tcx.sess, trait_ref.path.span, E0445,
-                                  "private trait in public interface");
-                    } else {
-                        self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
-                                               node_id,
-                                               trait_ref.path.span,
-                                               "private trait in public interface (error E0445)"
-                                                    .to_string());
-                    }
+            let vis = ty::Visibility::from_hir(&item.vis, node_id, &self.tcx);
+
+            if !vis.is_at_least(self.min_visibility, &self.tcx.map) {
+                self.min_visibility = vis;
+            }
+            if !vis.is_at_least(self.required_visibility, &self.tcx.map) {
+                if self.old_error_set.contains(&trait_ref.ref_id) {
+                    span_err!(self.tcx.sess, trait_ref.path.span, E0445,
+                              "private trait in public interface");
+                } else {
+                    self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
+                                           node_id,
+                                           trait_ref.path.span,
+                                           "private trait in public interface (error E0445)"
+                                                .to_string());
                 }
-                self.is_public = false;
             }
         }
 
@@ -1072,29 +1084,29 @@ struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
     // A type is considered public if it doesn't contain any private components
-    fn is_public_ty(&self, ty: &hir::Ty) -> bool {
-        let mut check = SearchInterfaceForPrivateItemsVisitor {
-            tcx: self.tcx, is_quiet: true, is_public: true, old_error_set: self.old_error_set
-        };
+    fn ty_visibility(&self, ty: &hir::Ty) -> ty::Visibility {
+        let mut check = SearchInterfaceForPrivateItemsVisitor::new(self.tcx, self.old_error_set);
         check.visit_ty(ty);
-        check.is_public
+        check.min_visibility
     }
 
     // A trait reference is considered public if it doesn't contain any private components
-    fn is_public_trait_ref(&self, trait_ref: &hir::TraitRef) -> bool {
-        let mut check = SearchInterfaceForPrivateItemsVisitor {
-            tcx: self.tcx, is_quiet: true, is_public: true, old_error_set: self.old_error_set
-        };
+    fn trait_ref_visibility(&self, trait_ref: &hir::TraitRef) -> ty::Visibility {
+        let mut check = SearchInterfaceForPrivateItemsVisitor::new(self.tcx, self.old_error_set);
         check.visit_trait_ref(trait_ref);
-        check.is_public
+        check.min_visibility
     }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
-        let mut check = SearchInterfaceForPrivateItemsVisitor {
-            tcx: self.tcx, is_quiet: false, is_public: true, old_error_set: self.old_error_set
+        let min = |vis1: ty::Visibility, vis2| {
+            if vis1.is_at_least(vis2, &self.tcx.map) { vis2 } else { vis1 }
         };
+
+        let mut check = SearchInterfaceForPrivateItemsVisitor::new(self.tcx, self.old_error_set);
+        let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, &self.tcx);
+
         match item.node {
             // Crates are always public
             hir::ItemExternCrate(..) => {}
@@ -1105,27 +1117,26 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivateItemsInPublicInterfacesVisitor<'a, 'tc
             // Subitems of these items have inherited publicity
             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
             hir::ItemEnum(..) | hir::ItemTrait(..) | hir::ItemTy(..) => {
-                if item.vis == hir::Public {
-                    check.visit_item(item);
-                }
+                check.required_visibility = item_visibility;
+                check.visit_item(item);
             }
             // Subitems of foreign modules have their own publicity
             hir::ItemForeignMod(ref foreign_mod) => {
                 for foreign_item in &foreign_mod.items {
-                    if foreign_item.vis == hir::Public {
-                        check.visit_foreign_item(foreign_item);
-                    }
+                    check.required_visibility =
+                        ty::Visibility::from_hir(&foreign_item.vis, item.id, &self.tcx);
+                    check.visit_foreign_item(foreign_item);
                 }
             }
             // Subitems of structs have their own publicity
             hir::ItemStruct(ref struct_def, ref generics) => {
-                if item.vis == hir::Public {
-                    check.visit_generics(generics);
-                    for field in struct_def.fields() {
-                        if field.vis == hir::Public {
-                            check.visit_struct_field(field);
-                        }
-                    }
+                check.required_visibility = item_visibility;
+                check.visit_generics(generics);
+
+                for field in struct_def.fields() {
+                    let field_visibility = ty::Visibility::from_hir(&field.vis, item.id, &self.tcx);
+                    check.required_visibility = min(item_visibility, field_visibility);
+                    check.visit_struct_field(field);
                 }
             }
             // The interface is empty
@@ -1133,23 +1144,25 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivateItemsInPublicInterfacesVisitor<'a, 'tc
             // An inherent impl is public when its type is public
             // Subitems of inherent impls have their own publicity
             hir::ItemImpl(_, _, ref generics, None, ref ty, ref impl_items) => {
-                if self.is_public_ty(ty) {
-                    check.visit_generics(generics);
-                    for impl_item in impl_items {
-                        if impl_item.vis == hir::Public {
-                            check.visit_impl_item(impl_item);
-                        }
-                    }
+                let ty_vis = self.ty_visibility(ty);
+                check.required_visibility = ty_vis;
+                check.visit_generics(generics);
+
+                for impl_item in impl_items {
+                    let impl_item_vis =
+                        ty::Visibility::from_hir(&impl_item.vis, item.id, &self.tcx);
+                    check.required_visibility = min(impl_item_vis, ty_vis);
+                    check.visit_impl_item(impl_item);
                 }
             }
             // A trait impl is public when both its type and its trait are public
             // Subitems of trait impls have inherited publicity
             hir::ItemImpl(_, _, ref generics, Some(ref trait_ref), ref ty, ref impl_items) => {
-                if self.is_public_ty(ty) && self.is_public_trait_ref(trait_ref) {
-                    check.visit_generics(generics);
-                    for impl_item in impl_items {
-                        check.visit_impl_item(impl_item);
-                    }
+                let vis = min(self.ty_visibility(ty), self.trait_ref_visibility(trait_ref));
+                check.required_visibility = vis;
+                check.visit_generics(generics);
+                for impl_item in impl_items {
+                    check.visit_impl_item(impl_item);
                 }
             }
         }

From dcd4621b4df9c1962ea55653e3f01cdf8b6a3e12 Mon Sep 17 00:00:00 2001
From: Jeffrey Seyfried 
Date: Sat, 2 Apr 2016 02:22:41 +0000
Subject: [PATCH 12/14] Add test for #30079

---
 src/test/compile-fail/issue-30079.rs | 55 ++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 src/test/compile-fail/issue-30079.rs

diff --git a/src/test/compile-fail/issue-30079.rs b/src/test/compile-fail/issue-30079.rs
new file mode 100644
index 00000000000..a8db01b82da
--- /dev/null
+++ b/src/test/compile-fail/issue-30079.rs
@@ -0,0 +1,55 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+#![allow(unused)]
+
+struct SemiPriv;
+
+mod m1 {
+    struct Priv;
+    impl ::SemiPriv {
+        pub fn f(_: Priv) {} //~ WARN private type in public interface
+        //~^ WARNING hard error
+    }
+
+    impl Priv {
+        pub fn f(_: Priv) {} // ok
+    }
+}
+
+mod m2 {
+    struct Priv;
+    impl ::std::ops::Deref for ::SemiPriv {
+        type Target = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
+        fn deref(&self) -> &Self::Target { unimplemented!() }
+    }
+
+    impl ::std::ops::Deref for Priv {
+        type Target = Priv; // ok
+        fn deref(&self) -> &Self::Target { unimplemented!() }
+    }
+}
+
+trait SemiPrivTrait {
+    type Assoc;
+}
+
+mod m3 {
+    struct Priv;
+    impl ::SemiPrivTrait for () {
+        type Assoc = Priv; //~ WARN private type in public interface
+        //~^ WARNING hard error
+    }
+}
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful

From 35f5e18f75d07873be768c2afe65d13d3a25f9d2 Mon Sep 17 00:00:00 2001
From: Jeffrey Seyfried 
Date: Thu, 7 Apr 2016 03:48:52 +0000
Subject: [PATCH 13/14] Fix fallout in tests

---
 .../compile-fail-fulldeps/macro-crate-doesnt-resolve.rs   | 1 -
 src/test/compile-fail/bad-module.rs                       | 2 +-
 src/test/compile-fail/bad-type-env-capture.rs             | 1 -
 src/test/compile-fail/export-fully-qualified.rs           | 2 +-
 src/test/compile-fail/export2.rs                          | 2 +-
 src/test/compile-fail/inner-static-type-parameter.rs      | 1 -
 src/test/compile-fail/issue-12796.rs                      | 1 -
 src/test/compile-fail/issue-3021-b.rs                     | 1 -
 src/test/compile-fail/issue-3021-c.rs                     | 2 --
 src/test/compile-fail/issue-3021-d.rs                     | 2 --
 src/test/compile-fail/issue-3021.rs                       | 1 -
 src/test/compile-fail/issue-3214.rs                       | 1 -
 src/test/compile-fail/issue-3521-2.rs                     | 1 -
 src/test/compile-fail/issue-3521.rs                       | 3 +--
 src/test/compile-fail/issue-3668-2.rs                     | 1 -
 src/test/compile-fail/issue-3668.rs                       | 1 -
 src/test/compile-fail/issue-5997-enum.rs                  | 1 -
 src/test/compile-fail/issue-5997-struct.rs                | 3 +--
 src/test/compile-fail/issue-6642.rs                       | 1 -
 src/test/compile-fail/macro-inner-attributes.rs           | 1 -
 src/test/compile-fail/no-link.rs                          | 1 -
 .../compile-fail/resolve-type-param-in-item-in-trait.rs   | 8 ++------
 22 files changed, 7 insertions(+), 31 deletions(-)

diff --git a/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs b/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs
index 8ac03606720..1fbde00a3df 100644
--- a/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs
+++ b/src/test/compile-fail-fulldeps/macro-crate-doesnt-resolve.rs
@@ -16,5 +16,4 @@ extern crate macro_crate_test;
 fn main() {
     macro_crate_test::foo();
     //~^ ERROR failed to resolve. Use of undeclared type or module `macro_crate_test`
-    //~^^ ERROR unresolved name `macro_crate_test::foo`
 }
diff --git a/src/test/compile-fail/bad-module.rs b/src/test/compile-fail/bad-module.rs
index edc118cb039..0cd3a885318 100644
--- a/src/test/compile-fail/bad-module.rs
+++ b/src/test/compile-fail/bad-module.rs
@@ -8,6 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name
+// error-pattern: failed to resolve. Use of undeclared type or module `thing`
 
 fn main() { let foo = thing::len(Vec::new()); }
diff --git a/src/test/compile-fail/bad-type-env-capture.rs b/src/test/compile-fail/bad-type-env-capture.rs
index a3139905244..c1547dd82b3 100644
--- a/src/test/compile-fail/bad-type-env-capture.rs
+++ b/src/test/compile-fail/bad-type-env-capture.rs
@@ -10,6 +10,5 @@
 
 fn foo() {
     fn bar(b: T) { } //~ ERROR can't use type parameters from outer
-    //~^ ERROR type name `T` is undefined or not in scope
 }
 fn main() { }
diff --git a/src/test/compile-fail/export-fully-qualified.rs b/src/test/compile-fail/export-fully-qualified.rs
index 2ba2ef1c05a..166ef7ab87f 100644
--- a/src/test/compile-fail/export-fully-qualified.rs
+++ b/src/test/compile-fail/export-fully-qualified.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name
+// error-pattern: failed to resolve. Use of undeclared type or module `foo`
 
 // In this test baz isn't resolved when called as foo.baz even though
 // it's called from inside foo. This is somewhat surprising and may
diff --git a/src/test/compile-fail/export2.rs b/src/test/compile-fail/export2.rs
index 6104c02c90a..f7b1400aa45 100644
--- a/src/test/compile-fail/export2.rs
+++ b/src/test/compile-fail/export2.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: unresolved name
+// error-pattern: failed to resolve. Use of undeclared type or module `bar`
 
 mod foo {
     pub fn x() { bar::x(); }
diff --git a/src/test/compile-fail/inner-static-type-parameter.rs b/src/test/compile-fail/inner-static-type-parameter.rs
index 6fcda66486b..a6a33198458 100644
--- a/src/test/compile-fail/inner-static-type-parameter.rs
+++ b/src/test/compile-fail/inner-static-type-parameter.rs
@@ -15,7 +15,6 @@ enum Bar { What } //~ ERROR parameter `T` is never used
 fn foo() {
     static a: Bar = Bar::What;
     //~^ ERROR cannot use an outer type parameter in this context
-    //~| ERROR type name `T` is undefined or not in scope
 }
 
 fn main() {
diff --git a/src/test/compile-fail/issue-12796.rs b/src/test/compile-fail/issue-12796.rs
index 33fbdce4ee2..0c3c82a99f2 100644
--- a/src/test/compile-fail/issue-12796.rs
+++ b/src/test/compile-fail/issue-12796.rs
@@ -12,7 +12,6 @@ trait Trait {
     fn outer(&self) {
         fn inner(_: &Self) {
             //~^ ERROR can't use type parameters from outer function
-            //~^^ ERROR use of `Self` outside of an impl or trait
         }
     }
 }
diff --git a/src/test/compile-fail/issue-3021-b.rs b/src/test/compile-fail/issue-3021-b.rs
index 5c539cd739c..2b0a24cfdb3 100644
--- a/src/test/compile-fail/issue-3021-b.rs
+++ b/src/test/compile-fail/issue-3021-b.rs
@@ -17,7 +17,6 @@ fn siphash(k0 : u64) {
     impl siphash {
         pub fn reset(&mut self) {
            self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
-           //~^ ERROR unresolved name `k0`
         }
     }
 }
diff --git a/src/test/compile-fail/issue-3021-c.rs b/src/test/compile-fail/issue-3021-c.rs
index 03473bd44cc..635006a3b4d 100644
--- a/src/test/compile-fail/issue-3021-c.rs
+++ b/src/test/compile-fail/issue-3021-c.rs
@@ -13,8 +13,6 @@ fn siphash() {
     trait t {
         fn g(&self, x: T) -> T;  //~ ERROR can't use type parameters from outer function; try using
         //~^ ERROR can't use type parameters from outer function; try using
-        //~^^ ERROR type name `T` is undefined or not in scope
-        //~^^^ ERROR type name `T` is undefined or not in scope
     }
 }
 
diff --git a/src/test/compile-fail/issue-3021-d.rs b/src/test/compile-fail/issue-3021-d.rs
index ecc8ac34ecf..c23e12e713a 100644
--- a/src/test/compile-fail/issue-3021-d.rs
+++ b/src/test/compile-fail/issue-3021-d.rs
@@ -29,9 +29,7 @@ fn siphash(k0 : u64, k1 : u64) {
    impl siphash for SipState {
         fn reset(&self) {
             self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
-            //~^ ERROR unresolved name `k0`
             self.v1 = k1 ^ 0x646f72616e646f6d; //~ ERROR can't capture dynamic environment
-            //~^ ERROR unresolved name `k1`
         }
         fn result(&self) -> u64 { return mk_result(self); }
     }
diff --git a/src/test/compile-fail/issue-3021.rs b/src/test/compile-fail/issue-3021.rs
index 7cf772b0728..f93a333d2ae 100644
--- a/src/test/compile-fail/issue-3021.rs
+++ b/src/test/compile-fail/issue-3021.rs
@@ -20,7 +20,6 @@ fn siphash(k0 : u64) {
     impl SipHash for SipState {
         fn reset(&self) {
            self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
-           //~^ ERROR unresolved name `k0`
         }
     }
     panic!();
diff --git a/src/test/compile-fail/issue-3214.rs b/src/test/compile-fail/issue-3214.rs
index 4f955df8205..d3b932fbc53 100644
--- a/src/test/compile-fail/issue-3214.rs
+++ b/src/test/compile-fail/issue-3214.rs
@@ -11,7 +11,6 @@
 fn foo() {
     struct foo {
         x: T, //~ ERROR can't use type parameters from outer function;
-        //~^ ERROR type name `T` is undefined or not in scope
     }
 
     impl Drop for foo {
diff --git a/src/test/compile-fail/issue-3521-2.rs b/src/test/compile-fail/issue-3521-2.rs
index ad5bc4e445c..6cd2c02c417 100644
--- a/src/test/compile-fail/issue-3521-2.rs
+++ b/src/test/compile-fail/issue-3521-2.rs
@@ -13,7 +13,6 @@ fn main() {
 
     static y: isize = foo + 1;
     //~^ ERROR attempt to use a non-constant value in a constant
-    //~| ERROR unresolved name `foo`
 
     println!("{}", y);
 }
diff --git a/src/test/compile-fail/issue-3521.rs b/src/test/compile-fail/issue-3521.rs
index 34cd8cae2de..52375ef281a 100644
--- a/src/test/compile-fail/issue-3521.rs
+++ b/src/test/compile-fail/issue-3521.rs
@@ -15,8 +15,7 @@ fn main() {
     enum Stuff {
         Bar = foo
         //~^ ERROR attempt to use a non-constant value in a constant
-        //~| ERROR unresolved name `foo`
-        //~^^^ ERROR constant evaluation error: non-constant path in constant expression
+        //~^^ ERROR constant evaluation error: non-constant path in constant expression
     }
 
     println!("{}", Stuff::Bar);
diff --git a/src/test/compile-fail/issue-3668-2.rs b/src/test/compile-fail/issue-3668-2.rs
index a09c8090de0..16fb2f68133 100644
--- a/src/test/compile-fail/issue-3668-2.rs
+++ b/src/test/compile-fail/issue-3668-2.rs
@@ -11,7 +11,6 @@
 fn f(x:isize) {
     static child: isize = x + 1;
     //~^ ERROR attempt to use a non-constant value in a constant
-    //~| ERROR unresolved name `x`
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-3668.rs b/src/test/compile-fail/issue-3668.rs
index 9b7476244f0..9c31dc1e38e 100644
--- a/src/test/compile-fail/issue-3668.rs
+++ b/src/test/compile-fail/issue-3668.rs
@@ -17,7 +17,6 @@ impl PTrait for P {
    fn getChildOption(&self) -> Option> {
        static childVal: Box

= self.child.get(); //~^ ERROR attempt to use a non-constant value in a constant - //~| ERROR unresolved name `self` panic!(); } } diff --git a/src/test/compile-fail/issue-5997-enum.rs b/src/test/compile-fail/issue-5997-enum.rs index 20d239c6ae0..463fdaa1069 100644 --- a/src/test/compile-fail/issue-5997-enum.rs +++ b/src/test/compile-fail/issue-5997-enum.rs @@ -11,7 +11,6 @@ fn f() -> bool { enum E { V(Z) } //~^ ERROR can't use type parameters from outer function - //~^^ ERROR type name `Z` is undefined or not in scope true } diff --git a/src/test/compile-fail/issue-5997-struct.rs b/src/test/compile-fail/issue-5997-struct.rs index 40be2f04cb4..e9cfafc98df 100644 --- a/src/test/compile-fail/issue-5997-struct.rs +++ b/src/test/compile-fail/issue-5997-struct.rs @@ -9,8 +9,7 @@ // except according to those terms. fn f() -> bool { - struct S(T); //~ ERROR type name `T` is undefined or not in scope - //~^ ERROR can't use type parameters from outer function; try using + struct S(T); //~ ERROR can't use type parameters from outer function; try using true } diff --git a/src/test/compile-fail/issue-6642.rs b/src/test/compile-fail/issue-6642.rs index 2c1809d4d48..1fe10ba7a27 100644 --- a/src/test/compile-fail/issue-6642.rs +++ b/src/test/compile-fail/issue-6642.rs @@ -13,7 +13,6 @@ impl A { fn m(&self) { fn x() { self.m() //~ ERROR can't capture dynamic environment in a fn item - //~^ ERROR unresolved name `self` } } } diff --git a/src/test/compile-fail/macro-inner-attributes.rs b/src/test/compile-fail/macro-inner-attributes.rs index abf0ed420e7..1111b21d455 100644 --- a/src/test/compile-fail/macro-inner-attributes.rs +++ b/src/test/compile-fail/macro-inner-attributes.rs @@ -26,6 +26,5 @@ test!(b, fn main() { a::bar(); //~^ ERROR failed to resolve. Use of undeclared type or module `a` - //~^^ ERROR unresolved name `a::bar` b::bar(); } diff --git a/src/test/compile-fail/no-link.rs b/src/test/compile-fail/no-link.rs index a9c2b6a942c..957b6cda553 100644 --- a/src/test/compile-fail/no-link.rs +++ b/src/test/compile-fail/no-link.rs @@ -14,6 +14,5 @@ extern crate libc; fn main() { unsafe { libc::abs(0); //~ ERROR Use of undeclared type or module `libc` - //~^ ERROR unresolved name `libc::abs` } } diff --git a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs index 92134ecde91..30ff1ed0e26 100644 --- a/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs +++ b/src/test/compile-fail/resolve-type-param-in-item-in-trait.rs @@ -18,7 +18,6 @@ trait TraitA { //~^ ERROR parameter `B` is never used Variance(A) //~^ ERROR can't use type parameters from outer function - //~^^ ERROR type name `A` is undefined or not in scope } } } @@ -27,8 +26,7 @@ trait TraitB { fn outer(self) { struct Foo(A); //~^ ERROR can't use type parameters from outer function - //~^^ ERROR type name `A` is undefined or not in scope - //~^^^ ERROR parameter `B` is never used + //~^^ ERROR parameter `B` is never used } } @@ -36,8 +34,7 @@ trait TraitC { fn outer(self) { struct Foo { a: A } //~^ ERROR can't use type parameters from outer function - //~^^ ERROR type name `A` is undefined or not in scope - //~^^^ ERROR parameter `B` is never used + //~^^ ERROR parameter `B` is never used } } @@ -45,7 +42,6 @@ trait TraitD { fn outer(self) { fn foo(a: A) { } //~^ ERROR can't use type parameters from outer function - //~^^ ERROR type name `A` is undefined or not in scope } } From 07dac9732d65dcb1f5aefc8be46ba366fb657d08 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 7 Apr 2016 04:13:34 +0000 Subject: [PATCH 14/14] Fix tidy errors --- src/librustc_resolve/lib.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e8adb1d94ba..3f18aa35654 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1902,7 +1902,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }).map_err(|error_reported| { self.record_def(eq_pred.id, err_path_resolution()); if error_reported { return } - resolve_error(self, eq_pred.span, ResolutionError::UndeclaredAssociatedType); + let error_variant = ResolutionError::UndeclaredAssociatedType; + resolve_error(self, eq_pred.span, error_variant); }).unwrap_or(()); } } @@ -3042,7 +3043,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(expr.id, err_path_resolution()); if let Ok(Def::Struct(..)) = type_res.map(|r| r.base_def) { - let error_variant = ResolutionError::StructVariantUsedAsFunction(&path_name); + let error_variant = + ResolutionError::StructVariantUsedAsFunction(&path_name); let mut err = resolve_struct_error(self, expr.span, error_variant); let msg = format!("did you mean to write: `{} {{ /* fields */ }}`?",