forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#90586 - jswrenn:relax-privacy-lints, r=petr…
…ochenkov 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 rust-lang#79291.
- Loading branch information
Showing
9 changed files
with
325 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 2 additions & 33 deletions
35
src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,12 @@ | ||
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 | ||
... | ||
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`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
Oops, something went wrong.