Rollup merge of #99651 - compiler-errors:fn-and-raw-ptr-in-const-generics, r=oli-obk
Deeply deny fn and raw ptrs in const generics I think this is right -- just because we wrap a fn ptr in a wrapper type does not mean we should allow it in a const parameter. We now reject both of these in the same way: ``` #![feature(adt_const_params)] #[derive(Eq, PartialEq)] struct Wrapper(); fn foo<const W: Wrapper>() {} fn foo2<const F: fn()>() {} ``` This does regress one test (`src/test/ui/consts/refs_check_const_eq-issue-88384.stderr`), but I'm not sure it should've passed in the first place. cc: ``@b-naber`` who introduced that test^ fixes #99641
This commit is contained in:
commit
9e7b7d5e1c
18 changed files with 193 additions and 139 deletions
|
@ -226,7 +226,7 @@ impl Qualif for CustomEq {
|
||||||
// because that component may be part of an enum variant (e.g.,
|
// because that component may be part of an enum variant (e.g.,
|
||||||
// `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
|
// `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
|
||||||
// structural-match (`Option::None`).
|
// structural-match (`Option::None`).
|
||||||
traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty, true).is_some()
|
traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_adt_inherently<'tcx>(
|
fn in_adt_inherently<'tcx>(
|
||||||
|
|
|
@ -203,7 +203,7 @@ impl<'tcx> Const<'tcx> {
|
||||||
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
|
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
ty::ConstKind::Value(valtree) => valtree,
|
ty::ConstKind::Value(valtree) => valtree,
|
||||||
_ => bug!("expected ConstKind::Value"),
|
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,37 +120,35 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
|
fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
|
||||||
traits::search_for_structural_match_violation(self.span, self.tcx(), ty, true).map(
|
traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
|
||||||
|non_sm_ty| {
|
with_no_trimmed_paths!(match non_sm_ty.kind() {
|
||||||
with_no_trimmed_paths!(match non_sm_ty.kind {
|
ty::Adt(adt, _) => self.adt_derive_msg(*adt),
|
||||||
traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
|
ty::Dynamic(..) => {
|
||||||
traits::NonStructuralMatchTyKind::Dynamic => {
|
"trait objects cannot be used in patterns".to_string()
|
||||||
"trait objects cannot be used in patterns".to_string()
|
}
|
||||||
}
|
ty::Opaque(..) => {
|
||||||
traits::NonStructuralMatchTyKind::Opaque => {
|
"opaque types cannot be used in patterns".to_string()
|
||||||
"opaque types cannot be used in patterns".to_string()
|
}
|
||||||
}
|
ty::Closure(..) => {
|
||||||
traits::NonStructuralMatchTyKind::Closure => {
|
"closures cannot be used in patterns".to_string()
|
||||||
"closures cannot be used in patterns".to_string()
|
}
|
||||||
}
|
ty::Generator(..) | ty::GeneratorWitness(..) => {
|
||||||
traits::NonStructuralMatchTyKind::Generator => {
|
"generators cannot be used in patterns".to_string()
|
||||||
"generators cannot be used in patterns".to_string()
|
}
|
||||||
}
|
ty::Float(..) => {
|
||||||
traits::NonStructuralMatchTyKind::Float => {
|
"floating-point numbers cannot be used in patterns".to_string()
|
||||||
"floating-point numbers cannot be used in patterns".to_string()
|
}
|
||||||
}
|
ty::FnPtr(..) => {
|
||||||
traits::NonStructuralMatchTyKind::Param => {
|
"function pointers cannot be used in patterns".to_string()
|
||||||
bug!("use of a constant whose type is a parameter inside a pattern")
|
}
|
||||||
}
|
ty::RawPtr(..) => {
|
||||||
traits::NonStructuralMatchTyKind::Projection => {
|
"raw pointers cannot be used in patterns".to_string()
|
||||||
bug!("use of a constant whose type is a projection inside a pattern")
|
}
|
||||||
}
|
_ => {
|
||||||
traits::NonStructuralMatchTyKind::Foreign => {
|
bug!("use of a value of `{non_sm_ty}` inside a pattern")
|
||||||
bug!("use of a value of a foreign type inside a pattern")
|
}
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
|
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
|
||||||
|
|
|
@ -60,8 +60,9 @@ pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError
|
||||||
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
|
pub use self::specialize::specialization_graph::FutureCompatOverlapError;
|
||||||
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
|
pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
|
||||||
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
|
pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
|
||||||
pub use self::structural_match::search_for_structural_match_violation;
|
pub use self::structural_match::{
|
||||||
pub use self::structural_match::{NonStructuralMatchTy, NonStructuralMatchTyKind};
|
search_for_adt_const_param_violation, search_for_structural_match_violation,
|
||||||
|
};
|
||||||
pub use self::util::{
|
pub use self::util::{
|
||||||
elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span,
|
elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span,
|
||||||
elaborate_trait_ref, elaborate_trait_refs,
|
elaborate_trait_ref, elaborate_trait_refs,
|
||||||
|
|
|
@ -6,29 +6,10 @@ use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NonStructuralMatchTy<'tcx> {
|
|
||||||
pub ty: Ty<'tcx>,
|
|
||||||
pub kind: NonStructuralMatchTyKind<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum NonStructuralMatchTyKind<'tcx> {
|
|
||||||
Adt(AdtDef<'tcx>),
|
|
||||||
Param,
|
|
||||||
Dynamic,
|
|
||||||
Foreign,
|
|
||||||
Opaque,
|
|
||||||
Closure,
|
|
||||||
Generator,
|
|
||||||
Projection,
|
|
||||||
Float,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This method traverses the structure of `ty`, trying to find an
|
/// This method traverses the structure of `ty`, trying to find an
|
||||||
/// instance of an ADT (i.e. struct or enum) that doesn't implement
|
/// instance of an ADT (i.e. struct or enum) that doesn't implement
|
||||||
/// the structural-match traits, or a generic type parameter
|
/// the structural-match traits, or a generic type parameter
|
||||||
|
@ -54,15 +35,28 @@ pub enum NonStructuralMatchTyKind<'tcx> {
|
||||||
/// For more background on why Rust has this requirement, and issues
|
/// For more background on why Rust has this requirement, and issues
|
||||||
/// that arose when the requirement was not enforced completely, see
|
/// that arose when the requirement was not enforced completely, see
|
||||||
/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
|
/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
|
||||||
///
|
|
||||||
/// The floats_allowed flag is used to deny constants in floating point
|
|
||||||
pub fn search_for_structural_match_violation<'tcx>(
|
pub fn search_for_structural_match_violation<'tcx>(
|
||||||
span: Span,
|
span: Span,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
floats_allowed: bool,
|
) -> Option<Ty<'tcx>> {
|
||||||
) -> Option<NonStructuralMatchTy<'tcx>> {
|
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), adt_const_param: false })
|
||||||
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), floats_allowed })
|
.break_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method traverses the structure of `ty`, trying to find any
|
||||||
|
/// types that are not allowed to be used in a const generic.
|
||||||
|
///
|
||||||
|
/// This is either because the type does not implement `StructuralEq`
|
||||||
|
/// and `StructuralPartialEq`, or because the type is intentionally
|
||||||
|
/// not supported in const generics (such as floats and raw pointers,
|
||||||
|
/// which are allowed in match blocks).
|
||||||
|
pub fn search_for_adt_const_param_violation<'tcx>(
|
||||||
|
span: Span,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
) -> Option<Ty<'tcx>> {
|
||||||
|
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), adt_const_param: true })
|
||||||
.break_value()
|
.break_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +119,10 @@ struct Search<'tcx> {
|
||||||
/// we will not recur on them again.
|
/// we will not recur on them again.
|
||||||
seen: FxHashSet<hir::def_id::DefId>,
|
seen: FxHashSet<hir::def_id::DefId>,
|
||||||
|
|
||||||
floats_allowed: bool,
|
// Additionally deny things that have been allowed in patterns,
|
||||||
|
// but are not allowed in adt const params, such as floats and
|
||||||
|
// fn ptrs.
|
||||||
|
adt_const_param: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Search<'tcx> {
|
impl<'tcx> Search<'tcx> {
|
||||||
|
@ -135,7 +132,7 @@ impl<'tcx> Search<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
|
impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
|
||||||
type BreakTy = NonStructuralMatchTy<'tcx>;
|
type BreakTy = Ty<'tcx>;
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
debug!("Search visiting ty: {:?}", ty);
|
debug!("Search visiting ty: {:?}", ty);
|
||||||
|
@ -143,51 +140,27 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
|
||||||
let (adt_def, substs) = match *ty.kind() {
|
let (adt_def, substs) = match *ty.kind() {
|
||||||
ty::Adt(adt_def, substs) => (adt_def, substs),
|
ty::Adt(adt_def, substs) => (adt_def, substs),
|
||||||
ty::Param(_) => {
|
ty::Param(_) => {
|
||||||
let kind = NonStructuralMatchTyKind::Param;
|
return ControlFlow::Break(ty);
|
||||||
return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
|
|
||||||
}
|
}
|
||||||
ty::Dynamic(..) => {
|
ty::Dynamic(..) => {
|
||||||
let kind = NonStructuralMatchTyKind::Dynamic;
|
return ControlFlow::Break(ty);
|
||||||
return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
|
|
||||||
}
|
}
|
||||||
ty::Foreign(_) => {
|
ty::Foreign(_) => {
|
||||||
let kind = NonStructuralMatchTyKind::Foreign;
|
return ControlFlow::Break(ty);
|
||||||
return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
|
|
||||||
}
|
}
|
||||||
ty::Opaque(..) => {
|
ty::Opaque(..) => {
|
||||||
let kind = NonStructuralMatchTyKind::Opaque;
|
return ControlFlow::Break(ty);
|
||||||
return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
|
|
||||||
}
|
}
|
||||||
ty::Projection(..) => {
|
ty::Projection(..) => {
|
||||||
let kind = NonStructuralMatchTyKind::Projection;
|
return ControlFlow::Break(ty);
|
||||||
return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
|
|
||||||
}
|
}
|
||||||
ty::Closure(..) => {
|
ty::Closure(..) => {
|
||||||
let kind = NonStructuralMatchTyKind::Closure;
|
return ControlFlow::Break(ty);
|
||||||
return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
|
|
||||||
}
|
}
|
||||||
ty::Generator(..) | ty::GeneratorWitness(..) => {
|
ty::Generator(..) | ty::GeneratorWitness(..) => {
|
||||||
let kind = NonStructuralMatchTyKind::Generator;
|
return ControlFlow::Break(ty);
|
||||||
return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
|
|
||||||
}
|
}
|
||||||
ty::RawPtr(..) => {
|
ty::FnDef(..) => {
|
||||||
// structural-match ignores substructure of
|
|
||||||
// `*const _`/`*mut _`, so skip `super_visit_with`.
|
|
||||||
//
|
|
||||||
// For example, if you have:
|
|
||||||
// ```
|
|
||||||
// struct NonStructural;
|
|
||||||
// #[derive(PartialEq, Eq)]
|
|
||||||
// struct T(*const NonStructural);
|
|
||||||
// const C: T = T(std::ptr::null());
|
|
||||||
// ```
|
|
||||||
//
|
|
||||||
// Even though `NonStructural` does not implement `PartialEq`,
|
|
||||||
// structural equality on `T` does not recur into the raw
|
|
||||||
// pointer. Therefore, one can still use `C` in a pattern.
|
|
||||||
return ControlFlow::CONTINUE;
|
|
||||||
}
|
|
||||||
ty::FnDef(..) | ty::FnPtr(..) => {
|
|
||||||
// Types of formals and return in `fn(_) -> _` are also irrelevant;
|
// Types of formals and return in `fn(_) -> _` are also irrelevant;
|
||||||
// so we do not recur into them via `super_visit_with`
|
// so we do not recur into them via `super_visit_with`
|
||||||
return ControlFlow::CONTINUE;
|
return ControlFlow::CONTINUE;
|
||||||
|
@ -206,14 +179,41 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
|
||||||
return ControlFlow::CONTINUE;
|
return ControlFlow::CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Float(_) => {
|
ty::FnPtr(..) => {
|
||||||
if self.floats_allowed {
|
if !self.adt_const_param {
|
||||||
return ControlFlow::CONTINUE;
|
return ControlFlow::CONTINUE;
|
||||||
} else {
|
} else {
|
||||||
return ControlFlow::Break(NonStructuralMatchTy {
|
return ControlFlow::Break(ty);
|
||||||
ty,
|
}
|
||||||
kind: NonStructuralMatchTyKind::Float,
|
}
|
||||||
});
|
|
||||||
|
ty::RawPtr(..) => {
|
||||||
|
if !self.adt_const_param {
|
||||||
|
// structural-match ignores substructure of
|
||||||
|
// `*const _`/`*mut _`, so skip `super_visit_with`.
|
||||||
|
//
|
||||||
|
// For example, if you have:
|
||||||
|
// ```
|
||||||
|
// struct NonStructural;
|
||||||
|
// #[derive(PartialEq, Eq)]
|
||||||
|
// struct T(*const NonStructural);
|
||||||
|
// const C: T = T(std::ptr::null());
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Even though `NonStructural` does not implement `PartialEq`,
|
||||||
|
// structural equality on `T` does not recur into the raw
|
||||||
|
// pointer. Therefore, one can still use `C` in a pattern.
|
||||||
|
return ControlFlow::CONTINUE;
|
||||||
|
} else {
|
||||||
|
return ControlFlow::Break(ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ty::Float(_) => {
|
||||||
|
if !self.adt_const_param {
|
||||||
|
return ControlFlow::CONTINUE;
|
||||||
|
} else {
|
||||||
|
return ControlFlow::Break(ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,8 +239,7 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
|
||||||
|
|
||||||
if !self.type_marked_structural(ty) {
|
if !self.type_marked_structural(ty) {
|
||||||
debug!("Search found ty: {:?}", ty);
|
debug!("Search found ty: {:?}", ty);
|
||||||
let kind = NonStructuralMatchTyKind::Adt(adt_def);
|
return ControlFlow::Break(ty);
|
||||||
return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// structural-match does not care about the
|
// structural-match does not care about the
|
||||||
|
|
|
@ -848,29 +848,13 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
|
||||||
let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id));
|
let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id));
|
||||||
|
|
||||||
if tcx.features().adt_const_params {
|
if tcx.features().adt_const_params {
|
||||||
let err = match ty.peel_refs().kind() {
|
|
||||||
ty::FnPtr(_) => Some("function pointers"),
|
|
||||||
ty::RawPtr(_) => Some("raw pointers"),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(unsupported_type) = err {
|
|
||||||
tcx.sess.span_err(
|
|
||||||
hir_ty.span,
|
|
||||||
&format!(
|
|
||||||
"using {} as const generic parameters is forbidden",
|
|
||||||
unsupported_type
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(non_structural_match_ty) =
|
if let Some(non_structural_match_ty) =
|
||||||
traits::search_for_structural_match_violation(param.span, tcx, ty, false)
|
traits::search_for_adt_const_param_violation(param.span, tcx, ty)
|
||||||
{
|
{
|
||||||
// We use the same error code in both branches, because this is really the same
|
// We use the same error code in both branches, because this is really the same
|
||||||
// issue: we just special-case the message for type parameters to make it
|
// issue: we just special-case the message for type parameters to make it
|
||||||
// clearer.
|
// clearer.
|
||||||
match ty.peel_refs().kind() {
|
match non_structural_match_ty.kind() {
|
||||||
ty::Param(_) => {
|
ty::Param(_) => {
|
||||||
// Const parameters may not have type parameters as their types,
|
// Const parameters may not have type parameters as their types,
|
||||||
// because we cannot be sure that the type parameter derives `PartialEq`
|
// because we cannot be sure that the type parameter derives `PartialEq`
|
||||||
|
@ -902,6 +886,24 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
|
||||||
.note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
|
.note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
|
ty::FnPtr(_) => {
|
||||||
|
struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
hir_ty.span,
|
||||||
|
E0741,
|
||||||
|
"using function pointers as const generic parameters is forbidden",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
ty::RawPtr(_) => {
|
||||||
|
struct_span_err!(
|
||||||
|
tcx.sess,
|
||||||
|
hir_ty.span,
|
||||||
|
E0741,
|
||||||
|
"using raw pointers as const generic parameters is forbidden",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut diag = struct_span_err!(
|
let mut diag = struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
|
@ -909,10 +911,10 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
|
||||||
E0741,
|
E0741,
|
||||||
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
|
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
|
||||||
the type of a const parameter",
|
the type of a const parameter",
|
||||||
non_structural_match_ty.ty,
|
non_structural_match_ty,
|
||||||
);
|
);
|
||||||
|
|
||||||
if ty == non_structural_match_ty.ty {
|
if ty == non_structural_match_ty {
|
||||||
diag.span_label(
|
diag.span_label(
|
||||||
hir_ty.span,
|
hir_ty.span,
|
||||||
format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
|
format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/fn-const-param-call.rs:11:25
|
--> $DIR/fn-const-param-call.rs:11:25
|
||||||
|
|
|
|
||||||
LL | struct Wrapper<const F: fn() -> u32>;
|
LL | struct Wrapper<const F: fn() -> u32>;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/fn-const-param-call.rs:13:15
|
--> $DIR/fn-const-param-call.rs:13:15
|
||||||
|
|
|
|
||||||
LL | impl<const F: fn() -> u32> Wrapper<F> {
|
LL | impl<const F: fn() -> u32> Wrapper<F> {
|
||||||
|
@ -12,3 +12,4 @@ LL | impl<const F: fn() -> u32> Wrapper<F> {
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0741`.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/fn-const-param-infer.rs:6:25
|
--> $DIR/fn-const-param-infer.rs:6:25
|
||||||
|
|
|
|
||||||
LL | struct Checked<const F: fn(usize) -> bool>;
|
LL | struct Checked<const F: fn(usize) -> bool>;
|
||||||
|
@ -6,3 +6,4 @@ LL | struct Checked<const F: fn(usize) -> bool>;
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0741`.
|
||||||
|
|
|
@ -10,13 +10,13 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
||||||
LL | const FN: unsafe extern "C" fn(Args),
|
LL | const FN: unsafe extern "C" fn(Args),
|
||||||
| ^^^^ the type must not depend on the parameter `Args`
|
| ^^^^ the type must not depend on the parameter `Args`
|
||||||
|
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/issue-71381.rs:14:61
|
--> $DIR/issue-71381.rs:14:61
|
||||||
|
|
|
|
||||||
LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
|
LL | pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/issue-71381.rs:23:19
|
--> $DIR/issue-71381.rs:23:19
|
||||||
|
|
|
|
||||||
LL | const FN: unsafe extern "C" fn(Args),
|
LL | const FN: unsafe extern "C" fn(Args),
|
||||||
|
@ -24,4 +24,5 @@ LL | const FN: unsafe extern "C" fn(Args),
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0770`.
|
Some errors have detailed explanations: E0741, E0770.
|
||||||
|
For more information about an error, try `rustc --explain E0741`.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/issue-71382.rs:16:23
|
--> $DIR/issue-71382.rs:16:23
|
||||||
|
|
|
|
||||||
LL | fn test<const FN: fn()>(&self) {
|
LL | fn test<const FN: fn()>(&self) {
|
||||||
|
@ -6,3 +6,4 @@ LL | fn test<const FN: fn()>(&self) {
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0741`.
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0770]: the type of const parameters must not depend on other generic para
|
||||||
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
||||||
| ^ the type must not depend on the parameter `A`
|
| ^ the type must not depend on the parameter `A`
|
||||||
|
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/issue-71611.rs:5:21
|
--> $DIR/issue-71611.rs:5:21
|
||||||
|
|
|
|
||||||
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
||||||
|
@ -12,4 +12,5 @@ LL | fn func<A, const F: fn(inner: A)>(outer: A) {
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0770`.
|
Some errors have detailed explanations: E0741, E0770.
|
||||||
|
For more information about an error, try `rustc --explain E0741`.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: using function pointers as const generic parameters is forbidden
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/issue-72352.rs:7:42
|
--> $DIR/issue-72352.rs:7:42
|
||||||
|
|
|
|
||||||
LL | unsafe fn unsafely_do_the_thing<const F: fn(&CStr) -> usize>(ptr: *const i8) -> usize {
|
LL | unsafe fn unsafely_do_the_thing<const F: fn(&CStr) -> usize>(ptr: *const i8) -> usize {
|
||||||
|
@ -6,3 +6,4 @@ LL | unsafe fn unsafely_do_the_thing<const F: fn(&CStr) -> usize>(ptr: *const i8
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0741`.
|
||||||
|
|
18
src/test/ui/const-generics/issues/issue-99641.rs
Normal file
18
src/test/ui/const-generics/issues/issue-99641.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#![feature(adt_const_params)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
pub struct Color<const WHITE: (fn(),)>;
|
||||||
|
//~^ ERROR using function pointers
|
||||||
|
|
||||||
|
impl<const WHITE: (fn(),)> Color<WHITE> {
|
||||||
|
//~^ ERROR using function pointers
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Color::<WHITE>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const D65: (fn(),) = (|| {},);
|
||||||
|
|
||||||
|
Color::<D65>::new();
|
||||||
|
}
|
15
src/test/ui/const-generics/issues/issue-99641.stderr
Normal file
15
src/test/ui/const-generics/issues/issue-99641.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
|
--> $DIR/issue-99641.rs:5:35
|
||||||
|
|
|
||||||
|
LL | pub struct Color<const WHITE: (fn(),)>;
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
|
--> $DIR/issue-99641.rs:8:23
|
||||||
|
|
|
||||||
|
LL | impl<const WHITE: (fn(),)> Color<WHITE> {
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0741`.
|
|
@ -1,10 +1,10 @@
|
||||||
error: using raw pointers as const generic parameters is forbidden
|
error[E0741]: using raw pointers as const generic parameters is forbidden
|
||||||
--> $DIR/raw-ptr-const-param-deref.rs:9:23
|
--> $DIR/raw-ptr-const-param-deref.rs:9:23
|
||||||
|
|
|
|
||||||
LL | struct Const<const P: *const u32>;
|
LL | struct Const<const P: *const u32>;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: using raw pointers as const generic parameters is forbidden
|
error[E0741]: using raw pointers as const generic parameters is forbidden
|
||||||
--> $DIR/raw-ptr-const-param-deref.rs:11:15
|
--> $DIR/raw-ptr-const-param-deref.rs:11:15
|
||||||
|
|
|
|
||||||
LL | impl<const P: *const u32> Const<P> {
|
LL | impl<const P: *const u32> Const<P> {
|
||||||
|
@ -12,3 +12,4 @@ LL | impl<const P: *const u32> Const<P> {
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0741`.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: using raw pointers as const generic parameters is forbidden
|
error[E0741]: using raw pointers as const generic parameters is forbidden
|
||||||
--> $DIR/raw-ptr-const-param.rs:6:23
|
--> $DIR/raw-ptr-const-param.rs:6:23
|
||||||
|
|
|
|
||||||
LL | struct Const<const P: *const u32>;
|
LL | struct Const<const P: *const u32>;
|
||||||
|
@ -6,3 +6,4 @@ LL | struct Const<const P: *const u32>;
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0741`.
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// check-pass
|
|
||||||
|
|
||||||
#![feature(fn_traits)]
|
#![feature(fn_traits)]
|
||||||
#![feature(adt_const_params)]
|
#![feature(adt_const_params)]
|
||||||
//~^ WARNING the feature `adt_const_params` is incomplete
|
//~^ WARNING the feature `adt_const_params` is incomplete
|
||||||
|
@ -10,8 +8,10 @@ struct CompileTimeSettings{
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Foo<const T: CompileTimeSettings>;
|
struct Foo<const T: CompileTimeSettings>;
|
||||||
|
//~^ ERROR using function pointers as const generic parameters is forbidden
|
||||||
|
|
||||||
impl<const T: CompileTimeSettings> Foo<T> {
|
impl<const T: CompileTimeSettings> Foo<T> {
|
||||||
|
//~^ ERROR using function pointers as const generic parameters is forbidden
|
||||||
fn call_hooks(){
|
fn call_hooks(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/refs_check_const_eq-issue-88384.rs:4:12
|
--> $DIR/refs_check_const_eq-issue-88384.rs:2:12
|
||||||
|
|
|
|
||||||
LL | #![feature(adt_const_params)]
|
LL | #![feature(adt_const_params)]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
@ -7,5 +7,18 @@ LL | #![feature(adt_const_params)]
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
|
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
|
||||||
|
|
||||||
warning: 1 warning emitted
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
|
--> $DIR/refs_check_const_eq-issue-88384.rs:10:21
|
||||||
|
|
|
||||||
|
LL | struct Foo<const T: CompileTimeSettings>;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||||
|
--> $DIR/refs_check_const_eq-issue-88384.rs:13:15
|
||||||
|
|
|
||||||
|
LL | impl<const T: CompileTimeSettings> Foo<T> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0741`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue