MGCA: require #[type_const] on free consts too
This commit is contained in:
parent
035b01b794
commit
e6f5b97152
14 changed files with 125 additions and 50 deletions
|
|
@ -1422,14 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
LowerTypeRelativePathMode::Const,
|
||||
)? {
|
||||
TypeRelativePath::AssocItem(def_id, args) => {
|
||||
if !self.tcx().is_type_const(def_id) {
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
span,
|
||||
"use of trait associated const without `#[type_const]`",
|
||||
);
|
||||
err.note("the declaration in the trait must be marked with `#[type_const]`");
|
||||
return Err(err.emit());
|
||||
}
|
||||
self.require_type_const_attribute(def_id, span)?;
|
||||
let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args));
|
||||
let ct = self.check_param_uses_if_mcg(ct, span, false);
|
||||
Ok(ct)
|
||||
|
|
@ -1885,30 +1878,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
item_def_id: DefId,
|
||||
trait_segment: Option<&hir::PathSegment<'tcx>>,
|
||||
item_segment: &hir::PathSegment<'tcx>,
|
||||
) -> Const<'tcx> {
|
||||
match self.lower_resolved_assoc_item_path(
|
||||
) -> Result<Const<'tcx>, ErrorGuaranteed> {
|
||||
let (item_def_id, item_args) = self.lower_resolved_assoc_item_path(
|
||||
span,
|
||||
opt_self_ty,
|
||||
item_def_id,
|
||||
trait_segment,
|
||||
item_segment,
|
||||
ty::AssocTag::Const,
|
||||
) {
|
||||
Ok((item_def_id, item_args)) => {
|
||||
if !self.tcx().is_type_const(item_def_id) {
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
span,
|
||||
"use of `const` in the type system without `#[type_const]`",
|
||||
);
|
||||
err.note("the declaration must be marked with `#[type_const]`");
|
||||
return Const::new_error(self.tcx(), err.emit());
|
||||
}
|
||||
|
||||
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
|
||||
Const::new_unevaluated(self.tcx(), uv)
|
||||
}
|
||||
Err(guar) => Const::new_error(self.tcx(), guar),
|
||||
}
|
||||
)?;
|
||||
self.require_type_const_attribute(item_def_id, span)?;
|
||||
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
|
||||
Ok(Const::new_unevaluated(self.tcx(), uv))
|
||||
}
|
||||
|
||||
/// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path.
|
||||
|
|
@ -2668,6 +2649,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self.lower_const_param(def_id, hir_id)
|
||||
}
|
||||
Res::Def(DefKind::Const, did) => {
|
||||
if let Err(guar) = self.require_type_const_attribute(did, span) {
|
||||
return Const::new_error(self.tcx(), guar);
|
||||
}
|
||||
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let [leading_segments @ .., segment] = path.segments else { bug!() };
|
||||
let _ = self
|
||||
|
|
@ -2718,6 +2703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
trait_segment,
|
||||
path.segments.last().unwrap(),
|
||||
)
|
||||
.unwrap_or_else(|guar| Const::new_error(tcx, guar))
|
||||
}
|
||||
Res::Def(DefKind::Static { .. }, _) => {
|
||||
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
|
||||
|
|
@ -2843,6 +2829,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
.map(|l| tcx.at(expr.span).lit_to_const(l))
|
||||
}
|
||||
|
||||
fn require_type_const_attribute(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = self.tcx();
|
||||
if tcx.is_type_const(def_id) {
|
||||
Ok(())
|
||||
} else {
|
||||
let mut err = self
|
||||
.dcx()
|
||||
.struct_span_err(span, "use of `const` in the type system without `#[type_const]`");
|
||||
if def_id.is_local() {
|
||||
let name = tcx.def_path_str(def_id);
|
||||
err.span_suggestion(
|
||||
tcx.def_span(def_id).shrink_to_lo(),
|
||||
format!("add `#[type_const]` attribute to `{name}`"),
|
||||
format!("#[type_const]\n"),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.note("only consts marked with `#[type_const]` may be used in types");
|
||||
}
|
||||
Err(err.emit())
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
|
||||
let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
|
||||
match idx {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
#![feature(min_generic_const_args)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#[type_const]
|
||||
pub const NON_LOCAL_CONST: char = 'a';
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
// regression test for #133808.
|
||||
//@ aux-build:non_local_type_const.rs
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![feature(min_generic_const_args)]
|
||||
#![allow(incomplete_features)]
|
||||
#![crate_type = "lib"]
|
||||
extern crate non_local_type_const;
|
||||
|
||||
pub trait Foo {}
|
||||
impl Foo for [u8; std::path::MAIN_SEPARATOR] {}
|
||||
//~^ ERROR the constant `MAIN_SEPARATOR` is not of type `usize`
|
||||
impl Foo for [u8; non_local_type_const::NON_LOCAL_CONST] {}
|
||||
//~^ ERROR the constant `'a'` is not of type `usize`
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
error: the constant `MAIN_SEPARATOR` is not of type `usize`
|
||||
--> $DIR/non-local-const.rs:9:14
|
||||
error: the constant `'a'` is not of type `usize`
|
||||
--> $DIR/non-local-const.rs:11:14
|
||||
|
|
||||
LL | impl Foo for [u8; std::path::MAIN_SEPARATOR] {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `char`
|
||||
LL | impl Foo for [u8; non_local_type_const::NON_LOCAL_CONST] {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `char`
|
||||
|
|
||||
= note: the length of array `[u8; MAIN_SEPARATOR]` must be type `usize`
|
||||
= note: the length of array `[u8; 'a']` must be type `usize`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,26 @@
|
|||
error: use of trait associated const without `#[type_const]`
|
||||
error: use of `const` in the type system without `#[type_const]`
|
||||
--> $DIR/assoc-const-without-type_const.rs:8:35
|
||||
|
|
||||
LL | fn mk_array<T: Tr>(_x: T) -> [(); T::SIZE] {
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: the declaration in the trait must be marked with `#[type_const]`
|
||||
help: add `#[type_const]` attribute to `Tr::SIZE`
|
||||
|
|
||||
LL + #[type_const]
|
||||
LL | const SIZE: usize;
|
||||
|
|
||||
|
||||
error: use of trait associated const without `#[type_const]`
|
||||
error: use of `const` in the type system without `#[type_const]`
|
||||
--> $DIR/assoc-const-without-type_const.rs:10:10
|
||||
|
|
||||
LL | [(); T::SIZE]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: the declaration in the trait must be marked with `#[type_const]`
|
||||
help: add `#[type_const]` attribute to `Tr::SIZE`
|
||||
|
|
||||
LL + #[type_const]
|
||||
LL | const SIZE: usize;
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
pub const N: usize = 2;
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#![expect(incomplete_features)]
|
||||
#![feature(min_generic_const_args)]
|
||||
|
||||
#[type_const]
|
||||
const C: usize = 0;
|
||||
pub struct A<const M: usize> {}
|
||||
impl A<C> {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error[E0107]: missing generics for struct `A`
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:12:6
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:13:6
|
||||
|
|
||||
LL | impl A {
|
||||
| ^ expected 1 generic argument
|
||||
|
|
||||
note: struct defined here, with 1 generic parameter: `M`
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:7:12
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:8:12
|
||||
|
|
||||
LL | pub struct A<const M: usize> {}
|
||||
| ^ --------------
|
||||
|
|
@ -15,7 +15,7 @@ LL | impl A<M> {
|
|||
| +++
|
||||
|
||||
error[E0592]: duplicate definitions with name `fun1`
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:9:5
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:10:5
|
||||
|
|
||||
LL | fn fun1() {}
|
||||
| ^^^^^^^^^ duplicate definitions for `fun1`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
// Just a test of the error message (it's different for non-local consts)
|
||||
//@ aux-build:non_local_const.rs
|
||||
#![feature(min_generic_const_args)]
|
||||
#![allow(incomplete_features)]
|
||||
extern crate non_local_const;
|
||||
fn main() {
|
||||
let x = [(); non_local_const::N];
|
||||
//~^ ERROR use of `const` in the type system without `#[type_const]`
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
error: use of `const` in the type system without `#[type_const]`
|
||||
--> $DIR/non-local-const-without-type_const.rs:7:18
|
||||
|
|
||||
LL | let x = [(); non_local_const::N];
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: only consts marked with `#[type_const]` may be used in types
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -12,6 +12,7 @@ enum MyEnum<T> {
|
|||
Unit,
|
||||
}
|
||||
|
||||
#[type_const]
|
||||
const CONST_ITEM: u32 = 42;
|
||||
|
||||
fn accepts_point<const P: Point>() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0425]: cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope
|
||||
--> $DIR/tuple_ctor_erroneous.rs:29:23
|
||||
--> $DIR/tuple_ctor_erroneous.rs:30:23
|
||||
|
|
||||
LL | accepts_point::<{ UnresolvedIdent(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^^ not found in this scope
|
||||
|
|
@ -10,55 +10,55 @@ LL | fn test_errors<const N: usize, const UnresolvedIdent: /* Type */>() {
|
|||
| +++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: tuple constructor has 2 arguments but 1 were provided
|
||||
--> $DIR/tuple_ctor_erroneous.rs:23:23
|
||||
--> $DIR/tuple_ctor_erroneous.rs:24:23
|
||||
|
|
||||
LL | accepts_point::<{ Point(N) }>();
|
||||
| ^^^^^^^^
|
||||
|
||||
error: tuple constructor has 2 arguments but 3 were provided
|
||||
--> $DIR/tuple_ctor_erroneous.rs:26:23
|
||||
--> $DIR/tuple_ctor_erroneous.rs:27:23
|
||||
|
|
||||
LL | accepts_point::<{ Point(N, N, N) }>();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: tuple constructor with invalid base path
|
||||
--> $DIR/tuple_ctor_erroneous.rs:29:23
|
||||
--> $DIR/tuple_ctor_erroneous.rs:30:23
|
||||
|
|
||||
LL | accepts_point::<{ UnresolvedIdent(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: tuple constructor with invalid base path
|
||||
--> $DIR/tuple_ctor_erroneous.rs:33:23
|
||||
--> $DIR/tuple_ctor_erroneous.rs:34:23
|
||||
|
|
||||
LL | accepts_point::<{ non_ctor(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: tuple constructor with invalid base path
|
||||
--> $DIR/tuple_ctor_erroneous.rs:36:23
|
||||
--> $DIR/tuple_ctor_erroneous.rs:37:23
|
||||
|
|
||||
LL | accepts_point::<{ CONST_ITEM(N, N) }>();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: the constant `Point` is not of type `Point`
|
||||
--> $DIR/tuple_ctor_erroneous.rs:39:23
|
||||
--> $DIR/tuple_ctor_erroneous.rs:40:23
|
||||
|
|
||||
LL | accepts_point::<{ Point }>();
|
||||
| ^^^^^ expected `Point`, found struct constructor
|
||||
|
|
||||
note: required by a const generic parameter in `accepts_point`
|
||||
--> $DIR/tuple_ctor_erroneous.rs:17:18
|
||||
--> $DIR/tuple_ctor_erroneous.rs:18:18
|
||||
|
|
||||
LL | fn accepts_point<const P: Point>() {}
|
||||
| ^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_point`
|
||||
|
||||
error: the constant `MyEnum::<u32>::Variant` is not of type `MyEnum<u32>`
|
||||
--> $DIR/tuple_ctor_erroneous.rs:42:22
|
||||
--> $DIR/tuple_ctor_erroneous.rs:43:22
|
||||
|
|
||||
LL | accepts_enum::<{ MyEnum::Variant::<u32> }>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ expected `MyEnum<u32>`, found enum constructor
|
||||
|
|
||||
note: required by a const generic parameter in `accepts_enum`
|
||||
--> $DIR/tuple_ctor_erroneous.rs:18:17
|
||||
--> $DIR/tuple_ctor_erroneous.rs:19:17
|
||||
|
|
||||
LL | fn accepts_enum<const E: MyEnum<u32>>() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_enum`
|
||||
|
|
|
|||
11
tests/ui/const-generics/mgca/unmarked-free-const.rs
Normal file
11
tests/ui/const-generics/mgca/unmarked-free-const.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// regression test, used to ICE
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
const N: usize = 4;
|
||||
|
||||
fn main() {
|
||||
let x = [(); N];
|
||||
//~^ ERROR use of `const` in the type system without `#[type_const]`
|
||||
}
|
||||
14
tests/ui/const-generics/mgca/unmarked-free-const.stderr
Normal file
14
tests/ui/const-generics/mgca/unmarked-free-const.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: use of `const` in the type system without `#[type_const]`
|
||||
--> $DIR/unmarked-free-const.rs:9:18
|
||||
|
|
||||
LL | let x = [(); N];
|
||||
| ^
|
||||
|
|
||||
help: add `#[type_const]` attribute to `N`
|
||||
|
|
||||
LL + #[type_const]
|
||||
LL | const N: usize = 4;
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue