fix for Self not respecting tuple Ctor privacy

This fixes #111220 by checking the privacy of tuple constructors using `Self`, so the following code now errors

```rust
mod my {
    pub struct Foo(&'static str);
}

impl AsRef<str> for my::Foo {
    fn as_ref(&self) -> &str {
        let Self(s) = self; // previously compiled, now errors correctly
        s
    }
}
```
This commit is contained in:
Deadbeef 2023-05-05 10:52:02 +00:00
parent c86212f9bc
commit be44860ab9
7 changed files with 126 additions and 0 deletions

View File

@ -25,6 +25,8 @@ hir_typeck_const_select_must_be_fn = this argument must be a function item
hir_typeck_convert_to_str = try converting the passed type into a `&str`
hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
hir_typeck_expected_default_return_type = expected `()` because of default return type
hir_typeck_expected_return_type = expected `{$expected}` because of return type

View File

@ -319,3 +319,11 @@ pub struct CandidateTraitNote {
pub item_name: Ident,
pub action_or_ty: String,
}
#[derive(Diagnostic)]
#[diag(hir_typeck_ctor_is_private, code = "E0603")]
pub struct CtorIsPrivate {
#[primary_span]
pub span: Span,
pub def: String,
}

View File

@ -1,4 +1,5 @@
use crate::callee::{self, DeferredCallResolution};
use crate::errors::CtorIsPrivate;
use crate::method::{self, MethodCallee, SelfSource};
use crate::rvalue_scopes;
use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
@ -1207,6 +1208,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match ty.normalized.ty_adt_def() {
Some(adt_def) if adt_def.has_ctor() => {
let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap();
// Check the visibility of the ctor.
let vis = tcx.visibility(ctor_def_id);
if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) {
tcx.sess
.emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) });
}
let new_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
let user_substs = Self::user_substs_for_adt(ty);
user_self_ty = user_substs.user_self_ty;

View File

@ -0,0 +1,33 @@
mod b {
pub struct A(u32);
}
trait Id {
type Assoc;
}
impl Id for b::A {
type Assoc = b::A;
}
impl Id for u32 {
type Assoc = u32;
}
trait Trait<T> {
fn method(&self)
where
T: Id<Assoc = b::A>;
}
impl<T: Id> Trait<T> for <T as Id>::Assoc {
fn method(&self)
where
T: Id<Assoc = b::A>,
{
let Self(a) = self;
//~^ ERROR: tuple struct constructor `A` is private
println!("{a}");
}
}
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0603]: tuple struct constructor `A` is private
--> $DIR/issue-111220-2-tuple-struct-fields-projection.rs:27:13
|
LL | let Self(a) = self;
| ^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0603`.

View File

@ -0,0 +1,46 @@
mod b {
#[derive(Default)]
pub struct A(u32);
}
impl b::A {
fn inherent_bypass(&self) {
let Self(x) = self;
//~^ ERROR: tuple struct constructor `A` is private
println!("{x}");
}
}
pub trait B {
fn f(&self);
}
impl B for b::A {
fn f(&self) {
let Self(a) = self;
//~^ ERROR: tuple struct constructor `A` is private
println!("{}", a);
}
}
pub trait Projector {
type P;
}
impl Projector for () {
type P = b::A;
}
pub trait Bypass2 {
fn f2(&self);
}
impl Bypass2 for <() as Projector>::P {
fn f2(&self) {
let Self(a) = self;
//~^ ERROR: tuple struct constructor `A` is private
println!("{}", a);
}
}
fn main() {}

View File

@ -0,0 +1,21 @@
error[E0603]: tuple struct constructor `A` is private
--> $DIR/issue-111220-tuple-struct-fields.rs:8:13
|
LL | let Self(x) = self;
| ^^^^^^^
error[E0603]: tuple struct constructor `A` is private
--> $DIR/issue-111220-tuple-struct-fields.rs:20:13
|
LL | let Self(a) = self;
| ^^^^^^^
error[E0603]: tuple struct constructor `A` is private
--> $DIR/issue-111220-tuple-struct-fields.rs:40:13
|
LL | let Self(a) = self;
| ^^^^^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0603`.