Skip to content

Commit 53779ed

Browse files
committed
Check associated type bindings for privacy and stability
1 parent 8dcd26a commit 53779ed

File tree

4 files changed

+45
-24
lines changed

4 files changed

+45
-24
lines changed

src/librustc_typeck/astconv.rs

+26-24
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
370370
poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
371371
// specify type to assert that error was already reported in Err case:
372372
let predicate: Result<_, ErrorReported> =
373-
self.ast_type_binding_to_poly_projection_predicate(poly_trait_ref, binding);
373+
self.ast_type_binding_to_poly_projection_predicate(trait_ref.ref_id, poly_trait_ref,
374+
binding);
374375
predicate.ok() // ok to ignore Err() because ErrorReported (see above)
375376
}));
376377

@@ -442,6 +443,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
442443

443444
fn ast_type_binding_to_poly_projection_predicate(
444445
&self,
446+
ref_id: ast::NodeId,
445447
trait_ref: ty::PolyTraitRef<'tcx>,
446448
binding: &ConvertedBinding<'tcx>)
447449
-> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
@@ -494,30 +496,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
494496
.emit();
495497
}
496498

497-
// Simple case: X is defined in the current trait.
498-
if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
499-
return Ok(trait_ref.map_bound(|trait_ref| {
500-
ty::ProjectionPredicate {
501-
projection_ty: ty::ProjectionTy::from_ref_and_name(
502-
tcx,
503-
trait_ref,
504-
binding.item_name,
505-
),
506-
ty: binding.ty,
507-
}
508-
}));
499+
let candidate = if self.trait_defines_associated_type_named(trait_ref.def_id(),
500+
binding.item_name) {
501+
// Simple case: X is defined in the current trait.
502+
Ok(trait_ref)
503+
} else {
504+
// Otherwise, we have to walk through the supertraits to find
505+
// those that do.
506+
let candidates = traits::supertraits(tcx, trait_ref).filter(|r| {
507+
self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
508+
});
509+
self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(),
510+
binding.item_name, binding.span)
511+
}?;
512+
513+
let (assoc_ident, def_scope) = tcx.adjust(binding.item_name, candidate.def_id(), ref_id);
514+
let assoc_ty = tcx.associated_items(candidate.def_id()).find(|i| {
515+
i.kind == ty::AssociatedKind::Type && i.name.to_ident() == assoc_ident
516+
}).expect("missing associated type");
517+
518+
if !assoc_ty.vis.is_accessible_from(def_scope, tcx) {
519+
let msg = format!("associated type `{}` is private", binding.item_name);
520+
tcx.sess.span_err(binding.span, &msg);
509521
}
510-
511-
// Otherwise, we have to walk through the supertraits to find
512-
// those that do.
513-
let candidates =
514-
traits::supertraits(tcx, trait_ref.clone())
515-
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name));
516-
517-
let candidate = self.one_bound_for_assoc_type(candidates,
518-
&trait_ref.to_string(),
519-
binding.item_name,
520-
binding.span)?;
522+
tcx.check_stability(assoc_ty.def_id, ref_id, binding.span);
521523

522524
Ok(candidate.map_bound(|trait_ref| {
523525
ty::ProjectionPredicate {

src/test/compile-fail/lint-stability-deprecated.rs

+5
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ mod cross_crate {
108108
struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
109109
struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
110110
//~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
111+
type A = TraitWithAssociatedTypes<
112+
TypeUnstable = u8,
113+
TypeDeprecated = u16,
114+
//~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated'
115+
>;
111116

112117
let _ = DeprecatedStruct { //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct'
113118
i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct::i'

src/test/compile-fail/lint-stability.rs

+4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ mod cross_crate {
9696
struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
9797
//~^ ERROR use of unstable library feature
9898
struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
99+
type A = TraitWithAssociatedTypes<
100+
TypeUnstable = u8, //~ ERROR use of unstable library feature
101+
TypeDeprecated = u16,
102+
>;
99103

100104
let _ = DeprecatedStruct {
101105
i: 0

src/test/compile-fail/trait-item-privacy.rs

+10
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,16 @@ fn check_assoc_ty<T: assoc_ty::C>() {
131131
let _: T::A; //~ ERROR associated type `A` is private
132132
let _: T::B; // OK
133133
let _: T::C; // OK
134+
135+
// Associated types, bindings
136+
let _: assoc_ty::B<
137+
B = u8, // OK
138+
>;
139+
let _: C<
140+
A = u8, //~ ERROR associated type `A` is private
141+
B = u8, // OK
142+
C = u8, // OK
143+
>;
134144
}
135145

136146
fn main() {}

0 commit comments

Comments
 (0)