Check associated type bindings for privacy and stability
This commit is contained in:
parent
8dcd26a6df
commit
53779ed5ec
@ -370,7 +370,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||||||
poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
|
poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
|
||||||
// specify type to assert that error was already reported in Err case:
|
// specify type to assert that error was already reported in Err case:
|
||||||
let predicate: Result<_, ErrorReported> =
|
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)
|
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(
|
fn ast_type_binding_to_poly_projection_predicate(
|
||||||
&self,
|
&self,
|
||||||
|
ref_id: ast::NodeId,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
binding: &ConvertedBinding<'tcx>)
|
binding: &ConvertedBinding<'tcx>)
|
||||||
-> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
|
-> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
|
||||||
@ -494,30 +496,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simple case: X is defined in the current trait.
|
let candidate = if self.trait_defines_associated_type_named(trait_ref.def_id(),
|
||||||
if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
|
binding.item_name) {
|
||||||
return Ok(trait_ref.map_bound(|trait_ref| {
|
// Simple case: X is defined in the current trait.
|
||||||
ty::ProjectionPredicate {
|
Ok(trait_ref)
|
||||||
projection_ty: ty::ProjectionTy::from_ref_and_name(
|
} else {
|
||||||
tcx,
|
// Otherwise, we have to walk through the supertraits to find
|
||||||
trait_ref,
|
// those that do.
|
||||||
binding.item_name,
|
let candidates = traits::supertraits(tcx, trait_ref).filter(|r| {
|
||||||
),
|
self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
|
||||||
ty: binding.ty,
|
});
|
||||||
}
|
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);
|
||||||
}
|
}
|
||||||
|
tcx.check_stability(assoc_ty.def_id, ref_id, binding.span);
|
||||||
// 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)?;
|
|
||||||
|
|
||||||
Ok(candidate.map_bound(|trait_ref| {
|
Ok(candidate.map_bound(|trait_ref| {
|
||||||
ty::ProjectionPredicate {
|
ty::ProjectionPredicate {
|
||||||
|
@ -108,6 +108,11 @@ mod cross_crate {
|
|||||||
struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
|
struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
|
||||||
struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
|
struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
|
||||||
//~^ WARN use of deprecated item 'lint_stability::TraitWithAssociatedTypes::TypeDeprecated': text
|
//~^ 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'
|
let _ = DeprecatedStruct { //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct'
|
||||||
i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct::i'
|
i: 0 //~ WARN use of deprecated item 'lint_stability::DeprecatedStruct::i'
|
||||||
|
@ -96,6 +96,10 @@ mod cross_crate {
|
|||||||
struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
|
struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
|
||||||
//~^ ERROR use of unstable library feature
|
//~^ ERROR use of unstable library feature
|
||||||
struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
|
struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
|
||||||
|
type A = TraitWithAssociatedTypes<
|
||||||
|
TypeUnstable = u8, //~ ERROR use of unstable library feature
|
||||||
|
TypeDeprecated = u16,
|
||||||
|
>;
|
||||||
|
|
||||||
let _ = DeprecatedStruct {
|
let _ = DeprecatedStruct {
|
||||||
i: 0
|
i: 0
|
||||||
|
@ -131,6 +131,16 @@ fn check_assoc_ty<T: assoc_ty::C>() {
|
|||||||
let _: T::A; //~ ERROR associated type `A` is private
|
let _: T::A; //~ ERROR associated type `A` is private
|
||||||
let _: T::B; // OK
|
let _: T::B; // OK
|
||||||
let _: T::C; // 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() {}
|
fn main() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user