Skip to content

Commit

Permalink
Auto merge of rust-lang#126076 - jswrenn:fix-45713, r=<try>
Browse files Browse the repository at this point in the history
privacy: normalize associated types before visiting

This permits associated types to reference private types and traits, so long as the normalized type does not itself violate type privacy.

Fixes rust-lang#45713

<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
tracking issue or there are none, feel free to ignore this.

This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using

    r​? <reviewer name>
-->
  • Loading branch information
bors committed Jun 18, 2024
2 parents af3d100 + c2af856 commit eac951e
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 48 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4611,10 +4611,12 @@ dependencies = [
"rustc_errors",
"rustc_fluent_macro",
"rustc_hir",
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_trait_selection",
"rustc_ty_utils",
"tracing",
]
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_privacy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_hir = { path = "../rustc_hir" }
rustc_infer = { path = "../rustc_infer" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_ty_utils = { path = "../rustc_ty_utils" }
tracing = "0.1"
# tidy-alphabetical-end
26 changes: 24 additions & 2 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
use rustc_middle::query::Providers;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::GenericArgs;
use rustc_middle::ty::{self, Const, GenericParamDefKind};
use rustc_middle::ty::{GenericArgs, ParamEnv};
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::infer::TyCtxtInferExt;
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
use tracing::debug;

use std::fmt;
Expand Down Expand Up @@ -1306,7 +1308,13 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {

fn ty(&mut self) -> &mut Self {
self.in_primary_interface = true;
self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity());
let ty = self.tcx.type_of(self.item_def_id).instantiate_identity();

// Attempt to normalize `ty`
let param_env = self.tcx.param_env(self.item_def_id);
let maybe_normalized_ty = try_normalize(self.tcx, param_env, ty);

self.visit(maybe_normalized_ty.unwrap_or(ty));
self
}

Expand Down Expand Up @@ -1767,3 +1775,17 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
checker.check_item(id);
}
}

/// Attempts to deeply normalize `ty`.
fn try_normalize<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Result<Ty<'tcx>, ()> {
let infcx = tcx.infer_ctxt().with_next_trait_solver(true).build();
let ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy();
let Ok(ty) = ocx.deeply_normalize(&cause, param_env, ty) else { return Err(()) };
let errors = ocx.select_all_or_error();
if errors.is_empty() { Ok(ty) } else { Err(()) }
}
1 change: 0 additions & 1 deletion src/tools/tidy/src/issues.txt
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,6 @@ ui/const-generics/issues/issue-80062.rs
ui/const-generics/issues/issue-80375.rs
ui/const-generics/issues/issue-82956.rs
ui/const-generics/issues/issue-83249.rs
ui/const-generics/issues/issue-83288.rs
ui/const-generics/issues/issue-83466.rs
ui/const-generics/issues/issue-83765.rs
ui/const-generics/issues/issue-84659.rs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@ build-pass
//@ known-bug: rust-lang/rust#83288

#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-inherent-types/private-in-public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
#![crate_type = "lib"]

pub type PubAlias0 = PubTy::PrivAssocTy;
//~^ WARNING associated type `PubTy::PrivAssocTy` is more private than the item `PubAlias0`

pub type PubAlias1 = PrivTy::PubAssocTy;
//~^ WARNING type `PrivTy` is more private than the item `PubAlias1`

pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>;
//~^ WARNING type `PrivTy` is more private than the item `PubAlias2`

Expand Down
28 changes: 2 additions & 26 deletions tests/ui/associated-inherent-types/private-in-public.stderr
Original file line number Diff line number Diff line change
@@ -1,28 +1,3 @@
warning: associated type `PubTy::PrivAssocTy` is more private than the item `PubAlias0`
--> $DIR/private-in-public.rs:7:1
|
LL | pub type PubAlias0 = PubTy::PrivAssocTy;
| ^^^^^^^^^^^^^^^^^^ type alias `PubAlias0` is reachable at visibility `pub`
|
note: but associated type `PubTy::PrivAssocTy` is only usable at visibility `pub(crate)`
--> $DIR/private-in-public.rs:16:5
|
LL | type PrivAssocTy = ();
| ^^^^^^^^^^^^^^^^
= note: `#[warn(private_interfaces)]` on by default

warning: type `PrivTy` is more private than the item `PubAlias1`
--> $DIR/private-in-public.rs:9:1
|
LL | pub type PubAlias1 = PrivTy::PubAssocTy;
| ^^^^^^^^^^^^^^^^^^ type alias `PubAlias1` is reachable at visibility `pub`
|
note: but type `PrivTy` is only usable at visibility `pub(crate)`
--> $DIR/private-in-public.rs:20:1
|
LL | struct PrivTy;
| ^^^^^^^^^^^^^

warning: type `PrivTy` is more private than the item `PubAlias2`
--> $DIR/private-in-public.rs:11:1
|
Expand All @@ -34,6 +9,7 @@ note: but type `PrivTy` is only usable at visibility `pub(crate)`
|
LL | struct PrivTy;
| ^^^^^^^^^^^^^
= note: `#[warn(private_interfaces)]` on by default

warning: 3 warnings emitted
warning: 1 warning emitted

3 changes: 1 addition & 2 deletions tests/ui/privacy/projections2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ mod m {

impl Trait4 for u8 {
type A<T: Trait> = <u8 as Trait3>::A<T>;
//~^ ERROR: private associated type `Trait3::A` in public interface
//~| ERROR: private trait `Trait3` in public interface
//~^ ERROR: private type `Priv` in public interface
}
}

Expand Down
19 changes: 5 additions & 14 deletions tests/ui/privacy/projections2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,15 @@ LL | struct Priv;
| ^^^^^^^^^^^
= note: `#[warn(private_interfaces)]` on by default

error[E0446]: private associated type `Trait3::A` in public interface
error[E0446]: private type `Priv` in public interface
--> $DIR/projections2.rs:19:9
|
LL | type A<T: Trait>;
| ---------------- `Trait3::A` declared as private
...
LL | type A<T: Trait> = <u8 as Trait3>::A<T>;
| ^^^^^^^^^^^^^^^^ can't leak private associated type

error[E0446]: private trait `Trait3` in public interface
--> $DIR/projections2.rs:19:9
|
LL | trait Trait3 {
| ------------ `Trait3` declared as private
LL | struct Priv;
| ----------- `Priv` declared as private
...
LL | type A<T: Trait> = <u8 as Trait3>::A<T>;
| ^^^^^^^^^^^^^^^^ can't leak private trait
| ^^^^^^^^^^^^^^^^ can't leak private type

error: aborting due to 2 previous errors; 1 warning emitted
error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0446`.

0 comments on commit eac951e

Please sign in to comment.