Skip to content

Commit d3e0d2f

Browse files
committed
supply substs to anon consts in defaults
1 parent 312b4fd commit d3e0d2f

11 files changed

+62
-71
lines changed

compiler/rustc_typeck/src/astconv/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
513513
GenericParamDefKind::Const { has_default } => {
514514
let ty = tcx.at(self.span).type_of(param.def_id);
515515
if !infer_args && has_default {
516-
tcx.const_param_default(param.def_id).into()
516+
tcx.const_param_default(param.def_id)
517+
.subst_spanned(tcx, substs.unwrap(), Some(self.span))
518+
.into()
517519
} else {
518520
if infer_args {
519521
self.astconv.ct_infer(ty, Some(param), self.span).into()

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1446,7 +1446,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14461446
}
14471447
GenericParamDefKind::Const { has_default, .. } => {
14481448
if !infer_args && has_default {
1449-
tcx.const_param_default(param.def_id).into()
1449+
tcx.const_param_default(param.def_id)
1450+
.subst_spanned(tcx, substs.unwrap(), Some(self.span))
1451+
.into()
14501452
} else {
14511453
self.fcx.var_for_def(self.span, param)
14521454
}

compiler/rustc_typeck/src/collect.rs

+19-20
Original file line numberDiff line numberDiff line change
@@ -1316,29 +1316,31 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
13161316
}
13171317
}
13181318

1319-
struct AnonConstInParamListDetector {
1320-
in_param_list: bool,
1321-
found_anon_const_in_list: bool,
1319+
struct AnonConstInParamTyDetector {
1320+
in_param_ty: bool,
1321+
found_anon_const_in_param_ty: bool,
13221322
ct: HirId,
13231323
}
13241324

1325-
impl<'v> Visitor<'v> for AnonConstInParamListDetector {
1325+
impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
13261326
type Map = intravisit::ErasedMap<'v>;
13271327

13281328
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
13291329
NestedVisitorMap::None
13301330
}
13311331

13321332
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
1333-
let prev = self.in_param_list;
1334-
self.in_param_list = true;
1335-
intravisit::walk_generic_param(self, p);
1336-
self.in_param_list = prev;
1333+
if let GenericParamKind::Const { ref ty, default: _ } = p.kind {
1334+
let prev = self.in_param_ty;
1335+
self.in_param_ty = true;
1336+
self.visit_ty(ty);
1337+
self.in_param_ty = prev;
1338+
}
13371339
}
13381340

13391341
fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
1340-
if self.in_param_list && self.ct == c.hir_id {
1341-
self.found_anon_const_in_list = true;
1342+
if self.in_param_ty && self.ct == c.hir_id {
1343+
self.found_anon_const_in_param_ty = true;
13421344
} else {
13431345
intravisit::walk_anon_const(self, c)
13441346
}
@@ -1366,27 +1368,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
13661368
let parent_id = tcx.hir().get_parent_item(hir_id);
13671369
let parent_def_id = tcx.hir().local_def_id(parent_id);
13681370

1369-
let mut in_param_list = false;
1371+
let mut in_param_ty = false;
13701372
for (_parent, node) in tcx.hir().parent_iter(hir_id) {
13711373
if let Some(generics) = node.generics() {
1372-
let mut visitor = AnonConstInParamListDetector {
1373-
in_param_list: false,
1374-
found_anon_const_in_list: false,
1374+
let mut visitor = AnonConstInParamTyDetector {
1375+
in_param_ty: false,
1376+
found_anon_const_in_param_ty: false,
13751377
ct: hir_id,
13761378
};
13771379

13781380
visitor.visit_generics(generics);
1379-
in_param_list = visitor.found_anon_const_in_list;
1381+
in_param_ty = visitor.found_anon_const_in_param_ty;
13801382
break;
13811383
}
13821384
}
13831385

1384-
if in_param_list {
1386+
if in_param_ty {
13851387
// We do not allow generic parameters in anon consts if we are inside
1386-
// of a param list.
1387-
//
1388-
// This affects both default type bindings, e.g. `struct<T, U = [u8; std::mem::size_of::<T>()]>(T, U)`,
1389-
// and the types of const parameters, e.g. `struct V<const N: usize, const M: [u8; N]>();`.
1388+
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
13901389
None
13911390
} else if tcx.lazy_normalization() {
13921391
// HACK(eddyb) this provides the correct generics when

src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr

+13-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
error[E0277]: the size for values of type `T` cannot be known at compilation time
2-
--> $DIR/complex-generic-default-expr.rs:9:62
1+
error: constant expression depends on a generic parameter
2+
--> $DIR/complex-generic-default-expr.rs:6:34
3+
|
4+
LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
5+
| ^
6+
|
7+
= note: this may fail depending on what value the parameter takes
8+
9+
error: constant expression depends on a generic parameter
10+
--> $DIR/complex-generic-default-expr.rs:10:21
311
|
412
LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
5-
| - ^ doesn't have a size known at compile-time
6-
| |
7-
| this type parameter needs to be `std::marker::Sized`
8-
|
9-
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
13+
| ^^^^^^^^^
1014
|
11-
LL | pub const fn size_of<T>() -> usize {
12-
| - required by this bound in `std::mem::size_of`
15+
= note: this may fail depending on what value the parameter takes
1316

14-
error: aborting due to previous error
17+
error: aborting due to 2 previous errors
1518

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

src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: generic parameters may not be used in const operations
2-
--> $DIR/complex-generic-default-expr.rs:10:47
2+
--> $DIR/complex-generic-default-expr.rs:6:47
33
|
44
LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
55
| ^ cannot perform const operation using `N`
@@ -8,7 +8,7 @@ LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
88
= help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
99

1010
error: generic parameters may not be used in const operations
11-
--> $DIR/complex-generic-default-expr.rs:13:62
11+
--> $DIR/complex-generic-default-expr.rs:10:62
1212
|
1313
LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
1414
| ^ cannot perform const operation using `T`
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
// revisions: min
2-
// FIXME(const_generics): add the `full` revision,
3-
// currently causes an ICE as we don't supply substs to
4-
// anon consts in the parameter listing, as that would
5-
// cause that anon const to reference itself.
1+
// revisions: full min
62
#![cfg_attr(full, feature(const_generics))]
73
#![feature(const_generics_defaults)]
84
#![allow(incomplete_features)]
95

106
struct Foo<const N: usize, const M: usize = { N + 1 }>;
11-
//[min]~^ ERROR generic parameters may not be used in const operations
7+
//[full]~^ ERROR constant expression depends on a generic parameter
8+
//[min]~^^ ERROR generic parameters may not be used in const operations
129

1310
struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
14-
//[min]~^ ERROR generic parameters may not be used in const operations
15-
//[full]~^^ ERROR the size for values of type `T` cannot be known at compilation time
11+
//[full]~^ ERROR constant expression depends on a generic parameter
12+
//[min]~^^ ERROR generic parameters may not be used in const operations
1613

1714
fn main() {}

src/test/ui/const-generics/defaults/const-param-as-default-value.rs

+9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,16 @@ fn foo<const N: usize>() -> Foo<N> {
88
Foo(x, x)
99
}
1010

11+
// To check that we actually apply the correct substs for const param defaults.
12+
fn concrete_foo() -> Foo<13> {
13+
Foo(Default::default(), Default::default())
14+
}
15+
16+
1117
fn main() {
1218
let val = foo::<13>();
1319
assert_eq!(val.0, val.1);
20+
21+
let val = concrete_foo();
22+
assert_eq!(val.0, val.1);
1423
}

src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs

-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
// run-pass
22
#![feature(const_generics_defaults)]
33
#![allow(incomplete_features)]
4-
// FIXME(const_generics_defaults): while we can allow this,
5-
// we probably won't easily allow this with more complex const operations.
6-
//
7-
// So we have to make a conscious decision here when stabilizing a relaxed parameter ordering.
84
struct Foo<const N: usize, T = [u8; N]>(T);
95

106
impl<const N: usize> Foo<N> {
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,17 @@
11
error: generic parameters with a default must be trailing
2-
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12
2+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12
33
|
44
LL | struct Bar<T = [u8; N], const N: usize>(T);
55
| ^
66
|
77
= note: using type defaults and const parameters in the same parameter list is currently not permitted
88

99
error[E0128]: generic parameters with a default cannot use forward declared identifiers
10-
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21
10+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
1111
|
1212
LL | struct Bar<T = [u8; N], const N: usize>(T);
1313
| ^ defaulted generic parameters cannot be forward declared
1414

15-
error[E0277]: the size for values of type `T` cannot be known at compilation time
16-
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
17-
|
18-
LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
19-
| - ^ doesn't have a size known at compile-time
20-
| |
21-
| this type parameter needs to be `std::marker::Sized`
22-
|
23-
::: $SRC_DIR/core/src/mem/mod.rs:LL:COL
24-
|
25-
LL | pub const fn size_of<T>() -> usize {
26-
| - required by this bound in `std::mem::size_of`
27-
28-
error: aborting due to 3 previous errors
15+
error: aborting due to 2 previous errors
2916

30-
Some errors have detailed explanations: E0128, E0277.
31-
For more information about an error, try `rustc --explain E0128`.
17+
For more information about this error, try `rustc --explain E0128`.

src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: generic parameters with a default must be trailing
2-
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:12
2+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12
33
|
44
LL | struct Bar<T = [u8; N], const N: usize>(T);
55
| ^
66
|
77
= note: using type defaults and const parameters in the same parameter list is currently not permitted
88

99
error: generic parameters may not be used in const operations
10-
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
10+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44
1111
|
1212
LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
1313
| ^ cannot perform const operation using `T`
@@ -16,7 +16,7 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
1616
= help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
1717

1818
error[E0128]: generic parameters with a default cannot use forward declared identifiers
19-
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:10:21
19+
--> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
2020
|
2121
LL | struct Bar<T = [u8; N], const N: usize>(T);
2222
| ^ defaulted generic parameters cannot be forward declared

src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
// revisions: full min
2-
32
#![cfg_attr(full, feature(const_generics))]
43
#![cfg_attr(full, allow(incomplete_features))]
54

65
struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
7-
//[full]~^ ERROR the size for values of type `T` cannot be known at compilation time
8-
//[min]~^^ ERROR generic parameters may not be used in const operations
6+
//[min]~^ ERROR generic parameters may not be used in const operations
97

108
struct Bar<T = [u8; N], const N: usize>(T);
119
//~^ ERROR generic parameters with a default cannot use forward declared identifiers

0 commit comments

Comments
 (0)