diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2017-11-18 18:38:56 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2017-12-21 03:17:19 +0300 |
| commit | 53779ed5ec8077fd11d5ea9c3e0e1c404ee92c36 (patch) | |
| tree | 0f1d96b4b10c57ae64bd20d37d4e48e80c377b13 | |
| parent | 8dcd26a6df4bb932cd94404a6c941d84a3d1d851 (diff) | |
| download | rust-53779ed5ec8077fd11d5ea9c3e0e1c404ee92c36.tar.gz rust-53779ed5ec8077fd11d5ea9c3e0e1c404ee92c36.zip | |
Check associated type bindings for privacy and stability
| -rw-r--r-- | src/librustc_typeck/astconv.rs | 50 | ||||
| -rw-r--r-- | src/test/compile-fail/lint-stability-deprecated.rs | 5 | ||||
| -rw-r--r-- | src/test/compile-fail/lint-stability.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/trait-item-privacy.rs | 10 |
4 files changed, 45 insertions, 24 deletions
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6b37a30cb82..ba0e7916892 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -370,7 +370,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { poly_projections.extend(assoc_bindings.iter().filter_map(|binding| { // specify type to assert that error was already reported in Err case: let predicate: Result<_, ErrorReported> = - self.ast_type_binding_to_poly_projection_predicate(poly_trait_ref, binding); + self.ast_type_binding_to_poly_projection_predicate(trait_ref.ref_id, poly_trait_ref, + binding); predicate.ok() // ok to ignore Err() because ErrorReported (see above) })); @@ -442,6 +443,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn ast_type_binding_to_poly_projection_predicate( &self, + ref_id: ast::NodeId, trait_ref: ty::PolyTraitRef<'tcx>, binding: &ConvertedBinding<'tcx>) -> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported> @@ -494,30 +496,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .emit(); } - // Simple case: X is defined in the current trait. - if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) { - return Ok(trait_ref.map_bound(|trait_ref| { - ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy::from_ref_and_name( - tcx, - trait_ref, - binding.item_name, - ), - ty: binding.ty, - } - })); + let candidate = if self.trait_defines_associated_type_named(trait_ref.def_id(), + binding.item_name) { + // Simple case: X is defined in the current trait. + Ok(trait_ref) + } else { + // Otherwise, we have to walk through the supertraits to find + // those that do. + let candidates = traits::supertraits(tcx, trait_ref).filter(|r| { + self.trait_defines_associated_type_named(r.def_id(), binding.item_name) + }); + self.one_bound_for_assoc_type(candidates, &trait_ref.to_string(), + binding.item_name, binding.span) + }?; + + let (assoc_ident, def_scope) = tcx.adjust(binding.item_name, candidate.def_id(), ref_id); + let assoc_ty = tcx.associated_items(candidate.def_id()).find(|i| { + i.kind == ty::AssociatedKind::Type && i.name.to_ident() == assoc_ident + }).expect("missing associated type"); + + if !assoc_ty.vis.is_accessible_from(def_scope, tcx) { + let msg = format!("associated type `{}` is private", binding.item_name); + tcx.sess.span_err(binding.span, &msg); } - - // Otherwise, we have to walk through the supertraits to find - // those that do. - let candidates = - traits::supertraits(tcx, trait_ref.clone()) - .filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name)); - - let candidate = self.one_bound_for_assoc_type(candidates, - &trait_ref.to_string(), - binding.item_name, - binding.span)?; + tcx.check_stability(assoc_ty.def_id, ref_id, binding.span); Ok(candidate.map_bound(|trait_ref| { ty::ProjectionPredicate { diff --git a/src/test/compile-fail/lint-stability-deprecated.rs b/src/test/compile-fail/lint-stability-deprecated.rs index df5c3dddcde..f2defc1d421 100644 --- a/src/test/compile-fail/lint-stability-deprecated.rs +++ b/src/test/compile-fail/lint-stability-deprecated.rs @@ -108,6 +108,11 @@ mod cross_crate { struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text + type A = TraitWithAssociatedTypes< + TypeUnstable = u8, + TypeDeprecated = u16, + //~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated' + >; let _ = DeprecatedStruct { //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct' i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct::i' diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index 1ece7a0b8e3..49a52204295 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -96,6 +96,10 @@ mod cross_crate { struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); //~^ ERROR use of unstable library feature struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); + type A = TraitWithAssociatedTypes< + TypeUnstable = u8, //~ ERROR use of unstable library feature + TypeDeprecated = u16, + >; let _ = DeprecatedStruct { i: 0 diff --git a/src/test/compile-fail/trait-item-privacy.rs b/src/test/compile-fail/trait-item-privacy.rs index b8d83e5adf2..be0f7dd4e1c 100644 --- a/src/test/compile-fail/trait-item-privacy.rs +++ b/src/test/compile-fail/trait-item-privacy.rs @@ -131,6 +131,16 @@ fn check_assoc_ty<T: assoc_ty::C>() { let _: T::A; //~ ERROR associated type `A` is private let _: T::B; // OK let _: T::C; // OK + + // Associated types, bindings + let _: assoc_ty::B< + B = u8, // OK + >; + let _: C< + A = u8, //~ ERROR associated type `A` is private + B = u8, // OK + C = u8, // OK + >; } fn main() {} |
