Skip to content

Commit 56d8a93

Browse files
committed
Auto merge of #76195 - lcnr:const-Self, r=varkor
allow concrete self types in consts This is quite a bad hack to fix #75486. There might be a better way to check if the self type depends on generic parameters, but I wasn't able to come up with one. r? `@varkor` cc `@petrochenkov`
2 parents 0b65a3d + 90dd798 commit 56d8a93

File tree

13 files changed

+146
-20
lines changed

13 files changed

+146
-20
lines changed

compiler/rustc_hir/src/def.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,16 @@ pub enum Res<Id = hir::HirId> {
199199

200200
// Type namespace
201201
PrimTy(hir::PrimTy),
202-
SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
202+
/// `Self`, with both an optional trait and impl `DefId`.
203+
///
204+
/// HACK(min_const_generics): impl self types also have an optional requirement to not mention
205+
/// any generic parameters to allow the following with `min_const_generics`:
206+
/// ```rust
207+
/// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] {} }
208+
/// ```
209+
///
210+
/// FIXME(lazy_normalization_consts): Remove this bodge once this feature is stable.
211+
SelfTy(Option<DefId> /* trait */, Option<(DefId, bool)> /* impl */),
203212
ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
204213

205214
// Value namespace

compiler/rustc_passes/src/dead.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
104104
if let Some(t) = t {
105105
self.check_def_id(t);
106106
}
107-
if let Some(i) = i {
107+
if let Some((i, _)) = i {
108108
self.check_def_id(i);
109109
}
110110
}

compiler/rustc_resolve/src/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl<'a> Resolver<'a> {
112112
match outer_res {
113113
Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => {
114114
if let Some(impl_span) =
115-
maybe_impl_defid.and_then(|def_id| self.opt_span(def_id))
115+
maybe_impl_defid.and_then(|(def_id, _)| self.opt_span(def_id))
116116
{
117117
err.span_label(
118118
reduce_impl_span_to_impl_keyword(sm, impl_span),

compiler/rustc_resolve/src/late.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ crate enum RibKind<'a> {
110110
ItemRibKind(HasGenericParams),
111111

112112
/// We're in a constant item. Can't refer to dynamic stuff.
113+
///
114+
/// The `bool` indicates if this constant may reference generic parameters
115+
/// and is used to only allow generic parameters to be used in trivial constant expressions.
113116
ConstantItemRibKind(bool),
114117

115118
/// We passed through a module.
@@ -848,7 +851,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
848851
self.with_current_self_item(item, |this| {
849852
this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
850853
let item_def_id = this.r.local_def_id(item.id).to_def_id();
851-
this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| {
854+
this.with_self_rib(Res::SelfTy(None, Some((item_def_id, false))), |this| {
852855
visit::walk_item(this, item);
853856
});
854857
});
@@ -1215,7 +1218,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
12151218
// Resolve the trait reference, if necessary.
12161219
this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
12171220
let item_def_id = this.r.local_def_id(item_id).to_def_id();
1218-
this.with_self_rib(Res::SelfTy(trait_id, Some(item_def_id)), |this| {
1221+
this.with_self_rib(Res::SelfTy(trait_id, Some((item_def_id, false))), |this| {
12191222
if let Some(trait_ref) = opt_trait_reference.as_ref() {
12201223
// Resolve type arguments in the trait path.
12211224
visit::walk_trait_ref(this, trait_ref);

compiler/rustc_resolve/src/lib.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -2539,7 +2539,7 @@ impl<'a> Resolver<'a> {
25392539
&mut self,
25402540
rib_index: usize,
25412541
rib_ident: Ident,
2542-
res: Res,
2542+
mut res: Res,
25432543
record_used: bool,
25442544
span: Span,
25452545
all_ribs: &[Rib<'a>],
@@ -2629,13 +2629,22 @@ impl<'a> Resolver<'a> {
26292629
ConstantItemRibKind(trivial) => {
26302630
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
26312631
if !trivial && self.session.features_untracked().min_const_generics {
2632-
if record_used {
2633-
self.report_error(
2634-
span,
2635-
ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name),
2636-
);
2632+
// HACK(min_const_generics): If we encounter `Self` in an anonymous constant
2633+
// we can't easily tell if it's generic at this stage, so we instead remember
2634+
// this and then enforce the self type to be concrete later on.
2635+
if let Res::SelfTy(trait_def, Some((impl_def, _))) = res {
2636+
res = Res::SelfTy(trait_def, Some((impl_def, true)));
2637+
} else {
2638+
if record_used {
2639+
self.report_error(
2640+
span,
2641+
ResolutionError::ParamInNonTrivialAnonConst(
2642+
rib_ident.name,
2643+
),
2644+
);
2645+
}
2646+
return Res::Err;
26372647
}
2638-
return Res::Err;
26392648
}
26402649

26412650
if in_ty_param_default {

compiler/rustc_typeck/src/astconv/mod.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -1460,7 +1460,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14601460
// Find the type of the associated item, and the trait where the associated
14611461
// item is declared.
14621462
let bound = match (&qself_ty.kind(), qself_res) {
1463-
(_, Res::SelfTy(Some(_), Some(impl_def_id))) => {
1463+
(_, Res::SelfTy(Some(_), Some((impl_def_id, _)))) => {
14641464
// `Self` in an impl of a trait -- we have a concrete self type and a
14651465
// trait reference.
14661466
let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
@@ -1917,12 +1917,29 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
19171917
self.prohibit_generics(path.segments);
19181918
tcx.types.self_param
19191919
}
1920-
Res::SelfTy(_, Some(def_id)) => {
1920+
Res::SelfTy(_, Some((def_id, forbid_generic))) => {
19211921
// `Self` in impl (we know the concrete type).
19221922
assert_eq!(opt_self_ty, None);
19231923
self.prohibit_generics(path.segments);
19241924
// Try to evaluate any array length constants.
1925-
self.normalize_ty(span, tcx.at(span).type_of(def_id))
1925+
let normalized_ty = self.normalize_ty(span, tcx.at(span).type_of(def_id));
1926+
if forbid_generic && normalized_ty.needs_subst() {
1927+
let mut err = tcx.sess.struct_span_err(
1928+
path.span,
1929+
"generic `Self` types are currently not permitted in anonymous constants",
1930+
);
1931+
if let Some(hir::Node::Item(&hir::Item {
1932+
kind: hir::ItemKind::Impl { self_ty, .. },
1933+
..
1934+
})) = tcx.hir().get_if_local(def_id)
1935+
{
1936+
err.span_note(self_ty.span, "not a concrete type");
1937+
}
1938+
err.emit();
1939+
tcx.ty_error()
1940+
} else {
1941+
normalized_ty
1942+
}
19261943
}
19271944
Res::Def(DefKind::AssocTy, def_id) => {
19281945
debug_assert!(path.segments.len() >= 2);

src/librustdoc/clean/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId {
601601
},
602602
Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias),
603603
Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
604-
Res::SelfTy(_, Some(impl_def_id)) => return impl_def_id,
604+
Res::SelfTy(_, Some((impl_def_id, _))) => return impl_def_id,
605605
_ => return res.def_id(),
606606
};
607607
if did.is_local() {
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
error: generic parameters must not be used inside of non trivial constant values
1+
error: generic `Self` types are currently not permitted in anonymous constants
22
--> $DIR/issue-62504.rs:19:25
33
|
44
LL | ArrayHolder([0; Self::SIZE])
5-
| ^^^^^^^^^^ non-trivial anonymous constants must not depend on the parameter `Self`
5+
| ^^^^^^^^^^
66
|
7-
= help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants
7+
note: not a concrete type
8+
--> $DIR/issue-62504.rs:17:22
9+
|
10+
LL | impl<const X: usize> ArrayHolder<X> {
11+
| ^^^^^^^^^^^^^^
812

913
error: aborting due to previous error
1014

src/test/ui/const-generics/issues/issue-62504.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ impl<const X: usize> ArrayHolder<X> {
1818
pub const fn new() -> Self {
1919
ArrayHolder([0; Self::SIZE])
2020
//[full]~^ ERROR constant expression depends on a generic parameter
21-
//[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
21+
//[min]~^^ ERROR generic `Self` types are currently
2222
}
2323
}
2424

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![feature(min_const_generics)]
2+
3+
trait Foo {
4+
fn t1() -> [u8; std::mem::size_of::<Self>()]; //~ERROR generic parameters
5+
}
6+
7+
struct Bar<T>(T);
8+
9+
impl Bar<u8> {
10+
fn t2() -> [u8; std::mem::size_of::<Self>()] { todo!() } // ok
11+
}
12+
13+
impl<T> Bar<T> {
14+
fn t3() -> [u8; std::mem::size_of::<Self>()] {} //~ERROR generic `Self`
15+
}
16+
17+
trait Baz {
18+
fn hey();
19+
}
20+
21+
impl Baz for u16 {
22+
fn hey() {
23+
let _: [u8; std::mem::size_of::<Self>()]; // ok
24+
}
25+
}
26+
27+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: generic parameters must not be used inside of non trivial constant values
2+
--> $DIR/self-ty-in-const-1.rs:4:41
3+
|
4+
LL | fn t1() -> [u8; std::mem::size_of::<Self>()];
5+
| ^^^^ non-trivial anonymous constants must not depend on the parameter `Self`
6+
|
7+
= help: it is currently only allowed to use either `Self` or `{ Self }` as generic constants
8+
9+
error: generic `Self` types are currently not permitted in anonymous constants
10+
--> $DIR/self-ty-in-const-1.rs:14:41
11+
|
12+
LL | fn t3() -> [u8; std::mem::size_of::<Self>()] {}
13+
| ^^^^
14+
|
15+
note: not a concrete type
16+
--> $DIR/self-ty-in-const-1.rs:13:9
17+
|
18+
LL | impl<T> Bar<T> {
19+
| ^^^^^^
20+
21+
error: aborting due to 2 previous errors
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#![feature(min_const_generics)]
2+
3+
struct Bar<T>(T);
4+
5+
trait Baz {
6+
fn hey();
7+
}
8+
9+
impl Baz for u16 {
10+
fn hey() {
11+
let _: [u8; std::mem::size_of::<Self>()]; // ok
12+
}
13+
}
14+
15+
impl<T> Baz for Bar<T> {
16+
fn hey() {
17+
let _: [u8; std::mem::size_of::<Self>()]; //~ERROR generic `Self`
18+
}
19+
}
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: generic `Self` types are currently not permitted in anonymous constants
2+
--> $DIR/self-ty-in-const-2.rs:17:41
3+
|
4+
LL | let _: [u8; std::mem::size_of::<Self>()];
5+
| ^^^^
6+
|
7+
note: not a concrete type
8+
--> $DIR/self-ty-in-const-2.rs:15:17
9+
|
10+
LL | impl<T> Baz for Bar<T> {
11+
| ^^^^^^
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)