Skip to content

Commit ac73a4a

Browse files
committed
Implement type_const impl validity check; fix bug in generics_of
1 parent cff04a7 commit ac73a4a

File tree

5 files changed

+88
-4
lines changed

5 files changed

+88
-4
lines changed

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_middle::ty::{
1818
TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast,
1919
};
2020
use rustc_middle::{bug, span_bug};
21-
use rustc_span::Span;
21+
use rustc_span::{Span, sym};
2222
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2323
use rustc_trait_selection::infer::InferCtxtExt;
2424
use rustc_trait_selection::regions::InferCtxtRegionExt;
@@ -46,7 +46,9 @@ pub(super) fn compare_impl_item(
4646
match impl_item.kind {
4747
ty::AssocKind::Fn => compare_impl_method(tcx, impl_item, trait_item, impl_trait_ref),
4848
ty::AssocKind::Type => compare_impl_ty(tcx, impl_item, trait_item, impl_trait_ref),
49-
ty::AssocKind::Const => compare_impl_const(tcx, impl_item, trait_item, impl_trait_ref),
49+
ty::AssocKind::Const => {
50+
compare_impl_const(tcx, impl_item_def_id, impl_item, trait_item, impl_trait_ref)
51+
}
5052
}
5153
}
5254

@@ -1769,14 +1771,59 @@ fn compare_generic_param_kinds<'tcx>(
17691771

17701772
fn compare_impl_const<'tcx>(
17711773
tcx: TyCtxt<'tcx>,
1774+
impl_item_def_id: LocalDefId,
17721775
impl_const_item: ty::AssocItem,
17731776
trait_const_item: ty::AssocItem,
17741777
impl_trait_ref: ty::TraitRef<'tcx>,
17751778
) -> Result<(), ErrorGuaranteed> {
17761779
compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
17771780
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
17781781
check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
1779-
compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
1782+
compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)?;
1783+
check_type_const_satisfied(tcx, impl_item_def_id, trait_const_item)
1784+
}
1785+
1786+
fn check_type_const_satisfied<'tcx>(
1787+
tcx: TyCtxt<'tcx>,
1788+
impl_item_def_id: LocalDefId,
1789+
trait_ct: ty::AssocItem,
1790+
) -> Result<(), ErrorGuaranteed> {
1791+
// Only need to check if mgca is enabled.
1792+
// Only need to check it if the trait const was actually marked with the attr.
1793+
if !tcx.features().min_generic_const_args() || !tcx.has_attr(trait_ct.def_id, sym::type_const) {
1794+
return Ok(());
1795+
}
1796+
1797+
let (_, ct_body, ct_arg) =
1798+
tcx.hir_node_by_def_id(impl_item_def_id).expect_impl_item().expect_const();
1799+
if let Some(ct_arg) = ct_arg {
1800+
match ct_arg {
1801+
hir::ConstArg { kind: hir::ConstArgKind::Path(..), .. } => return Ok(()),
1802+
_ => unreachable!("only const paths are created here currently"),
1803+
}
1804+
}
1805+
1806+
let body = tcx.hir_body(ct_body);
1807+
let hir::ExprKind::ConstBlock(ct_block) = body.value.kind else {
1808+
unreachable!("always lowered to const block")
1809+
};
1810+
let generics = tcx.generics_of(ct_block.def_id);
1811+
// FIXME(mgca): we exclude own params since they include synthetic params created for the const's type
1812+
// but are there cases where own params could exist that would be a problem?
1813+
if generics.parent_count == 0 {
1814+
return Ok(());
1815+
}
1816+
1817+
let mut diag = tcx.dcx().struct_span_err(
1818+
tcx.def_span(ct_block.def_id),
1819+
"assoc const body is not safe for type system usage",
1820+
);
1821+
diag.note(format!("the body uses generic parameters in nontrivial computations"));
1822+
diag.span_note(
1823+
tcx.def_span(trait_ct.def_id),
1824+
"the `#[type_const]` declaration in the trait required this",
1825+
);
1826+
Err(diag.emit())
17801827
}
17811828

17821829
/// The equivalent of [compare_method_predicate_entailment], but for associated constants

compiler/rustc_hir_analysis/src/collect/generics_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
204204
// HACK(mgca): we lower non-path const item bodies as const blocks
205205
// so we can control use of generics independently from the const item's type etc
206206
if tcx.features().min_generic_const_args()
207-
&& is_const_item(tcx.parent_hir_node(hir_id))
207+
&& is_const_item(tcx.parent_hir_node(tcx.parent_hir_id(hir_id)))
208208
&& !does_body_reference_generics(tcx, *body)
209209
{
210210
// If the body doesn't reference any generic params, we don't inherit from the parent.

tests/ui/const-generics/mgca/assoc-const.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ pub trait Tr<X> {
88
const SIZE: usize;
99
}
1010

11+
impl<X> Tr<X> for () {
12+
const SIZE: usize = 42;
13+
}
14+
1115
fn mk_array<T: Tr<bool>>(_x: T) -> [(); <T as Tr<bool>>::SIZE] {
1216
[(); T::SIZE]
1317
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(min_generic_const_args)]
2+
#![allow(incomplete_features)]
3+
4+
pub trait Tr<X> {
5+
#[type_const]
6+
const SIZE: usize;
7+
}
8+
9+
impl<X> Tr<X> for () {
10+
const SIZE: usize = 42;
11+
}
12+
13+
impl<const N: usize> Tr<[(); N]> for i32 {
14+
const SIZE: usize = 42 + N;
15+
//~^ ERROR assoc const body is not safe for type system usage
16+
}
17+
18+
fn main() {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: assoc const body is not safe for type system usage
2+
--> $DIR/bad-assoc-const.rs:14:25
3+
|
4+
LL | const SIZE: usize = 42 + N;
5+
| ^^^^^^
6+
|
7+
= note: the body uses generic parameters in nontrivial computations
8+
note: the `#[type_const]` declaration in the trait required this
9+
--> $DIR/bad-assoc-const.rs:6:5
10+
|
11+
LL | const SIZE: usize;
12+
| ^^^^^^^^^^^^^^^^^
13+
14+
error: aborting due to 1 previous error
15+

0 commit comments

Comments
 (0)