Skip to content

Commit aa4441e

Browse files
committed
MGCA: require #[type_const] on free consts too
1 parent 8bccf12 commit aa4441e

11 files changed

Lines changed: 98 additions & 52 deletions

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,9 @@ use rustc_errors::codes::*;
2828
use rustc_errors::{
2929
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err,
3030
};
31-
use rustc_hir::attrs::AttributeKind;
3231
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
3332
use rustc_hir::def_id::{DefId, LocalDefId};
34-
use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId, find_attr};
33+
use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
3534
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
3635
use rustc_infer::traits::DynCompatibilityViolation;
3736
use rustc_macros::{TypeFoldable, TypeVisitable};
@@ -1423,14 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
14231422
LowerTypeRelativePathMode::Const,
14241423
)? {
14251424
TypeRelativePath::AssocItem(def_id, args) => {
1426-
if !find_attr!(self.tcx().get_all_attrs(def_id), AttributeKind::TypeConst(_)) {
1427-
let mut err = self.dcx().struct_span_err(
1428-
span,
1429-
"use of trait associated const without `#[type_const]`",
1430-
);
1431-
err.note("the declaration in the trait must be marked with `#[type_const]`");
1432-
return Err(err.emit());
1433-
}
1425+
self.require_type_const_attribute(def_id, span)?;
14341426
let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args));
14351427
let ct = self.check_param_uses_if_mcg(ct, span, false);
14361428
Ok(ct)
@@ -1886,30 +1878,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
18861878
item_def_id: DefId,
18871879
trait_segment: Option<&hir::PathSegment<'tcx>>,
18881880
item_segment: &hir::PathSegment<'tcx>,
1889-
) -> Const<'tcx> {
1890-
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(
18911883
span,
18921884
opt_self_ty,
18931885
item_def_id,
18941886
trait_segment,
18951887
item_segment,
18961888
ty::AssocTag::Const,
1897-
) {
1898-
Ok((item_def_id, item_args)) => {
1899-
if !find_attr!(self.tcx().get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) {
1900-
let mut err = self.dcx().struct_span_err(
1901-
span,
1902-
"use of `const` in the type system without `#[type_const]`",
1903-
);
1904-
err.note("the declaration must be marked with `#[type_const]`");
1905-
return Const::new_error(self.tcx(), err.emit());
1906-
}
1907-
1908-
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
1909-
Const::new_unevaluated(self.tcx(), uv)
1910-
}
1911-
Err(guar) => Const::new_error(self.tcx(), guar),
1912-
}
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))
19131893
}
19141894

19151895
/// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path.
@@ -2669,6 +2649,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
26692649
self.lower_const_param(def_id, hir_id)
26702650
}
26712651
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+
26722656
assert_eq!(opt_self_ty, None);
26732657
let [leading_segments @ .., segment] = path.segments else { bug!() };
26742658
let _ = self
@@ -2719,6 +2703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27192703
trait_segment,
27202704
path.segments.last().unwrap(),
27212705
)
2706+
.unwrap_or_else(|guar| Const::new_error(tcx, guar))
27222707
}
27232708
Res::Def(DefKind::Static { .. }, _) => {
27242709
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
@@ -2844,6 +2829,25 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
28442829
.map(|l| tcx.at(expr.span).lit_to_const(l))
28452830
}
28462831

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+
28472851
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
28482852
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
28492853
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)