about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-11-18 18:38:56 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-12-21 03:17:19 +0300
commit53779ed5ec8077fd11d5ea9c3e0e1c404ee92c36 (patch)
tree0f1d96b4b10c57ae64bd20d37d4e48e80c377b13
parent8dcd26a6df4bb932cd94404a6c941d84a3d1d851 (diff)
downloadrust-53779ed5ec8077fd11d5ea9c3e0e1c404ee92c36.tar.gz
rust-53779ed5ec8077fd11d5ea9c3e0e1c404ee92c36.zip
Check associated type bindings for privacy and stability
-rw-r--r--src/librustc_typeck/astconv.rs50
-rw-r--r--src/test/compile-fail/lint-stability-deprecated.rs5
-rw-r--r--src/test/compile-fail/lint-stability.rs4
-rw-r--r--src/test/compile-fail/trait-item-privacy.rs10
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() {}