Check that impls of #[type_const] consts also have the attr
This commit is contained in:
parent
9ba89327df
commit
db2fbdb714
8 changed files with 105 additions and 28 deletions
|
|
@ -6,9 +6,10 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId};
|
|||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::VisitorExt;
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit};
|
||||
use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
|
|
@ -1984,12 +1985,46 @@ fn compare_impl_const<'tcx>(
|
|||
trait_const_item: ty::AssocItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
compare_type_const(tcx, impl_const_item, trait_const_item)?;
|
||||
compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
|
||||
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
|
||||
check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
|
||||
compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
|
||||
}
|
||||
|
||||
fn compare_type_const<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_const_item: ty::AssocItem,
|
||||
trait_const_item: ty::AssocItem,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let impl_is_type_const =
|
||||
find_attr!(tcx.get_all_attrs(impl_const_item.def_id), AttributeKind::TypeConst(_));
|
||||
let trait_type_const_span = find_attr!(
|
||||
tcx.get_all_attrs(trait_const_item.def_id),
|
||||
AttributeKind::TypeConst(sp) => *sp
|
||||
);
|
||||
|
||||
if let Some(trait_type_const_span) = trait_type_const_span
|
||||
&& !impl_is_type_const
|
||||
{
|
||||
return Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
tcx.def_span(impl_const_item.def_id),
|
||||
"implementation of `#[type_const]` const must be marked with `#[type_const]`",
|
||||
)
|
||||
.with_span_note(
|
||||
MultiSpan::from_spans(vec![
|
||||
tcx.def_span(trait_const_item.def_id),
|
||||
trait_type_const_span,
|
||||
]),
|
||||
"trait declaration of const is marked with `#[type_const]`",
|
||||
)
|
||||
.emit());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The equivalent of [compare_method_predicate_entailment], but for associated constants
|
||||
/// instead of associated functions.
|
||||
// FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
|
||||
|
|
|
|||
|
|
@ -1600,8 +1600,12 @@ fn const_of_item<'tcx>(
|
|||
};
|
||||
let ct_arg = match ct_rhs {
|
||||
hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
|
||||
hir::ConstItemRhs::Body(body_id) => {
|
||||
bug!("cannot call const_of_item on a non-type_const {body_id:?}")
|
||||
hir::ConstItemRhs::Body(_) => {
|
||||
let e = tcx.dcx().span_delayed_bug(
|
||||
tcx.def_span(def_id),
|
||||
"cannot call const_of_item on a non-type_const",
|
||||
);
|
||||
return ty::EarlyBinder::bind(Const::new_error(tcx, e));
|
||||
}
|
||||
};
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
//@ known-bug: #140729
|
||||
#![feature(min_generic_const_args)]
|
||||
|
||||
const C: usize = 0;
|
||||
pub struct A<const M: usize> {}
|
||||
impl A<C> {
|
||||
fn fun1() {}
|
||||
}
|
||||
impl A {
|
||||
fn fun1() {}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
//@ known-bug: #140860
|
||||
#![feature(min_generic_const_args)]
|
||||
#![feature(unsized_const_params)]
|
||||
#![feature(with_negative_coherence, negative_impls)]
|
||||
trait a < const b : &'static str> {} trait c {} struct d< e >(e);
|
||||
impl<e> c for e where e: a<""> {}
|
||||
impl<e> c for d<e> {}
|
||||
impl<e> !a<f> for e {}
|
||||
const f : &str = "";
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Regression test for #140729
|
||||
|
||||
#![expect(incomplete_features)]
|
||||
#![feature(min_generic_const_args)]
|
||||
|
||||
const C: usize = 0;
|
||||
pub struct A<const M: usize> {}
|
||||
impl A<C> {
|
||||
fn fun1() {}
|
||||
//~^ ERROR duplicate definitions with name `fun1`
|
||||
}
|
||||
impl A {
|
||||
//~^ ERROR missing generics for struct `A`
|
||||
fn fun1() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
error[E0107]: missing generics for struct `A`
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:12: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
|
||||
|
|
||||
LL | pub struct A<const M: usize> {}
|
||||
| ^ --------------
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | impl A<M> {
|
||||
| +++
|
||||
|
||||
error[E0592]: duplicate definitions with name `fun1`
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:9:5
|
||||
|
|
||||
LL | fn fun1() {}
|
||||
| ^^^^^^^^^ duplicate definitions for `fun1`
|
||||
...
|
||||
LL | fn fun1() {}
|
||||
| --------- other definition for `fun1`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0592.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
//@ known-bug: #132980
|
||||
// Move this test to tests/ui/const-generics/mgca/type_const-only-in-trait.rs
|
||||
// once fixed.
|
||||
|
||||
#![expect(incomplete_features)]
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
|
||||
|
|
@ -14,6 +10,7 @@ struct BadS;
|
|||
|
||||
impl GoodTr for BadS {
|
||||
const NUM: usize = 42;
|
||||
//~^ ERROR implementation of `#[type_const]` const must be marked with `#[type_const]`
|
||||
}
|
||||
|
||||
fn accept_good_tr<const N: usize, T: GoodTr<NUM = { N }>>(_x: &T) {}
|
||||
16
tests/ui/const-generics/mgca/type_const-only-in-trait.stderr
Normal file
16
tests/ui/const-generics/mgca/type_const-only-in-trait.stderr
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
error: implementation of `#[type_const]` const must be marked with `#[type_const]`
|
||||
--> $DIR/type_const-only-in-trait.rs:12:5
|
||||
|
|
||||
LL | const NUM: usize = 42;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: trait declaration of const is marked with `#[type_const]`
|
||||
--> $DIR/type_const-only-in-trait.rs:5:5
|
||||
|
|
||||
LL | #[type_const]
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | const NUM: usize;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue