Skip to content

Commit

Permalink
fix for Self not respecting tuple Ctor privacy
Browse files Browse the repository at this point in the history
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
    }
}
```
  • Loading branch information
fee1-dead committed May 25, 2023
1 parent 70db836 commit dee65a4
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 0 deletions.
2 changes: 2 additions & 0 deletions compiler/rustc_hir_typeck/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,5 @@ hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`
[implement] , perhaps you need to implement it
*[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
}
hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
8 changes: 8 additions & 0 deletions compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
7 changes: 7 additions & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -1210,6 +1211,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;
Expand Down
33 changes: 33 additions & 0 deletions tests/ui/privacy/issue-111220-2-tuple-struct-fields-projection.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.
46 changes: 46 additions & 0 deletions tests/ui/privacy/issue-111220-tuple-struct-fields.rs
Original file line number Diff line number Diff line change
@@ -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() {}
21 changes: 21 additions & 0 deletions tests/ui/privacy/issue-111220-tuple-struct-fields.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit dee65a4

Please sign in to comment.