Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 54 additions & 63 deletions compiler/rustc_privacy/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// tidy-alphabetical-start
#![feature(associated_type_defaults)]
#![feature(default_field_values)]
#![feature(try_blocks)]
// tidy-alphabetical-end

Expand Down Expand Up @@ -29,8 +30,8 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility,
use rustc_middle::query::Providers;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{
self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
TypeVisitor,
self, AssocContainer, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
TypeVisitable, TypeVisitor,
};
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
Expand Down Expand Up @@ -311,6 +312,18 @@ where
}
}

fn assoc_has_type_of(tcx: TyCtxt<'_>, item: &ty::AssocItem) -> bool {
if let ty::AssocKind::Type { data: ty::AssocTypeData::Normal(..) } = item.kind
&& let hir::Node::TraitItem(item) =
tcx.hir_node(tcx.local_def_id_to_hir_id(item.def_id.expect_local()))
&& let hir::TraitItemKind::Type(_, None) = item.kind
{
false
} else {
true
}
}

fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
}
Expand Down Expand Up @@ -639,6 +652,19 @@ impl<'tcx> EmbargoVisitor<'tcx> {
}

impl<'tcx> EmbargoVisitor<'tcx> {
fn check_assoc_item(&mut self, item: &ty::AssocItem, item_ev: EffectiveVisibility) {
let def_id = item.def_id.expect_local();
let tcx = self.tcx;
let mut reach = self.reach(def_id, item_ev);
reach.generics().predicates();
if assoc_has_type_of(tcx, item) {
reach.ty();
}
if item.is_type() && item.container == AssocContainer::Trait {
reach.bounds();
}
}

fn check_def_id(&mut self, owner_id: OwnerId) {
// Update levels of nested things and mark all items
// in interfaces of reachable items as reachable.
Expand Down Expand Up @@ -669,22 +695,10 @@ impl<'tcx> EmbargoVisitor<'tcx> {
self.reach(owner_id.def_id, item_ev).generics().predicates();

for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
if assoc_item.is_impl_trait_in_trait() {
continue;
}

let def_id = assoc_item.def_id.expect_local();
self.update(def_id, item_ev, Level::Reachable);

let tcx = self.tcx;
let mut reach = self.reach(def_id, item_ev);
reach.generics().predicates();

if assoc_item.is_type() && !assoc_item.defaultness(tcx).has_value() {
// No type to visit.
} else {
reach.ty();
}
self.check_assoc_item(assoc_item, item_ev);
}
}
}
Expand Down Expand Up @@ -722,17 +736,13 @@ impl<'tcx> EmbargoVisitor<'tcx> {
}

for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
if assoc_item.is_impl_trait_in_trait() {
continue;
}

let def_id = assoc_item.def_id.expect_local();
let max_vis =
if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) };
self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);

if let Some(impl_item_ev) = self.get(def_id) {
self.reach(def_id, impl_item_ev).generics().predicates().ty();
self.check_assoc_item(assoc_item, impl_item_ev);
}
}
}
Expand Down Expand Up @@ -824,7 +834,12 @@ impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
}

fn predicates(&mut self) -> &mut Self {
self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id));
self.visit_predicates(self.ev.tcx.explicit_predicates_of(self.item_def_id));
self
}

fn bounds(&mut self) -> &mut Self {
self.visit_clauses(self.ev.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
self
}

Expand Down Expand Up @@ -1353,26 +1368,20 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
/// The visitor checks that each component type is at least this visible.
required_visibility: ty::Visibility,
required_effective_vis: Option<EffectiveVisibility>,
in_assoc_ty: bool,
in_primary_interface: bool,
skip_assoc_tys: bool,
hard_error: bool = false,
in_primary_interface: bool = true,
skip_assoc_tys: bool = false,
}

impl SearchInterfaceForPrivateItemsVisitor<'_> {
fn generics(&mut self) -> &mut Self {
self.in_primary_interface = true;
for param in &self.tcx.generics_of(self.item_def_id).own_params {
match param.kind {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { has_default, .. } => {
if has_default {
let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
}
}
// FIXME(generic_const_exprs): May want to look inside const here
GenericParamDefKind::Const { .. } => {
let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
}
if let GenericParamDefKind::Const { .. } = param.kind {
let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
}
if let Some(default) = param.default_value(self.tcx) {
let _ = self.visit(default.instantiate_identity());
}
}
self
Expand Down Expand Up @@ -1427,7 +1436,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
};

let vis = self.tcx.local_visibility(local_def_id);
if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) {
if self.hard_error && !vis.is_at_least(self.required_visibility, self.tcx) {
let vis_descr = match vis {
ty::Visibility::Public => "public",
ty::Visibility::Restricted(vis_def_id) => {
Expand Down Expand Up @@ -1544,9 +1553,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
item_def_id: def_id,
required_visibility,
required_effective_vis,
in_assoc_ty: false,
in_primary_interface: true,
skip_assoc_tys: false,
..
}
}

Expand Down Expand Up @@ -1584,16 +1591,17 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
) {
let mut check = self.check(item.def_id.expect_local(), vis, effective_vis);

let (check_ty, is_assoc_ty) = match item.kind {
ty::AssocKind::Const { .. } | ty::AssocKind::Fn { .. } => (true, false),
ty::AssocKind::Type { .. } => (item.defaultness(self.tcx).has_value(), true),
};

check.in_assoc_ty = is_assoc_ty;
let is_assoc_ty = item.is_type();
check.hard_error = is_assoc_ty && !item.is_impl_trait_in_trait();
check.generics().predicates();
if check_ty {
if assoc_has_type_of(self.tcx, item) {
check.hard_error = check.hard_error && item.defaultness(self.tcx).has_value();
check.ty();
}
if is_assoc_ty && item.container == AssocContainer::Trait {
check.hard_error = false;
check.bounds();
}
}

fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
Expand Down Expand Up @@ -1625,20 +1633,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
self.check(def_id, item_visibility, effective_vis).generics().predicates();

for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
if assoc_item.is_impl_trait_in_trait() {
continue;
}

self.check_assoc_item(assoc_item, item_visibility, effective_vis);

if assoc_item.is_type() {
self.check(
assoc_item.def_id.expect_local(),
item_visibility,
effective_vis,
)
.bounds();
}
}
}
DefKind::TraitAlias => {
Expand Down Expand Up @@ -1712,10 +1707,6 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
}

for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
if assoc_item.is_impl_trait_in_trait() {
continue;
}

let impl_item_vis = if !of_trait {
min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx)
} else {
Expand Down
24 changes: 12 additions & 12 deletions tests/ui/associated-type-bounds/duplicate-bound-err.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
LL | [2u32].into_iter()
| ------------------ return type was inferred to be `std::array::IntoIter<u32, 1>` here

error[E0271]: expected `impl Iterator<Item = u32>` to be an iterator that yields `i32`, but it yields `u32`
--> $DIR/duplicate-bound-err.rs:111:17
|
LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
note: required by a bound in `Trait3::foo::{anon_assoc#0}`
--> $DIR/duplicate-bound-err.rs:107:31
|
LL | fn foo() -> impl Iterator<Item = i32, Item = u32>;
| ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}`

error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
--> $DIR/duplicate-bound-err.rs:87:42
|
Expand Down Expand Up @@ -158,18 +170,6 @@ LL | type MustFail4 = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;
| |
| `ASSOC` bound here first

error[E0271]: expected `impl Iterator<Item = u32>` to be an iterator that yields `i32`, but it yields `u32`
--> $DIR/duplicate-bound-err.rs:111:17
|
LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
note: required by a bound in `Trait3::foo::{anon_assoc#0}`
--> $DIR/duplicate-bound-err.rs:107:31
|
LL | fn foo() -> impl Iterator<Item = i32, Item = u32>;
| ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}`

error[E0271]: expected `Empty<u32>` to be an iterator that yields `i32`, but it yields `u32`
--> $DIR/duplicate-bound-err.rs:119:16
|
Expand Down
6 changes: 1 addition & 5 deletions tests/ui/delegation/unsupported.current.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@ note: ...which requires comparing an impl and trait method signature, inferring
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:32:5: 32:25>::opaque_ret::{anon_assoc#0}`, completing the cycle
note: cycle used when checking assoc item `opaque::<impl at $DIR/unsupported.rs:32:5: 32:25>::opaque_ret` is compatible with trait definition
--> $DIR/unsupported.rs:33:24
|
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
= note: cycle used when checking effective visibilities
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information

error[E0283]: type annotations needed
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/delegation/unsupported.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ note: ...which requires comparing an impl and trait method signature, inferring
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:32:5: 32:25>::opaque_ret::{anon_assoc#0}`, completing the cycle
= note: cycle used when computing implied outlives bounds for `<u16 as opaque::ToReuse>::opaque_ret::{anon_assoc#0}` (hack disabled = false)
= note: cycle used when checking effective visibilities
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information

error[E0283]: type annotations needed
Expand Down
20 changes: 10 additions & 10 deletions tests/ui/lint/lint-stability-deprecated.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
--> $DIR/lint-stability-deprecated.rs:97:48
warning: use of deprecated function `lint_stability::deprecated`: text
--> $DIR/lint-stability-deprecated.rs:24:9
|
LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
| ^^^^^^^^^^^^^^^^^
LL | deprecated();
| ^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-stability-deprecated.rs:6:9
|
LL | #![warn(deprecated)]
| ^^^^^^^^^^

warning: use of deprecated function `lint_stability::deprecated`: text
--> $DIR/lint-stability-deprecated.rs:24:9
|
LL | deprecated();
| ^^^^^^^^^^

warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text
--> $DIR/lint-stability-deprecated.rs:29:16
|
Expand Down Expand Up @@ -322,6 +316,12 @@ warning: use of deprecated function `this_crate::MethodTester::test_method_body:
LL | fn_in_body();
| ^^^^^^^^^^

warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
--> $DIR/lint-stability-deprecated.rs:97:48
|
LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated);
| ^^^^^^^^^^^^^^^^^

warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text
--> $DIR/lint-stability-deprecated.rs:101:13
|
Expand Down
18 changes: 9 additions & 9 deletions tests/ui/lint/lint-stability.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
error[E0658]: use of unstable library feature `unstable_test_feature`
--> $DIR/lint-stability.rs:88:48
|
LL | struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
| ^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: use of unstable library feature `unstable_test_feature`
--> $DIR/lint-stability.rs:17:5
|
Expand Down Expand Up @@ -376,6 +367,15 @@ LL | let _ = Unstable::StableVariant;
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: use of unstable library feature `unstable_test_feature`
--> $DIR/lint-stability.rs:88:48
|
LL | struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
| ^^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: use of unstable library feature `unstable_test_feature`
--> $DIR/lint-stability.rs:92:13
|
Expand Down
40 changes: 40 additions & 0 deletions tests/ui/privacy/auxiliary/missing-mir-priv-bounds-extern.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
pub trait ToPriv {
type AssocPriv;
}

pub trait PubTr {
#[expect(private_bounds)]
type Assoc: ToPriv<AssocPriv = Priv>;
}

struct Dummy;
struct DummyToPriv;
impl PubTr for Dummy {
type Assoc = DummyToPriv;
}
impl ToPriv for DummyToPriv {
type AssocPriv = Priv;
}

pub fn get_dummy() -> impl PubTr {
Dummy
}

struct Priv;

pub trait GetUnreachable {
type Assoc;
}

mod m {
pub struct Unreachable;

impl Unreachable {
#[expect(dead_code)]
pub fn generic<T>() {}
}

impl crate::GetUnreachable for crate::Priv {
type Assoc = Unreachable;
}
}
Loading
Loading