Skip to content

Commit 6f5d8bf

Browse files
committed
don't supply generics to AnonConsts in param lists
1 parent 3f55840 commit 6f5d8bf

File tree

4 files changed

+68
-37
lines changed

4 files changed

+68
-37
lines changed

src/librustc_typeck/collect.rs

+56-5
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
2929
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
3030
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
3131
use rustc_hir::weak_lang_items;
32-
use rustc_hir::{GenericParamKind, Node};
32+
use rustc_hir::{GenericParamKind, HirId, Node};
3333
use rustc_middle::hir::map::blocks::FnLikeNode;
3434
use rustc_middle::hir::map::Map;
3535
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@@ -1155,6 +1155,35 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
11551155
}
11561156
}
11571157

1158+
struct AnonConstInParamListDetector {
1159+
in_param_list: bool,
1160+
found_anon_const_in_list: bool,
1161+
ct: HirId,
1162+
}
1163+
1164+
impl<'v> Visitor<'v> for AnonConstInParamListDetector {
1165+
type Map = intravisit::ErasedMap<'v>;
1166+
1167+
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
1168+
NestedVisitorMap::None
1169+
}
1170+
1171+
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
1172+
let prev = self.in_param_list;
1173+
self.in_param_list = true;
1174+
intravisit::walk_generic_param(self, p);
1175+
self.in_param_list = prev;
1176+
}
1177+
1178+
fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
1179+
if self.in_param_list && self.ct == c.hir_id {
1180+
self.found_anon_const_in_list = true;
1181+
} else {
1182+
intravisit::walk_anon_const(self, c)
1183+
}
1184+
}
1185+
}
1186+
11581187
fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
11591188
use rustc_hir::*;
11601189

@@ -1176,10 +1205,32 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
11761205
let parent_id = tcx.hir().get_parent_item(hir_id);
11771206
let parent_def_id = tcx.hir().local_def_id(parent_id);
11781207

1179-
// HACK(eddyb) this provides the correct generics when
1180-
// `feature(const_generics)` is enabled, so that const expressions
1181-
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
1182-
if tcx.lazy_normalization() {
1208+
let mut in_param_list = false;
1209+
for (_parent, node) in tcx.hir().parent_iter(hir_id) {
1210+
if let Some(generics) = node.generics() {
1211+
let mut visitor = AnonConstInParamListDetector {
1212+
in_param_list: false,
1213+
found_anon_const_in_list: false,
1214+
ct: hir_id,
1215+
};
1216+
1217+
visitor.visit_generics(generics);
1218+
in_param_list = visitor.found_anon_const_in_list;
1219+
break;
1220+
}
1221+
}
1222+
1223+
if in_param_list {
1224+
// We do not allow generic parameters in anon consts if we are inside
1225+
// of a param list.
1226+
//
1227+
// This affects both default type bindings, e.g. `struct<T, U = [u8; std::mem::size_of::<T>()]>(T, U)`,
1228+
// and the types of const parameters, e.g. `struct V<const N: usize, const M: [u8; N]>();`.
1229+
None
1230+
} else if tcx.lazy_normalization() {
1231+
// HACK(eddyb) this provides the correct generics when
1232+
// `feature(const_generics)` is enabled, so that const expressions
1233+
// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
11831234
Some(parent_def_id.to_def_id())
11841235
} else {
11851236
let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));

src/test/ui/const-generics/const-param-type-depends-on-const-param.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88

99
pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
1010
//~^ ERROR: the type of const parameters must not depend on other generic parameters
11-
//~| ERROR: cycle detected when computing type of `Dependent::X`
1211

1312
pub struct SelfDependent<const N: [u8; N]>;
1413
//~^ ERROR: the type of const parameters must not depend on other generic parameters
15-
//~| ERROR: cycle detected when computing type of `SelfDependent::N`
1614

1715
fn main() {}

src/test/ui/const-generics/const-param-type-depends-on-const-param.stderr

+3-30
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ error[E0770]: the type of const parameters must not depend on other generic para
44
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
55
| ^ const parameters must have a concrete type
66

7-
error[E0769]: the type of const parameters must not depend on other generic parameters
8-
--> $DIR/const-param-type-depends-on-const-param.rs:13:40
7+
error[E0770]: the type of const parameters must not depend on other generic parameters
8+
--> $DIR/const-param-type-depends-on-const-param.rs:12:40
99
|
1010
LL | pub struct SelfDependent<const N: [u8; N]>;
1111
| ^ const parameters must have a concrete type
@@ -19,32 +19,5 @@ LL | #![feature(const_generics)]
1919
= note: `#[warn(incomplete_features)]` on by default
2020
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
2121

22-
error[E0391]: cycle detected when computing type of `Dependent::X`
23-
--> $DIR/const-param-type-depends-on-const-param.rs:9:44
24-
|
25-
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
26-
| ^
27-
|
28-
= note: ...which again requires computing type of `Dependent::X`, completing the cycle
29-
note: cycle used when computing type of `Dependent`
30-
--> $DIR/const-param-type-depends-on-const-param.rs:9:1
31-
|
32-
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
33-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34-
35-
error[E0391]: cycle detected when computing type of `SelfDependent::N`
36-
--> $DIR/const-param-type-depends-on-const-param.rs:13:32
37-
|
38-
LL | pub struct SelfDependent<const N: [u8; N]>;
39-
| ^
40-
|
41-
= note: ...which again requires computing type of `SelfDependent::N`, completing the cycle
42-
note: cycle used when computing type of `SelfDependent`
43-
--> $DIR/const-param-type-depends-on-const-param.rs:13:1
44-
|
45-
LL | pub struct SelfDependent<const N: [u8; N]>;
46-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47-
48-
error: aborting due to 4 previous errors; 1 warning emitted
22+
error: aborting due to 2 previous errors; 1 warning emitted
4923

50-
For more information about this error, try `rustc --explain E0391`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// check-pass
2+
#![feature(const_generics)]
3+
#![allow(incomplete_features)]
4+
5+
fn test<const N: [u8; 1 + 2]>() {}
6+
7+
struct Foo<const N: [u8; 1 + 2]>;
8+
9+
fn main() {}

0 commit comments

Comments
 (0)