Skip to content

Commit 6b927d7

Browse files
committed
MGCA: require #[type_const] on free consts too
1 parent 035b01b commit 6b927d7

11 files changed

Lines changed: 97 additions & 50 deletions

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,14 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14221422
LowerTypeRelativePathMode::Const,
14231423
)? {
14241424
TypeRelativePath::AssocItem(def_id, args) => {
1425-
if !self.tcx().is_type_const(def_id) {
1426-
let mut err = self.dcx().struct_span_err(
1427-
span,
1428-
"use of trait associated const without `#[type_const]`",
1429-
);
1430-
err.note("the declaration in the trait must be marked with `#[type_const]`");
1431-
return Err(err.emit());
1432-
}
1425+
self.require_type_const_attribute(def_id, span)?;
14331426
let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args));
14341427
let ct = self.check_param_uses_if_mcg(ct, span, false);
14351428
Ok(ct)
@@ -1885,30 +1878,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
18851878
item_def_id: DefId,
18861879
trait_segment: Option<&hir::PathSegment<'tcx>>,
18871880
item_segment: &hir::PathSegment<'tcx>,
1888-
) -> Const<'tcx> {
1889-
match self.lower_resolved_assoc_item_path(
1881+
) -> Result<Const<'tcx>, ErrorGuaranteed> {
1882+
let (item_def_id, item_args) = self.lower_resolved_assoc_item_path(
18901883
span,
18911884
opt_self_ty,
18921885
item_def_id,
18931886
trait_segment,
18941887
item_segment,
18951888
ty::AssocTag::Const,
1896-
) {
1897-
Ok((item_def_id, item_args)) => {
1898-
if !self.tcx().is_type_const(item_def_id) {
1899-
let mut err = self.dcx().struct_span_err(
1900-
span,
1901-
"use of `const` in the type system without `#[type_const]`",
1902-
);
1903-
err.note("the declaration must be marked with `#[type_const]`");
1904-
return Const::new_error(self.tcx(), err.emit());
1905-
}
1906-
1907-
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
1908-
Const::new_unevaluated(self.tcx(), uv)
1909-
}
1910-
Err(guar) => Const::new_error(self.tcx(), guar),
1911-
}
1889+
)?;
1890+
self.require_type_const_attribute(item_def_id, span)?;
1891+
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
1892+
Ok(Const::new_unevaluated(self.tcx(), uv))
19121893
}
19131894

19141895
/// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path.
@@ -2668,6 +2649,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26682649
self.lower_const_param(def_id, hir_id)
26692650
}
26702651
Res::Def(DefKind::Const, did) => {
2652+
if let Err(guar) = self.require_type_const_attribute(did, span) {
2653+
return Const::new_error(self.tcx(), guar);
2654+
}
2655+
26712656
assert_eq!(opt_self_ty, None);
26722657
let [leading_segments @ .., segment] = path.segments else { bug!() };
26732658
let _ = self
@@ -2718,6 +2703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27182703
trait_segment,
27192704
path.segments.last().unwrap(),
27202705
)
2706+
.unwrap_or_else(|guar| Const::new_error(tcx, guar))
27212707
}
27222708
Res::Def(DefKind::Static { .. }, _) => {
27232709
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
@@ -2843,6 +2829,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
28432829
.map(|l| tcx.at(expr.span).lit_to_const(l))
28442830
}
28452831

2832+
fn require_type_const_attribute(
2833+
&self,
2834+
def_id: DefId,
2835+
span: Span,
2836+
) -> Result<(), ErrorGuaranteed> {
2837+
if self.tcx().is_type_const(def_id) {
2838+
Ok(())
2839+
} else {
2840+
let mut err = self
2841+
.dcx()
2842+
.struct_span_err(span, "use of `const` in the type system without `#[type_const]`");
2843+
err.span_note(
2844+
self.tcx().def_span(def_id),
2845+
"the declaration must be marked with `#[type_const]`",
2846+
);
2847+
Err(err.emit())
2848+
}
2849+
}
2850+
28462851
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
28472852
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
28482853
match idx {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![feature(min_generic_const_args)]
2+
#![allow(incomplete_features)]
3+
4+
#[type_const]
5+
pub const NON_LOCAL_CONST: char = 'a';
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// regression test for #133808.
2+
//@ aux-build:non_local_type_const.rs
23

34
#![feature(generic_const_exprs)]
45
#![feature(min_generic_const_args)]
56
#![allow(incomplete_features)]
67
#![crate_type = "lib"]
8+
extern crate non_local_type_const;
79

810
pub trait Foo {}
9-
impl Foo for [u8; std::path::MAIN_SEPARATOR] {}
10-
//~^ ERROR the constant `MAIN_SEPARATOR` is not of type `usize`
11+
impl Foo for [u8; non_local_type_const::NON_LOCAL_CONST] {}
12+
//~^ ERROR the constant `'a'` is not of type `usize`
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
error: the constant `MAIN_SEPARATOR` is not of type `usize`
2-
--> $DIR/non-local-const.rs:9:14
1+
error: the constant `'a'` is not of type `usize`
2+
--> $DIR/non-local-const.rs:11:14
33
|
4-
LL | impl Foo for [u8; std::path::MAIN_SEPARATOR] {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `char`
4+
LL | impl Foo for [u8; non_local_type_const::NON_LOCAL_CONST] {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `char`
66
|
7-
= note: the length of array `[u8; MAIN_SEPARATOR]` must be type `usize`
7+
= note: the length of array `[u8; 'a']` must be type `usize`
88

99
error: aborting due to 1 previous error
1010

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
1-
error: use of trait associated const without `#[type_const]`
1+
error: use of `const` in the type system without `#[type_const]`
22
--> $DIR/assoc-const-without-type_const.rs:8:35
33
|
44
LL | fn mk_array<T: Tr>(_x: T) -> [(); T::SIZE] {
55
| ^^^^^^^
66
|
7-
= note: the declaration in the trait must be marked with `#[type_const]`
7+
note: the declaration must be marked with `#[type_const]`
8+
--> $DIR/assoc-const-without-type_const.rs:5:5
9+
|
10+
LL | const SIZE: usize;
11+
| ^^^^^^^^^^^^^^^^^
812

9-
error: use of trait associated const without `#[type_const]`
13+
error: use of `const` in the type system without `#[type_const]`
1014
--> $DIR/assoc-const-without-type_const.rs:10:10
1115
|
1216
LL | [(); T::SIZE]
1317
| ^^^^^^^
1418
|
15-
= note: the declaration in the trait must be marked with `#[type_const]`
19+
note: the declaration must be marked with `#[type_const]`
20+
--> $DIR/assoc-const-without-type_const.rs:5:5
21+
|
22+
LL | const SIZE: usize;
23+
| ^^^^^^^^^^^^^^^^^
1624

1725
error: aborting due to 2 previous errors
1826

tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![expect(incomplete_features)]
44
#![feature(min_generic_const_args)]
55

6+
#[type_const]
67
const C: usize = 0;
78
pub struct A<const M: usize> {}
89
impl A<C> {

tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0107]: missing generics for struct `A`
2-
--> $DIR/const-arg-coherence-conflicting-methods.rs:12:6
2+
--> $DIR/const-arg-coherence-conflicting-methods.rs:13:6
33
|
44
LL | impl A {
55
| ^ expected 1 generic argument
66
|
77
note: struct defined here, with 1 generic parameter: `M`
8-
--> $DIR/const-arg-coherence-conflicting-methods.rs:7:12
8+
--> $DIR/const-arg-coherence-conflicting-methods.rs:8:12
99
|
1010
LL | pub struct A<const M: usize> {}
1111
| ^ --------------
@@ -15,7 +15,7 @@ LL | impl A<M> {
1515
| +++
1616

1717
error[E0592]: duplicate definitions with name `fun1`
18-
--> $DIR/const-arg-coherence-conflicting-methods.rs:9:5
18+
--> $DIR/const-arg-coherence-conflicting-methods.rs:10:5
1919
|
2020
LL | fn fun1() {}
2121
| ^^^^^^^^^ duplicate definitions for `fun1`

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ enum MyEnum<T> {
1212
Unit,
1313
}
1414

15+
#[type_const]
1516
const CONST_ITEM: u32 = 42;
1617

1718
fn accepts_point<const P: Point>() {}

tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0425]: cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope
2-
--> $DIR/tuple_ctor_erroneous.rs:29:23
2+
--> $DIR/tuple_ctor_erroneous.rs:30:23
33
|
44
LL | accepts_point::<{ UnresolvedIdent(N, N) }>();
55
| ^^^^^^^^^^^^^^^ not found in this scope
@@ -10,55 +10,55 @@ LL | fn test_errors<const N: usize, const UnresolvedIdent: /* Type */>() {
1010
| +++++++++++++++++++++++++++++++++++
1111

1212
error: tuple constructor has 2 arguments but 1 were provided
13-
--> $DIR/tuple_ctor_erroneous.rs:23:23
13+
--> $DIR/tuple_ctor_erroneous.rs:24:23
1414
|
1515
LL | accepts_point::<{ Point(N) }>();
1616
| ^^^^^^^^
1717

1818
error: tuple constructor has 2 arguments but 3 were provided
19-
--> $DIR/tuple_ctor_erroneous.rs:26:23
19+
--> $DIR/tuple_ctor_erroneous.rs:27:23
2020
|
2121
LL | accepts_point::<{ Point(N, N, N) }>();
2222
| ^^^^^^^^^^^^^^
2323

2424
error: tuple constructor with invalid base path
25-
--> $DIR/tuple_ctor_erroneous.rs:29:23
25+
--> $DIR/tuple_ctor_erroneous.rs:30:23
2626
|
2727
LL | accepts_point::<{ UnresolvedIdent(N, N) }>();
2828
| ^^^^^^^^^^^^^^^^^^^^^
2929

3030
error: tuple constructor with invalid base path
31-
--> $DIR/tuple_ctor_erroneous.rs:33:23
31+
--> $DIR/tuple_ctor_erroneous.rs:34:23
3232
|
3333
LL | accepts_point::<{ non_ctor(N, N) }>();
3434
| ^^^^^^^^^^^^^^
3535

3636
error: tuple constructor with invalid base path
37-
--> $DIR/tuple_ctor_erroneous.rs:36:23
37+
--> $DIR/tuple_ctor_erroneous.rs:37:23
3838
|
3939
LL | accepts_point::<{ CONST_ITEM(N, N) }>();
4040
| ^^^^^^^^^^^^^^^^
4141

4242
error: the constant `Point` is not of type `Point`
43-
--> $DIR/tuple_ctor_erroneous.rs:39:23
43+
--> $DIR/tuple_ctor_erroneous.rs:40:23
4444
|
4545
LL | accepts_point::<{ Point }>();
4646
| ^^^^^ expected `Point`, found struct constructor
4747
|
4848
note: required by a const generic parameter in `accepts_point`
49-
--> $DIR/tuple_ctor_erroneous.rs:17:18
49+
--> $DIR/tuple_ctor_erroneous.rs:18:18
5050
|
5151
LL | fn accepts_point<const P: Point>() {}
5252
| ^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_point`
5353

5454
error: the constant `MyEnum::<u32>::Variant` is not of type `MyEnum<u32>`
55-
--> $DIR/tuple_ctor_erroneous.rs:42:22
55+
--> $DIR/tuple_ctor_erroneous.rs:43:22
5656
|
5757
LL | accepts_enum::<{ MyEnum::Variant::<u32> }>();
5858
| ^^^^^^^^^^^^^^^^^^^^^^ expected `MyEnum<u32>`, found enum constructor
5959
|
6060
note: required by a const generic parameter in `accepts_enum`
61-
--> $DIR/tuple_ctor_erroneous.rs:18:17
61+
--> $DIR/tuple_ctor_erroneous.rs:19:17
6262
|
6363
LL | fn accepts_enum<const E: MyEnum<u32>>() {}
6464
| ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_enum`
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// regression test, used to ICE
2+
3+
#![feature(min_generic_const_args)]
4+
#![allow(incomplete_features)]
5+
6+
const N: usize = 4;
7+
8+
fn main() {
9+
let x = [(); N];
10+
//~^ ERROR use of `const` in the type system without `#[type_const]`
11+
}

0 commit comments

Comments
 (0)