about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-12-27 21:42:25 +0100
committerGitHub <noreply@github.com>2021-12-27 21:42:25 +0100
commitb57a6b38c5b3ac932cf5bc70558fc2b4d0792e91 (patch)
tree7e208c328600531e1611ebb71bbb54da5754d034
parentf8abed9ed48bace6be0087bcd44ed534e239b8d8 (diff)
parentebef8a8ceec0173b98fcc842bb319788e7d38562 (diff)
downloadrust-b57a6b38c5b3ac932cf5bc70558fc2b4d0792e91.tar.gz
rust-b57a6b38c5b3ac932cf5bc70558fc2b4d0792e91.zip
Rollup merge of #90586 - jswrenn:relax-privacy-lints, r=petrochenkov
Relax priv-in-pub lint on generic bounds and where clauses of trait impls.

The priv-in-pub lint is a legacy mechanism of the compiler, supplanted by a reachability-based [type privacy](https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md) analysis. This PR does **not** relax type privacy; it only relaxes the lint (as proposed by the type privacy RFC) in the case of trait impls.

## Current Behavior
On public trait impls, it's currently an **error** to have a `where` bound constraining a private type with a trait:
```rust
pub trait Trait {}
pub struct Type {}

struct Priv {}
impl Trait for Priv {}

impl Trait for Type
where
    Priv: Trait // ERROR
{}
```

...and it's a **warning** to have have a public type constrained by a private trait:
```rust
pub trait Trait {}
pub struct Type {}

pub struct Pub {}
trait Priv {}
impl Priv for Pub {}

impl Trait for Type
where
    Pub: Priv // WARNING
{}
```

This lint applies to `where` clauses in other contexts, too; e.g. on free functions:
```rust
struct Priv<T>(T);
pub trait Pub {}
impl<T: Pub> Pub for Priv<T> {}

pub fn function<T>()
where
    Priv<T>: Pub // WARNING
{}
```

**These constraints could be relaxed without issue.**

## New Behavior
This lint is relaxed for `where` clauses on trait impls, such that it's okay to have a `where` bound constraining a private type with a trait:
```rust
pub trait Trait {}
pub struct Type {}

struct Priv {}
impl Trait for Priv {}

impl Trait for Type
where
    Priv: Trait // OK
{}
```

...and it's okay to have a public type constrained by a private trait:
```rust
pub trait Trait {}
pub struct Type {}

pub struct Pub {}
trait Priv {}
impl Priv for Pub {}

impl Trait for Type
where
    Pub: Priv // OK
{}
```

## Rationale
While the priv-in-pub lint is not essential for soundness, it *can* help programmers avoid pitfalls that would make their libraries difficult to use by others. For instance, such a lint *is* useful for free functions; e.g. if a downstream crate tries to call the `function` in the previous snippet in a generic context:
```rust
fn callsite<T>()
where
    Priv<T>: Pub // ERROR: omitting this bound is a compile error, but including it is too
{
    function::<T>()
}
```
...it cannot do so without repeating `function`'s `where` bound, which we cannot do because `Priv` is out-of-scope. A lint for this case is arguably helpful.

However, this same reasoning **doesn't** hold for trait impls. To call an unconstrained method on a public trait impl with private bounds, you don't need to forward those private bounds, you can forward the public trait:
```rust
mod upstream {
    pub trait Trait {
        fn method(&self) {}
    }
    pub struct Type<T>(T);

    pub struct Pub<T>(T);
    trait Priv {}
    impl<T: Priv> Priv for Pub<T> {}

    impl<T> Trait for Type<T>
    where
        Pub<T>: Priv // WARNING
    {}
}

mod downstream {
    use super::upstream::*;

    fn function<T>(value: Type<T>)
    where
        Type<T>: Trait // <- no private deets!
    {
        value.method();
    }
}
```

**This PR only eliminates the lint on trait impls.** It leaves it intact for all other contexts, including trait definitions, inherent impls, and function definitions. It doesn't need to exist in those cases either, but I figured I'd first target a case where it's mostly pointless.

## Other Notes
- See discussion [on zulip](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/relax.20priv-in-pub.20lint.20for.20trait.20impl.20.60where.60.20bounds/near/222458397).
- This PR effectively reverts #79291.
-rw-r--r--compiler/rustc_privacy/src/lib.rs6
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs7
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr35
-rw-r--r--src/test/ui/privacy/private-in-public-warn.rs7
-rw-r--r--src/test/ui/privacy/private-in-public-warn.stderr56
-rw-r--r--src/test/ui/privacy/where-priv-type.rs90
-rw-r--r--src/test/ui/privacy/where-priv-type.stderr82
-rw-r--r--src/test/ui/privacy/where-pub-type-impls-priv-trait.rs56
-rw-r--r--src/test/ui/privacy/where-pub-type-impls-priv-trait.stderr68
9 files changed, 325 insertions, 82 deletions
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 10f6f6b1a9f..183a5a205ec 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -2064,7 +2064,11 @@ impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> {
             // Subitems of trait impls have inherited publicity.
             hir::ItemKind::Impl(ref impl_) => {
                 let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default());
-                self.check(item.def_id, impl_vis).generics().predicates();
+                // check that private components do not appear in the generics or predicates of inherent impls
+                // this check is intentionally NOT performed for impls of traits, per #90586
+                if impl_.of_trait.is_none() {
+                    self.check(item.def_id, impl_vis).generics().predicates();
+                }
                 for impl_item_ref in impl_.items {
                     let impl_item_vis = if impl_.of_trait.is_none() {
                         min(tcx.visibility(impl_item_ref.id.def_id), impl_vis, tcx)
diff --git a/src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs
index 80d0662f1f4..8023b998a40 100644
--- a/src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs
@@ -9,12 +9,7 @@ pub trait Trait {
     fn assoc_fn() -> Self::AssocTy;
 }
 
-impl<const U: u8> Trait for Const<U>
-//~^ WARN private type
-//~| WARN this was previously
-//~| WARN private type
-//~| WARN this was previously
-
+impl<const U: u8> Trait for Const<U> // OK, trait impl predicates
 where
     Const<{ my_const_fn(U) }>: ,
 {
diff --git a/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr
index 842c22c5c67..c6b0ce93145 100644
--- a/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr
@@ -1,36 +1,5 @@
-warning: private type `fn(u8) -> u8 {my_const_fn}` in public interface (error E0446)
-  --> $DIR/eval-privacy.rs:12:1
-   |
-LL | / impl<const U: u8> Trait for Const<U>
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     }
-LL | | }
-   | |_^
-   |
-   = note: `#[warn(private_in_public)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
-
-warning: private type `fn(u8) -> u8 {my_const_fn}` in public interface (error E0446)
-  --> $DIR/eval-privacy.rs:12:1
-   |
-LL | / impl<const U: u8> Trait for Const<U>
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     }
-LL | | }
-   | |_^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
-
 error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
-  --> $DIR/eval-privacy.rs:21:5
+  --> $DIR/eval-privacy.rs:16:5
    |
 LL |     type AssocTy = Const<{ my_const_fn(U) }>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
@@ -38,6 +7,6 @@ LL |     type AssocTy = Const<{ my_const_fn(U) }>;
 LL | const fn my_const_fn(val: u8) -> u8 {
    | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
 
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs
index 09afa04501e..0fa1de975b0 100644
--- a/src/test/ui/privacy/private-in-public-warn.rs
+++ b/src/test/ui/privacy/private-in-public-warn.rs
@@ -63,8 +63,7 @@ mod traits {
     }
     impl<T: PrivTr> Pub<T> {} //~ ERROR private trait `traits::PrivTr` in public interface
         //~^ WARNING hard error
-    impl<T: PrivTr> PubTr for Pub<T> {} //~ ERROR private trait `traits::PrivTr` in public interface
-        //~^ WARNING hard error
+    impl<T: PrivTr> PubTr for Pub<T> {} // OK, trait impl predicates
 }
 
 mod traits_where {
@@ -87,9 +86,7 @@ mod traits_where {
     impl<T> Pub<T> where T: PrivTr {}
         //~^ ERROR private trait `traits_where::PrivTr` in public interface
         //~| WARNING hard error
-    impl<T> PubTr for Pub<T> where T: PrivTr {}
-        //~^ ERROR private trait `traits_where::PrivTr` in public interface
-        //~| WARNING hard error
+    impl<T> PubTr for Pub<T> where T: PrivTr {} // OK, trait impl predicates
 }
 
 mod generics {
diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr
index f51cfc836a8..a72d8247792 100644
--- a/src/test/ui/privacy/private-in-public-warn.stderr
+++ b/src/test/ui/privacy/private-in-public-warn.stderr
@@ -156,17 +156,8 @@ LL |     impl<T: PrivTr> Pub<T> {}
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
-error: private trait `traits::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:66:5
-   |
-LL |     impl<T: PrivTr> PubTr for Pub<T> {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
-
 error: private trait `traits_where::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:75:5
+  --> $DIR/private-in-public-warn.rs:74:5
    |
 LL |     pub type Alias<T> where T: PrivTr = T;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -175,7 +166,7 @@ LL |     pub type Alias<T> where T: PrivTr = T;
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private trait `traits_where::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:79:5
+  --> $DIR/private-in-public-warn.rs:78:5
    |
 LL |     pub trait Tr2<T> where T: PrivTr {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -184,7 +175,7 @@ LL |     pub trait Tr2<T> where T: PrivTr {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private trait `traits_where::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:83:9
+  --> $DIR/private-in-public-warn.rs:82:9
    |
 LL |         fn f<T>(arg: T) where T: PrivTr {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -193,7 +184,7 @@ LL |         fn f<T>(arg: T) where T: PrivTr {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private trait `traits_where::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:87:5
+  --> $DIR/private-in-public-warn.rs:86:5
    |
 LL |     impl<T> Pub<T> where T: PrivTr {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -201,17 +192,8 @@ LL |     impl<T> Pub<T> where T: PrivTr {}
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
-error: private trait `traits_where::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:90:5
-   |
-LL |     impl<T> PubTr for Pub<T> where T: PrivTr {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
-
 error: private trait `generics::PrivTr<generics::Pub>` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:101:5
+  --> $DIR/private-in-public-warn.rs:98:5
    |
 LL |     pub trait Tr1: PrivTr<Pub> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -220,7 +202,7 @@ LL |     pub trait Tr1: PrivTr<Pub> {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private type `generics::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-warn.rs:104:5
+  --> $DIR/private-in-public-warn.rs:101:5
    |
 LL |     pub trait Tr2: PubTr<Priv> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -229,7 +211,7 @@ LL |     pub trait Tr2: PubTr<Priv> {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private type `generics::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-warn.rs:106:5
+  --> $DIR/private-in-public-warn.rs:103:5
    |
 LL |     pub trait Tr3: PubTr<[Priv; 1]> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -238,7 +220,7 @@ LL |     pub trait Tr3: PubTr<[Priv; 1]> {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private type `generics::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-warn.rs:108:5
+  --> $DIR/private-in-public-warn.rs:105:5
    |
 LL |     pub trait Tr4: PubTr<Pub<Priv>> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -247,7 +229,7 @@ LL |     pub trait Tr4: PubTr<Pub<Priv>> {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error[E0446]: private type `impls::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:135:9
+  --> $DIR/private-in-public-warn.rs:132:9
    |
 LL |     struct Priv;
    |     ------------ `impls::Priv` declared as private
@@ -256,7 +238,7 @@ LL |         type Alias = Priv;
    |         ^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error: private type `aliases_pub::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-warn.rs:206:9
+  --> $DIR/private-in-public-warn.rs:203:9
    |
 LL |         pub fn f(arg: Priv) {}
    |         ^^^^^^^^^^^^^^^^^^^
@@ -265,7 +247,7 @@ LL |         pub fn f(arg: Priv) {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:210:9
+  --> $DIR/private-in-public-warn.rs:207:9
    |
 LL |     struct Priv;
    |     ------------ `aliases_pub::Priv` declared as private
@@ -274,7 +256,7 @@ LL |         type Check = Priv;
    |         ^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:213:9
+  --> $DIR/private-in-public-warn.rs:210:9
    |
 LL |     struct Priv;
    |     ------------ `aliases_pub::Priv` declared as private
@@ -283,7 +265,7 @@ LL |         type Check = Priv;
    |         ^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:216:9
+  --> $DIR/private-in-public-warn.rs:213:9
    |
 LL |     struct Priv;
    |     ------------ `aliases_pub::Priv` declared as private
@@ -292,7 +274,7 @@ LL |         type Check = Priv;
    |         ^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:219:9
+  --> $DIR/private-in-public-warn.rs:216:9
    |
 LL |     struct Priv;
    |     ------------ `aliases_pub::Priv` declared as private
@@ -301,7 +283,7 @@ LL |         type Check = Priv;
    |         ^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error: private trait `PrivTr1` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:249:5
+  --> $DIR/private-in-public-warn.rs:246:5
    |
 LL |     pub trait Tr1: PrivUseAliasTr {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -310,7 +292,7 @@ LL |     pub trait Tr1: PrivUseAliasTr {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private trait `PrivTr1<Priv2>` in public interface (error E0445)
-  --> $DIR/private-in-public-warn.rs:252:5
+  --> $DIR/private-in-public-warn.rs:249:5
    |
 LL |     pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -319,7 +301,7 @@ LL |     pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error: private type `Priv2` in public interface (error E0446)
-  --> $DIR/private-in-public-warn.rs:252:5
+  --> $DIR/private-in-public-warn.rs:249:5
    |
 LL |     pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -341,7 +323,7 @@ LL +     pub type Alias<T> = T;
    | 
 
 warning: where clauses are not enforced in type aliases
-  --> $DIR/private-in-public-warn.rs:75:29
+  --> $DIR/private-in-public-warn.rs:74:29
    |
 LL |     pub type Alias<T> where T: PrivTr = T;
    |                             ^^^^^^^^^
@@ -352,6 +334,6 @@ LL -     pub type Alias<T> where T: PrivTr = T;
 LL +     pub type Alias<T>  = T;
    | 
 
-error: aborting due to 36 previous errors; 2 warnings emitted
+error: aborting due to 34 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/privacy/where-priv-type.rs b/src/test/ui/privacy/where-priv-type.rs
new file mode 100644
index 00000000000..66ee9c4bbd8
--- /dev/null
+++ b/src/test/ui/privacy/where-priv-type.rs
@@ -0,0 +1,90 @@
+// priv-in-pub lint tests where the private type appears in the
+// `where` clause of a public item
+
+#![crate_type = "lib"]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+
+struct PrivTy;
+trait PrivTr {}
+pub struct PubTy;
+pub struct PubTyGeneric<T>(T);
+pub trait PubTr {}
+impl PubTr for PrivTy {}
+pub trait PubTrWithAssocTy { type AssocTy; }
+impl PubTrWithAssocTy for PrivTy { type AssocTy = PrivTy; }
+
+
+pub struct S
+//~^ WARNING private type `PrivTy` in public interface
+//~| WARNING hard error
+where
+    PrivTy:
+{}
+
+
+pub enum E
+//~^ WARNING private type `PrivTy` in public interface
+//~| WARNING hard error
+where
+    PrivTy:
+{}
+
+
+pub fn f()
+//~^ WARNING private type `PrivTy` in public interface
+//~| WARNING hard error
+where
+    PrivTy:
+{}
+
+
+impl S
+//~^ ERROR private type `PrivTy` in public interface
+where
+    PrivTy:
+{
+    pub fn f()
+    //~^ WARNING private type `PrivTy` in public interface
+    //~| WARNING hard error
+    where
+        PrivTy:
+    {}
+}
+
+
+impl PubTr for PubTy
+where
+    PrivTy:
+{}
+
+
+impl<T> PubTr for PubTyGeneric<T>
+where
+    T: PubTrWithAssocTy<AssocTy=PrivTy>
+{}
+
+
+pub struct Const<const U: u8>;
+
+pub trait Trait {
+    type AssocTy;
+    fn assoc_fn() -> Self::AssocTy;
+}
+
+impl<const U: u8> Trait for Const<U>
+where
+    Const<{ my_const_fn(U) }>: ,
+{
+    type AssocTy = Const<{ my_const_fn(U) }>;
+    //~^ ERROR private type
+    fn assoc_fn() -> Self::AssocTy {
+        Const
+    }
+}
+
+const fn my_const_fn(val: u8) -> u8 {
+    // body of this function doesn't matter
+    val
+}
diff --git a/src/test/ui/privacy/where-priv-type.stderr b/src/test/ui/privacy/where-priv-type.stderr
new file mode 100644
index 00000000000..378c14810d9
--- /dev/null
+++ b/src/test/ui/privacy/where-priv-type.stderr
@@ -0,0 +1,82 @@
+warning: private type `PrivTy` in public interface (error E0446)
+  --> $DIR/where-priv-type.rs:19:1
+   |
+LL | / pub struct S
+LL | |
+LL | |
+LL | | where
+LL | |     PrivTy:
+LL | | {}
+   | |__^
+   |
+   = note: `#[warn(private_in_public)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+warning: private type `PrivTy` in public interface (error E0446)
+  --> $DIR/where-priv-type.rs:27:1
+   |
+LL | / pub enum E
+LL | |
+LL | |
+LL | | where
+LL | |     PrivTy:
+LL | | {}
+   | |__^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+warning: private type `PrivTy` in public interface (error E0446)
+  --> $DIR/where-priv-type.rs:35:1
+   |
+LL | / pub fn f()
+LL | |
+LL | |
+LL | | where
+LL | |     PrivTy:
+   | |___________^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `PrivTy` in public interface
+  --> $DIR/where-priv-type.rs:43:1
+   |
+LL |   struct PrivTy;
+   |   -------------- `PrivTy` declared as private
+...
+LL | / impl S
+LL | |
+LL | | where
+LL | |     PrivTy:
+...  |
+LL | |     {}
+LL | | }
+   | |_^ can't leak private type
+
+warning: private type `PrivTy` in public interface (error E0446)
+  --> $DIR/where-priv-type.rs:48:5
+   |
+LL | /     pub fn f()
+LL | |
+LL | |
+LL | |     where
+LL | |         PrivTy:
+   | |_______________^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
+  --> $DIR/where-priv-type.rs:80:5
+   |
+LL |     type AssocTy = Const<{ my_const_fn(U) }>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+...
+LL | const fn my_const_fn(val: u8) -> u8 {
+   | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
+
+error: aborting due to 2 previous errors; 4 warnings emitted
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/privacy/where-pub-type-impls-priv-trait.rs b/src/test/ui/privacy/where-pub-type-impls-priv-trait.rs
new file mode 100644
index 00000000000..87c211df169
--- /dev/null
+++ b/src/test/ui/privacy/where-pub-type-impls-priv-trait.rs
@@ -0,0 +1,56 @@
+// priv-in-pub lint tests where the private trait bounds a public type
+
+#![crate_type = "lib"]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+
+struct PrivTy;
+trait PrivTr {}
+pub struct PubTy;
+pub struct PubTyGeneric<T>(T);
+pub trait PubTr {}
+impl PubTr for PrivTy {}
+impl PrivTr for PubTy {}
+pub trait PubTrWithAssocTy { type AssocTy; }
+impl PubTrWithAssocTy for PrivTy { type AssocTy = PrivTy; }
+
+
+pub struct S
+//~^ ERROR private trait `PrivTr` in public interface
+where
+    PubTy: PrivTr
+{}
+
+
+pub enum E
+//~^ ERROR private trait `PrivTr` in public interface
+where
+    PubTy: PrivTr
+{}
+
+
+pub fn f()
+//~^ ERROR private trait `PrivTr` in public interface
+where
+    PubTy: PrivTr
+{}
+
+
+impl S
+//~^ ERROR private trait `PrivTr` in public interface
+where
+    PubTy: PrivTr
+{
+    pub fn f()
+    //~^ ERROR private trait `PrivTr` in public interface
+    where
+        PubTy: PrivTr
+    {}
+}
+
+
+impl PubTr for PubTy
+where
+    PubTy: PrivTr
+{}
diff --git a/src/test/ui/privacy/where-pub-type-impls-priv-trait.stderr b/src/test/ui/privacy/where-pub-type-impls-priv-trait.stderr
new file mode 100644
index 00000000000..9ce7b9a139f
--- /dev/null
+++ b/src/test/ui/privacy/where-pub-type-impls-priv-trait.stderr
@@ -0,0 +1,68 @@
+error[E0445]: private trait `PrivTr` in public interface
+  --> $DIR/where-pub-type-impls-priv-trait.rs:19:1
+   |
+LL |   trait PrivTr {}
+   |   ------------ `PrivTr` declared as private
+...
+LL | / pub struct S
+LL | |
+LL | | where
+LL | |     PubTy: PrivTr
+LL | | {}
+   | |__^ can't leak private trait
+
+error[E0445]: private trait `PrivTr` in public interface
+  --> $DIR/where-pub-type-impls-priv-trait.rs:26:1
+   |
+LL |   trait PrivTr {}
+   |   ------------ `PrivTr` declared as private
+...
+LL | / pub enum E
+LL | |
+LL | | where
+LL | |     PubTy: PrivTr
+LL | | {}
+   | |__^ can't leak private trait
+
+error[E0445]: private trait `PrivTr` in public interface
+  --> $DIR/where-pub-type-impls-priv-trait.rs:33:1
+   |
+LL |   trait PrivTr {}
+   |   ------------ `PrivTr` declared as private
+...
+LL | / pub fn f()
+LL | |
+LL | | where
+LL | |     PubTy: PrivTr
+   | |_________________^ can't leak private trait
+
+error[E0445]: private trait `PrivTr` in public interface
+  --> $DIR/where-pub-type-impls-priv-trait.rs:40:1
+   |
+LL |   trait PrivTr {}
+   |   ------------ `PrivTr` declared as private
+...
+LL | / impl S
+LL | |
+LL | | where
+LL | |     PubTy: PrivTr
+...  |
+LL | |     {}
+LL | | }
+   | |_^ can't leak private trait
+
+error[E0445]: private trait `PrivTr` in public interface
+  --> $DIR/where-pub-type-impls-priv-trait.rs:45:5
+   |
+LL |   trait PrivTr {}
+   |   ------------ `PrivTr` declared as private
+...
+LL | /     pub fn f()
+LL | |
+LL | |     where
+LL | |         PubTy: PrivTr
+   | |_____________________^ can't leak private trait
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0445`.