diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 26f663b1c9d..2c5c664566a 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -117,6 +117,13 @@ declare_lint! { Allow, "detects trivial casts of numeric types which could be removed" } + +declare_lint! { + pub PRIVATE_IN_PUBLIC, + Warn, + "detect private items in public interfaces not caught by the old implementation" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -141,6 +148,7 @@ impl LintPass for HardwiredLints { FAT_PTR_TRANSMUTES, TRIVIAL_CASTS, TRIVIAL_NUMERIC_CASTS, + PRIVATE_IN_PUBLIC, CONST_ERR ) } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 69fd569c8d4..1d0c616c3b7 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -146,6 +146,9 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE, UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES); + add_lint_group!(sess, "future_incompatible", + PRIVATE_IN_PUBLIC); + // We have one lint pass defined specially store.register_late_pass(sess, false, box lint::GatherNodeLevels); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index b65c0c19497..275f328bfe0 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -38,6 +38,7 @@ use std::mem::replace; use rustc_front::hir; use rustc_front::intravisit::{self, Visitor}; +use rustc::lint; use rustc::middle::def; use rustc::middle::def_id::DefId; use rustc::middle::privacy::{AccessLevel, AccessLevels}; @@ -1488,9 +1489,17 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, } if item.vis != hir::Public { if !self.is_quiet { - let is_warning = !self.old_error_set.contains(&ty.id); - span_err_or_warn!(is_warning, self.tcx.sess, ty.span, E0446, - "private type in public interface"); + if self.old_error_set.contains(&ty.id) { + span_err!(self.tcx.sess, ty.span, E0446, + "private type in public interface"); + } else { + self.tcx.sess.add_lint ( + lint::builtin::PRIVATE_IN_PUBLIC, + node_id, + ty.span, + "private type in public interface".to_string() + ); + } } self.is_public = false; } @@ -1515,9 +1524,15 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, if let Some(ast_map::NodeItem(ref item)) = self.tcx.map.find(node_id) { if item.vis != hir::Public { if !self.is_quiet { - let is_warning = !self.old_error_set.contains(&trait_ref.ref_id); - span_err_or_warn!(is_warning, self.tcx.sess, trait_ref.path.span, E0445, - "private trait in public interface"); + if self.old_error_set.contains(&trait_ref.ref_id) { + span_err!(self.tcx.sess, trait_ref.path.span, E0445, + "private trait in public interface"); + } else { + self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC, + node_id, + trait_ref.path.span, + "private trait in public interface".to_string()); + } } self.is_public = false; } diff --git a/src/test/compile-fail/issue-28450-1.rs b/src/test/compile-fail/issue-28450-1.rs new file mode 100644 index 00000000000..7239e6ddc37 --- /dev/null +++ b/src/test/compile-fail/issue-28450-1.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks for private types in public interfaces + +type Foo = u8; +pub fn foo(f: Foo) {} //~ ERROR private type in public interface + +fn main() {} diff --git a/src/test/compile-fail/issue-28450.rs b/src/test/compile-fail/issue-28450.rs index 2e073051858..65c5978103a 100644 --- a/src/test/compile-fail/issue-28450.rs +++ b/src/test/compile-fail/issue-28450.rs @@ -10,6 +10,8 @@ // Checks for private types in public interfaces +#![feature(rustc_attrs)] + struct Priv; pub use self::private::public; @@ -28,9 +30,6 @@ impl Pointer for *const T { type Pointee = T; } pub type __CFArrayRevealed = ::Pointee; //~^ WARN private type in public interface -type Foo = u8; -pub fn foo(f: Foo) {} //~ ERROR private type in public interface - pub trait Exporter { type Output; } @@ -49,6 +48,7 @@ pub fn block() -> ::Output { Inner } -fn main() { +#[rustc_error] +fn main() { //~ ERROR compilation successful block().poke(); } diff --git a/src/test/compile-fail/lint-private-in-public.rs b/src/test/compile-fail/lint-private-in-public.rs new file mode 100644 index 00000000000..f9b049c5d33 --- /dev/null +++ b/src/test/compile-fail/lint-private-in-public.rs @@ -0,0 +1,33 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +mod m1 { + #![deny(private_in_public)] + + pub struct Pub; + struct Priv; + + impl Pub { + pub fn f() -> Priv {} //~ ERROR private type in public interface + } +} + +mod m2 { + #![deny(future_incompatible)] + + pub struct Pub; + struct Priv; + + impl Pub { + pub fn f() -> Priv {} //~ ERROR private type in public interface + } +} + +fn main() {} diff --git a/src/test/compile-fail/lint-visible-private-types-1.rs b/src/test/compile-fail/lint-visible-private-types-1.rs new file mode 100644 index 00000000000..69c4eca1a0a --- /dev/null +++ b/src/test/compile-fail/lint-visible-private-types-1.rs @@ -0,0 +1,41 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(dead_code)] + +use std::marker; + +struct Private(marker::PhantomData); +pub struct Public(marker::PhantomData); + +pub trait PubTrait { + type Output; +} + +type PrivAlias = Public; + +trait PrivTrait2 { + type Alias; +} +impl PrivTrait2 for Private { + type Alias = Public; +} + +impl PubTrait for PrivAlias { + type Output = Private; //~ WARN private type in public interface +} + +impl PubTrait for as PrivTrait2>::Alias { + type Output = Private; //~ WARN private type in public interface +} + +#[rustc_error] +fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/lint-visible-private-types.rs b/src/test/compile-fail/lint-visible-private-types.rs index 154acbcfd60..1fd61605557 100644 --- a/src/test/compile-fail/lint-visible-private-types.rs +++ b/src/test/compile-fail/lint-visible-private-types.rs @@ -75,8 +75,8 @@ pub trait PubTrait { } impl PubTrait for Public { - fn bar(&self) -> Private { panic!() } //~ WARN private type in public interface - fn baz() -> Private { panic!() } //~ WARN private type in public interface + fn bar(&self) -> Private { panic!() } // Warns in lint checking phase + fn baz() -> Private { panic!() } // Warns in lint checking phase } impl PubTrait for Public> { fn bar(&self) -> Private { panic!() } @@ -121,22 +121,3 @@ impl>> //~ ERROR private type in public interface ParamTrait for Public { fn foo() -> T { panic!() } } - -type PrivAlias = Public; - -trait PrivTrait2 { - type Alias; -} -impl PrivTrait2 for Private { - type Alias = Public; -} - -impl PubTrait for PrivAlias { - fn bar(&self) -> Private { panic!() } //~ WARN private type in public interface - fn baz() -> Private { panic!() } //~ WARN private type in public interface -} - -impl PubTrait for as PrivTrait2>::Alias { - fn bar(&self) -> Private { panic!() } //~ WARN private type in public interface - fn baz() -> Private { panic!() } //~ WARN private type in public interface -}