Skip to content

Commit 8cd12bf

Browse files
committed
check types of const param default
1 parent dc8fe1f commit 8cd12bf

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+33
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,39 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
14881488
.then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
14891489
default,
14901490
);
1491+
} else {
1492+
// If we've got a generic const parameter we still want to check its
1493+
// type is correct in case both it and the param type are fully concrete.
1494+
let GenericArgKind::Const(ct) = default.unpack() else {
1495+
continue;
1496+
};
1497+
1498+
let ct_ty = match ct.kind() {
1499+
ty::ConstKind::Infer(_)
1500+
| ty::ConstKind::Placeholder(_)
1501+
| ty::ConstKind::Bound(_, _) => unreachable!(),
1502+
ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue,
1503+
ty::ConstKind::Value(cv) => cv.ty,
1504+
ty::ConstKind::Unevaluated(uv) => {
1505+
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
1506+
}
1507+
ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(wfcx.param_env),
1508+
};
1509+
1510+
let param_ty = tcx.type_of(param.def_id).instantiate_identity();
1511+
if !ct_ty.has_param() && !param_ty.has_param() {
1512+
let cause = traits::ObligationCause::new(
1513+
tcx.def_span(param.def_id),
1514+
wfcx.body_def_id,
1515+
ObligationCauseCode::WellFormed(None),
1516+
);
1517+
wfcx.register_obligation(Obligation::new(
1518+
tcx,
1519+
cause,
1520+
wfcx.param_env,
1521+
ty::ClauseKind::ConstArgHasType(ct, param_ty),
1522+
));
1523+
}
14911524
}
14921525
}
14931526
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)]
2+
//~^ WARN the feature `generic_const_parameter_types` is incomplete
3+
//~| WARN the feature `unsized_const_params` is incomplete
4+
// Make sure that we test the const param type of default const parameters
5+
// if both the type of the default and the type of the parameter are concrete.
6+
7+
use std::marker::ConstParamTy_;
8+
9+
struct Foo<const N: u32, const M: u64 = N>; //~ ERROR the constant `N` is not of type `u64`
10+
struct Bar<T: ConstParamTy_, const N: T, const M: u64 = N>(T); // ok
11+
struct Baz<T: ConstParamTy_, const N: u32, const M: T = N>(T); // ok
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes
2+
--> $DIR/concrete-const-param-type.rs:1:12
3+
|
4+
LL | #![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #137626 <https://github.com/rust-lang/rust/issues/137626> for more information
8+
= note: `#[warn(incomplete_features)]` on by default
9+
10+
warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
11+
--> $DIR/concrete-const-param-type.rs:1:43
12+
|
13+
LL | #![feature(generic_const_parameter_types, unsized_const_params, adt_const_params)]
14+
| ^^^^^^^^^^^^^^^^^^^^
15+
|
16+
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
17+
18+
error: the constant `N` is not of type `u64`
19+
--> $DIR/concrete-const-param-type.rs:9:26
20+
|
21+
LL | struct Foo<const N: u32, const M: u64 = N>;
22+
| ^^^^^^^^^^^^^^^^ expected `u64`, found `u32`
23+
24+
error: aborting due to 1 previous error; 2 warnings emitted
25+

0 commit comments

Comments
 (0)