Skip to content

Commit c7a86e7

Browse files
authored
Rollup merge of rust-lang#104348 - fmease:iat-vis-stab, r=cjgillot
Respect visibility & stability of inherent associated types As discussed in rust-lang#103621, this probably won't be the final location of the code that resolves inherent associated types. Still, I think it's valuable to push correctness fixes for this feature (in regards to visibility and stability). Let me know if I should write a translatable diagnostic instead and if I should move the tests to `privacy/` and `stability-attribute/` respectively. Fixes rust-lang#104243. ```@rustbot``` label A-visibility F-inherent_associated_types r? ```@cjgillot``` (since you reviewed rust-lang#103621, feel free to reroll though)
2 parents d93d8ee + 70ad2f5 commit c7a86e7

File tree

7 files changed

+122
-38
lines changed

7 files changed

+122
-38
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+46-37
Original file line numberDiff line numberDiff line change
@@ -1917,17 +1917,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
19171917
}
19181918

19191919
// see if we can satisfy using an inherent associated type
1920-
for impl_ in tcx.inherent_impls(adt_def.did()) {
1921-
let assoc_ty = tcx.associated_items(impl_).find_by_name_and_kind(
1922-
tcx,
1923-
assoc_ident,
1924-
ty::AssocKind::Type,
1925-
*impl_,
1926-
);
1927-
if let Some(assoc_ty) = assoc_ty {
1928-
let ty = tcx.type_of(assoc_ty.def_id);
1929-
return Ok((ty, DefKind::AssocTy, assoc_ty.def_id));
1930-
}
1920+
for &impl_ in tcx.inherent_impls(adt_def.did()) {
1921+
let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, impl_) else {
1922+
continue;
1923+
};
1924+
// FIXME(inherent_associated_types): This does not substitute parameters.
1925+
let ty = tcx.type_of(assoc_ty_did);
1926+
return Ok((ty, DefKind::AssocTy, assoc_ty_did));
19311927
}
19321928
}
19331929

@@ -2014,37 +2010,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20142010
};
20152011

20162012
let trait_did = bound.def_id();
2017-
let (assoc_ident, def_scope) =
2018-
tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
2019-
2020-
// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
2021-
// of calling `filter_by_name_and_kind`.
2022-
let item = tcx.associated_items(trait_did).in_definition_order().find(|i| {
2023-
i.kind.namespace() == Namespace::TypeNS
2024-
&& i.ident(tcx).normalize_to_macros_2_0() == assoc_ident
2025-
});
2026-
// Assume that if it's not matched, there must be a const defined with the same name
2027-
// but it was used in a type position.
2028-
let Some(item) = item else {
2013+
let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did) else {
2014+
// Assume that if it's not matched, there must be a const defined with the same name
2015+
// but it was used in a type position.
20292016
let msg = format!("found associated const `{assoc_ident}` when type was expected");
20302017
let guar = tcx.sess.struct_span_err(span, &msg).emit();
20312018
return Err(guar);
20322019
};
20332020

2034-
let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound);
2021+
let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound);
20352022
let ty = self.normalize_ty(span, ty);
20362023

2037-
let kind = DefKind::AssocTy;
2038-
if !item.visibility(tcx).is_accessible_from(def_scope, tcx) {
2039-
let kind = kind.descr(item.def_id);
2040-
let msg = format!("{} `{}` is private", kind, assoc_ident);
2041-
tcx.sess
2042-
.struct_span_err(span, &msg)
2043-
.span_label(span, &format!("private {}", kind))
2044-
.emit();
2045-
}
2046-
tcx.check_stability(item.def_id, Some(hir_ref_id), span, None);
2047-
20482024
if let Some(variant_def_id) = variant_resolution {
20492025
tcx.struct_span_lint_hir(
20502026
AMBIGUOUS_ASSOCIATED_ITEMS,
@@ -2063,7 +2039,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20632039
};
20642040

20652041
could_refer_to(DefKind::Variant, variant_def_id, "");
2066-
could_refer_to(kind, item.def_id, " also");
2042+
could_refer_to(DefKind::AssocTy, assoc_ty_did, " also");
20672043

20682044
lint.span_suggestion(
20692045
span,
@@ -2076,7 +2052,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20762052
},
20772053
);
20782054
}
2079-
Ok((ty, kind, item.def_id))
2055+
Ok((ty, DefKind::AssocTy, assoc_ty_did))
2056+
}
2057+
2058+
fn lookup_assoc_ty(
2059+
&self,
2060+
ident: Ident,
2061+
block: hir::HirId,
2062+
span: Span,
2063+
scope: DefId,
2064+
) -> Option<DefId> {
2065+
let tcx = self.tcx();
2066+
let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, block);
2067+
2068+
// We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead
2069+
// of calling `find_by_name_and_kind`.
2070+
let item = tcx.associated_items(scope).in_definition_order().find(|i| {
2071+
i.kind.namespace() == Namespace::TypeNS
2072+
&& i.ident(tcx).normalize_to_macros_2_0() == ident
2073+
})?;
2074+
2075+
let kind = DefKind::AssocTy;
2076+
if !item.visibility(tcx).is_accessible_from(def_scope, tcx) {
2077+
let kind = kind.descr(item.def_id);
2078+
let msg = format!("{kind} `{ident}` is private");
2079+
let def_span = self.tcx().def_span(item.def_id);
2080+
tcx.sess
2081+
.struct_span_err_with_code(span, &msg, rustc_errors::error_code!(E0624))
2082+
.span_label(span, &format!("private {kind}"))
2083+
.span_label(def_span, &format!("{kind} defined here"))
2084+
.emit();
2085+
}
2086+
tcx.check_stability(item.def_id, Some(block), span, None);
2087+
2088+
Some(item.def_id)
20802089
}
20812090

20822091
fn qpath_to_ty(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![feature(inherent_associated_types)]
2+
#![allow(incomplete_features)]
3+
4+
mod m {
5+
pub struct T;
6+
impl T {
7+
type P = ();
8+
}
9+
}
10+
type U = m::T::P; //~ ERROR associated type `P` is private
11+
12+
mod n {
13+
pub mod n {
14+
pub struct T;
15+
impl T {
16+
pub(super) type P = bool;
17+
}
18+
}
19+
type U = n::T::P;
20+
}
21+
type V = n::n::T::P; //~ ERROR associated type `P` is private
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0624]: associated type `P` is private
2+
--> $DIR/assoc-inherent-private.rs:10:10
3+
|
4+
LL | type P = ();
5+
| ------ associated type defined here
6+
...
7+
LL | type U = m::T::P;
8+
| ^^^^^^^ private associated type
9+
10+
error[E0624]: associated type `P` is private
11+
--> $DIR/assoc-inherent-private.rs:21:10
12+
|
13+
LL | pub(super) type P = bool;
14+
| ----------------- associated type defined here
15+
...
16+
LL | type V = n::n::T::P;
17+
| ^^^^^^^^^^ private associated type
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0624`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// aux-crate:aux=assoc-inherent-unstable.rs
2+
// edition: 2021
3+
4+
type Data = aux::Owner::Data; //~ ERROR use of unstable library feature 'data'
5+
6+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0658]: use of unstable library feature 'data'
2+
--> $DIR/assoc-inherent-unstable.rs:4:13
3+
|
4+
LL | type Data = aux::Owner::Data;
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
= help: add `#![feature(data)]` to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(staged_api)]
2+
#![feature(inherent_associated_types)]
3+
#![stable(feature = "main", since = "1.0.0")]
4+
5+
#[stable(feature = "main", since = "1.0.0")]
6+
pub struct Owner;
7+
8+
impl Owner {
9+
#[unstable(feature = "data", issue = "none")]
10+
pub type Data = ();
11+
}

src/test/ui/traits/item-privacy.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,12 @@ error[E0223]: ambiguous associated type
162162
LL | let _: S::C;
163163
| ^^^^ help: use fully-qualified syntax: `<S as Trait>::C`
164164

165-
error: associated type `A` is private
165+
error[E0624]: associated type `A` is private
166166
--> $DIR/item-privacy.rs:119:12
167167
|
168+
LL | type A = u8;
169+
| ------ associated type defined here
170+
...
168171
LL | let _: T::A;
169172
| ^^^^ private associated type
170173

0 commit comments

Comments
 (0)