Autoderef privacy for methods
This commit is contained in:
parent
62d181f474
commit
6f16c5c81f
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<CandidateSource>,
|
||||
|
||||
/// Some(candidate) if there is a private candidate
|
||||
private_candidate: Option<Def>,
|
||||
|
||||
/// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
|
||||
/// for error reporting
|
||||
unsatisfied_predicates: Vec<TraitRef<'tcx>>
|
||||
|
@ -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)))
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue