Skip to content

Commit 496145b

Browse files
committed
Auto merge of #139646 - lcnr:default-is-fully-concrete, r=BoxyUwU
check types of const param defaults fixes #139643 by checking that the type of a const parameter default matches the type of the parameter as long as both types are fully concrete r? `@BoxyUwU`
2 parents 43e62a7 + 8cd12bf commit 496145b

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
@@ -1483,6 +1483,39 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
14831483
.then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
14841484
default.as_term().unwrap(),
14851485
);
1486+
} else {
1487+
// If we've got a generic const parameter we still want to check its
1488+
// type is correct in case both it and the param type are fully concrete.
1489+
let GenericArgKind::Const(ct) = default.unpack() else {
1490+
continue;
1491+
};
1492+
1493+
let ct_ty = match ct.kind() {
1494+
ty::ConstKind::Infer(_)
1495+
| ty::ConstKind::Placeholder(_)
1496+
| ty::ConstKind::Bound(_, _) => unreachable!(),
1497+
ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue,
1498+
ty::ConstKind::Value(cv) => cv.ty,
1499+
ty::ConstKind::Unevaluated(uv) => {
1500+
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args)
1501+
}
1502+
ty::ConstKind::Param(param_ct) => param_ct.find_ty_from_env(wfcx.param_env),
1503+
};
1504+
1505+
let param_ty = tcx.type_of(param.def_id).instantiate_identity();
1506+
if !ct_ty.has_param() && !param_ty.has_param() {
1507+
let cause = traits::ObligationCause::new(
1508+
tcx.def_span(param.def_id),
1509+
wfcx.body_def_id,
1510+
ObligationCauseCode::WellFormed(None),
1511+
);
1512+
wfcx.register_obligation(Obligation::new(
1513+
tcx,
1514+
cause,
1515+
wfcx.param_env,
1516+
ty::ClauseKind::ConstArgHasType(ct, param_ty),
1517+
));
1518+
}
14861519
}
14871520
}
14881521
}
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)