From 6f16c5c81f86be4b4b50ef5396c6412844235dbf Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Thu, 25 Feb 2016 02:11:29 +0000 Subject: [PATCH] Autoderef privacy for methods --- src/librustc_typeck/check/method/mod.rs | 4 +++ src/librustc_typeck/check/method/probe.rs | 18 +++++++++++- src/librustc_typeck/check/method/suggest.rs | 7 ++++- src/librustc_typeck/check/mod.rs | 31 +++++++++++++-------- 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 11f7feba86b..8c8d02bd3e6 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -43,6 +43,9 @@ pub enum MethodError<'tcx> { // Using a `Fn`/`FnMut`/etc method on a raw closure type before we have inferred its kind. ClosureAmbiguity(/* DefId of fn trait */ DefId), + + // Found an applicable method, but it is not visible. + PrivateMatch(Def), } // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which @@ -90,6 +93,7 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, Err(NoMatch(..)) => false, Err(Ambiguity(..)) => true, Err(ClosureAmbiguity(..)) => true, + Err(PrivateMatch(..)) => true, } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 4b42846297b..477b46ce4ce 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -16,6 +16,7 @@ use super::suggest; use check; use check::{FnCtxt, UnresolvedTypeAction}; use middle::def_id::DefId; +use middle::def::Def; use rustc::ty::subst; use rustc::ty::subst::Subst; use rustc::traits; @@ -47,6 +48,9 @@ struct ProbeContext<'a, 'tcx:'a> { /// used for error reporting static_candidates: Vec, + /// Some(candidate) if there is a private candidate + private_candidate: Option, + /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used /// for error reporting unsatisfied_predicates: Vec> @@ -247,6 +251,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { steps: Rc::new(steps), opt_simplified_steps: opt_simplified_steps, static_candidates: Vec::new(), + private_candidate: None, unsatisfied_predicates: Vec::new(), } } @@ -256,6 +261,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { self.extension_candidates.clear(); self.impl_dups.clear(); self.static_candidates.clear(); + self.private_candidate = None; } fn tcx(&self) -> &'a TyCtxt<'tcx> { @@ -407,6 +413,11 @@ 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()) { + self.private_candidate = Some(item.def()); + return + } + let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id); let impl_ty = impl_ty.subst(self.tcx(), &impl_substs); @@ -846,6 +857,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { } let static_candidates = mem::replace(&mut self.static_candidates, vec![]); + let private_candidate = mem::replace(&mut self.private_candidate, None); let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]); // things failed, so lets look at all traits, for diagnostic purposes now: @@ -879,9 +891,13 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { // this error only occurs when assembling candidates tcx.sess.span_bug(span, "encountered ClosureAmbiguity from pick_core"); } - None => vec![], + _ => vec![], }; + if let Some(def) = private_candidate { + return Err(MethodError::PrivateMatch(def)); + } + Err(MethodError::NoMatch(NoMatchData::new(static_candidates, unsatisfied_predicates, out_of_scope_traits, self.mode))) } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index aae7912cace..f1d67883117 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -91,7 +91,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, MethodError::NoMatch(NoMatchData { static_candidates: static_sources, unsatisfied_predicates, out_of_scope_traits, - mode }) => { + mode, .. }) => { let cx = fcx.tcx(); let mut err = fcx.type_error_struct( @@ -208,6 +208,11 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, }; fcx.sess().span_err(span, &msg); } + + MethodError::PrivateMatch(def) => { + let msg = format!("{} `{}` is private", def.kind_name(), item_name); + fcx.tcx().sess.span_err(span, &msg); + } } fn report_candidates(fcx: &FnCtxt, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 294ebb9915b..78694b2e96f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3757,23 +3757,30 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>, &ty_segments[base_ty_end..]); let item_segment = path.segments.last().unwrap(); let item_name = item_segment.identifier.name; - match method::resolve_ufcs(fcx, span, item_name, ty, node_id) { - Ok(def) => { - // Write back the new resolution. - fcx.ccx.tcx.def_map.borrow_mut() - .insert(node_id, def::PathResolution { - base_def: def, - depth: 0 - }); - Some((Some(ty), slice::ref_slice(item_segment), def)) - } + let def = match method::resolve_ufcs(fcx, span, item_name, ty, node_id) { + Ok(def) => Some(def), Err(error) => { + let def = match error { + method::MethodError::PrivateMatch(def) => Some(def), + _ => None, + }; if item_name != special_idents::invalid.name { method::report_error(fcx, span, ty, item_name, None, error); } - fcx.write_error(node_id); - None + def } + }; + + if let Some(def) = def { + // Write back the new resolution. + fcx.ccx.tcx.def_map.borrow_mut().insert(node_id, def::PathResolution { + base_def: def, + depth: 0, + }); + Some((Some(ty), slice::ref_slice(item_segment), def)) + } else { + fcx.write_error(node_id); + None } } }