Skip to content

Check privacy of trait items in all contexts #41332

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 26, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Check privacy of trait items in all contexts
  • Loading branch information
petrochenkov committed Apr 25, 2017
commit 82e030322bd47d0ac3d1639cabf93e24dbdc1779
25 changes: 11 additions & 14 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2156,6 +2156,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

fn associated_item_from_trait_item_ref(self,
parent_def_id: DefId,
parent_vis: &hir::Visibility,
trait_item_ref: &hir::TraitItemRef)
-> AssociatedItem {
let def_id = self.hir.local_def_id(trait_item_ref.id.node_id);
Expand All @@ -2170,7 +2171,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
AssociatedItem {
name: trait_item_ref.name,
kind: kind,
vis: Visibility::from_hir(&hir::Inherited, trait_item_ref.id.node_id, self),
// Visibility of trait items is inherited from their traits.
vis: Visibility::from_hir(parent_vis, trait_item_ref.id.node_id, self),
defaultness: trait_item_ref.defaultness,
def_id: def_id,
container: TraitContainer(parent_def_id),
Expand All @@ -2180,7 +2182,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

fn associated_item_from_impl_item_ref(self,
parent_def_id: DefId,
from_trait_impl: bool,
impl_item_ref: &hir::ImplItemRef)
-> AssociatedItem {
let def_id = self.hir.local_def_id(impl_item_ref.id.node_id);
Expand All @@ -2192,14 +2193,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
};

// Trait impl items are always public.
let public = hir::Public;
let vis = if from_trait_impl { &public } else { &impl_item_ref.vis };

ty::AssociatedItem {
name: impl_item_ref.name,
kind: kind,
vis: ty::Visibility::from_hir(vis, impl_item_ref.id.node_id, self),
// Visibility of trait impl items doesn't matter.
vis: ty::Visibility::from_hir(&impl_item_ref.vis, impl_item_ref.id.node_id, self),
defaultness: impl_item_ref.defaultness,
def_id: def_id,
container: ImplContainer(parent_def_id),
Expand Down Expand Up @@ -2639,21 +2637,20 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
let parent_def_id = tcx.hir.local_def_id(parent_id);
let parent_item = tcx.hir.expect_item(parent_id);
match parent_item.node {
hir::ItemImpl(.., ref impl_trait_ref, _, ref impl_item_refs) => {
hir::ItemImpl(.., ref impl_item_refs) => {
if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.node_id == id) {
let assoc_item =
tcx.associated_item_from_impl_item_ref(parent_def_id,
impl_trait_ref.is_some(),
impl_item_ref);
let assoc_item = tcx.associated_item_from_impl_item_ref(parent_def_id,
impl_item_ref);
debug_assert_eq!(assoc_item.def_id, def_id);
return assoc_item;
}
}

hir::ItemTrait(.., ref trait_item_refs) => {
if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.node_id == id) {
let assoc_item =
tcx.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref);
let assoc_item = tcx.associated_item_from_trait_item_ref(parent_def_id,
&parent_item.vis,
trait_item_ref);
debug_assert_eq!(assoc_item.def_id, def_id);
return assoc_item;
}
Expand Down
27 changes: 0 additions & 27 deletions src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,14 +427,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
}

impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
fn item_is_accessible(&self, did: DefId) -> bool {
match self.tcx.hir.as_local_node_id(did) {
Some(node_id) =>
ty::Visibility::from_hir(&self.tcx.hir.expect_item(node_id).vis, node_id, self.tcx),
None => self.tcx.sess.cstore.visibility(did),
}.is_accessible_from(self.curitem, self.tcx)
}

// Checks that a field is in scope.
fn check_field(&mut self, span: Span, def: &'tcx ty::AdtDef, field: &'tcx ty::FieldDef) {
if !def.is_enum() && !field.vis.is_accessible_from(self.curitem, self.tcx) {
Expand All @@ -444,20 +436,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
.emit();
}
}

// Checks that a method is in scope.
fn check_method(&mut self, span: Span, method_def_id: DefId) {
match self.tcx.associated_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_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);
}
_ => {}
}
}
}

impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
Expand All @@ -483,11 +461,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {

fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
match expr.node {
hir::ExprMethodCall(..) => {
let method_call = ty::MethodCall::expr(expr.id);
let method = self.tables.method_map[&method_call];
self.check_method(expr.span, method.def_id);
}
hir::ExprStruct(ref qpath, ref expr_fields, _) => {
let def = self.tables.qpath_def(qpath, expr.id);
let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap();
Expand Down
14 changes: 10 additions & 4 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,10 +903,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
let ty = self.normalize_ty(span, ty);

let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name);
let def_id = item.expect("missing associated type").def_id;
tcx.check_stability(def_id, ref_id, span);
(ty, Def::AssociatedTy(def_id))
let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name)
.expect("missing associated type");
let def = Def::AssociatedTy(item.def_id);
if !tcx.vis_is_accessible_from(item.vis, ref_id) {
let msg = format!("{} `{}` is private", def.kind_name(), assoc_name);
tcx.sess.span_err(span, &msg);
}
tcx.check_stability(item.def_id, ref_id, span);

(ty, def)
}

fn qpath_to_ty(&self,
Expand Down
7 changes: 0 additions & 7 deletions src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,15 +349,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}

let def = pick.item.def();

self.tcx.check_stability(def.def_id(), expr_id, span);

if let probe::InherentImplPick = pick.kind {
if !self.tcx.vis_is_accessible_from(pick.item.vis, self.body_id) {
let msg = format!("{} `{}` is private", def.kind_name(), method_name);
self.tcx.sess.span_err(span, &msg);
}
}
Ok(def)
}

Expand Down
78 changes: 30 additions & 48 deletions src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,24 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
///////////////////////////////////////////////////////////////////////////
// CANDIDATE ASSEMBLY

fn push_inherent_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem,
kind: CandidateKind<'tcx>, import_id: Option<ast::NodeId>) {
if self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
self.inherent_candidates.push(Candidate { xform_self_ty, item, kind, import_id });
} else if self.private_candidate.is_none() {
self.private_candidate = Some(item.def());
}
}

fn push_extension_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem,
kind: CandidateKind<'tcx>, import_id: Option<ast::NodeId>) {
if self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
self.extension_candidates.push(Candidate { xform_self_ty, item, kind, import_id });
} else if self.private_candidate.is_none() {
self.private_candidate = Some(item.def());
}
}

fn assemble_inherent_candidates(&mut self) {
let steps = self.steps.clone();
for step in steps.iter() {
Expand Down Expand Up @@ -499,11 +517,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
continue
}

if !self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
self.private_candidate = Some(item.def());
continue
}

let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
let impl_ty = impl_ty.subst(self.tcx, impl_substs);

Expand All @@ -519,12 +532,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
xform_self_ty);

self.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item,
kind: InherentImplCandidate(impl_substs, obligations),
import_id: None,
});
self.push_inherent_candidate(xform_self_ty, item,
InherentImplCandidate(impl_substs, obligations), None);
}
}

Expand All @@ -548,12 +557,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
let xform_self_ty =
this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs);

this.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item,
kind: ObjectCandidate,
import_id: None,
});
this.push_inherent_candidate(xform_self_ty, item, ObjectCandidate, None);
});
}

Expand Down Expand Up @@ -599,12 +603,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
// `WhereClausePick`.
assert!(!trait_ref.substs.needs_infer());

this.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item,
kind: WhereClauseCandidate(poly_trait_ref),
import_id: None,
});
this.push_inherent_candidate(xform_self_ty, item,
WhereClauseCandidate(poly_trait_ref), None);
});
}

Expand Down Expand Up @@ -743,12 +743,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {

debug!("xform_self_ty={:?}", xform_self_ty);

self.extension_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: ExtensionImplCandidate(impl_def_id, impl_substs, obligations),
import_id: import_id,
});
self.push_extension_candidate(xform_self_ty, item,
ExtensionImplCandidate(impl_def_id, impl_substs, obligations), import_id);
});
}

Expand Down Expand Up @@ -833,12 +829,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
});

let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs);
self.inherent_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: TraitCandidate,
import_id: import_id,
});
self.push_inherent_candidate(xform_self_ty, item, TraitCandidate, import_id);
}

Ok(())
Expand All @@ -854,7 +845,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
trait_def_id,
item);

for step in self.steps.iter() {
for step in Rc::clone(&self.steps).iter() {
debug!("assemble_projection_candidates: step={:?}", step);

let (def_id, substs) = match step.self_ty.sty {
Expand Down Expand Up @@ -889,12 +880,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
bound,
xform_self_ty);

self.extension_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: TraitCandidate,
import_id: import_id,
});
self.push_extension_candidate(xform_self_ty, item, TraitCandidate, import_id);
}
}
}
Expand All @@ -918,12 +904,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
bound,
xform_self_ty);

self.extension_candidates.push(Candidate {
xform_self_ty: xform_self_ty,
item: item.clone(),
kind: WhereClauseCandidate(poly_bound),
import_id: import_id,
});
self.push_extension_candidate(xform_self_ty, item,
WhereClauseCandidate(poly_bound), import_id);
}
}

Expand Down
47 changes: 0 additions & 47 deletions src/test/compile-fail/issue-28514.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/test/compile-fail/no-method-suggested-traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct Foo;
enum Bar { X }

mod foo {
trait Bar {
pub trait Bar {
fn method(&self) {}

fn method2(&self) {}
Expand Down
Loading