Skip to content

Commit 92b8adf

Browse files
authored
Rollup merge of rust-lang#98907 - compiler-errors:plz-no-float, r=oli-obk
Deny float const params even when `adt_const_params` is enabled Supersedes rust-lang#98825 Fixes rust-lang#98813 r? ``@oli-obk``
2 parents 9431520 + a163464 commit 92b8adf

File tree

7 files changed

+135
-66
lines changed

7 files changed

+135
-66
lines changed

compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ impl Qualif for CustomEq {
226226
// because that component may be part of an enum variant (e.g.,
227227
// `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
228228
// structural-match (`Option::None`).
229-
traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
229+
traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty, true).is_some()
230230
}
231231

232232
fn in_adt_inherently<'tcx>(

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

+31-26
Original file line numberDiff line numberDiff line change
@@ -120,32 +120,37 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
120120
}
121121

122122
fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
123-
traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
124-
with_no_trimmed_paths!(match non_sm_ty.kind {
125-
traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
126-
traits::NonStructuralMatchTyKind::Dynamic => {
127-
"trait objects cannot be used in patterns".to_string()
128-
}
129-
traits::NonStructuralMatchTyKind::Opaque => {
130-
"opaque types cannot be used in patterns".to_string()
131-
}
132-
traits::NonStructuralMatchTyKind::Closure => {
133-
"closures cannot be used in patterns".to_string()
134-
}
135-
traits::NonStructuralMatchTyKind::Generator => {
136-
"generators cannot be used in patterns".to_string()
137-
}
138-
traits::NonStructuralMatchTyKind::Param => {
139-
bug!("use of a constant whose type is a parameter inside a pattern")
140-
}
141-
traits::NonStructuralMatchTyKind::Projection => {
142-
bug!("use of a constant whose type is a projection inside a pattern")
143-
}
144-
traits::NonStructuralMatchTyKind::Foreign => {
145-
bug!("use of a value of a foreign type inside a pattern")
146-
}
147-
})
148-
})
123+
traits::search_for_structural_match_violation(self.span, self.tcx(), ty, true).map(
124+
|non_sm_ty| {
125+
with_no_trimmed_paths!(match non_sm_ty.kind {
126+
traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
127+
traits::NonStructuralMatchTyKind::Dynamic => {
128+
"trait objects cannot be used in patterns".to_string()
129+
}
130+
traits::NonStructuralMatchTyKind::Opaque => {
131+
"opaque types cannot be used in patterns".to_string()
132+
}
133+
traits::NonStructuralMatchTyKind::Closure => {
134+
"closures cannot be used in patterns".to_string()
135+
}
136+
traits::NonStructuralMatchTyKind::Generator => {
137+
"generators cannot be used in patterns".to_string()
138+
}
139+
traits::NonStructuralMatchTyKind::Float => {
140+
"floating-point numbers cannot be used in patterns".to_string()
141+
}
142+
traits::NonStructuralMatchTyKind::Param => {
143+
bug!("use of a constant whose type is a parameter inside a pattern")
144+
}
145+
traits::NonStructuralMatchTyKind::Projection => {
146+
bug!("use of a constant whose type is a projection inside a pattern")
147+
}
148+
traits::NonStructuralMatchTyKind::Foreign => {
149+
bug!("use of a value of a foreign type inside a pattern")
150+
}
151+
})
152+
},
153+
)
149154
}
150155

151156
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {

compiler/rustc_trait_selection/src/traits/structural_match.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub enum NonStructuralMatchTyKind<'tcx> {
2626
Closure,
2727
Generator,
2828
Projection,
29+
Float,
2930
}
3031

3132
/// This method traverses the structure of `ty`, trying to find an
@@ -53,12 +54,16 @@ pub enum NonStructuralMatchTyKind<'tcx> {
5354
/// For more background on why Rust has this requirement, and issues
5455
/// that arose when the requirement was not enforced completely, see
5556
/// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
57+
///
58+
/// The floats_allowed flag is used to deny constants in floating point
5659
pub fn search_for_structural_match_violation<'tcx>(
5760
span: Span,
5861
tcx: TyCtxt<'tcx>,
5962
ty: Ty<'tcx>,
63+
floats_allowed: bool,
6064
) -> Option<NonStructuralMatchTy<'tcx>> {
61-
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default() }).break_value()
65+
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), floats_allowed })
66+
.break_value()
6267
}
6368

6469
/// This method returns true if and only if `adt_ty` itself has been marked as
@@ -119,6 +124,8 @@ struct Search<'tcx> {
119124
/// Tracks ADTs previously encountered during search, so that
120125
/// we will not recur on them again.
121126
seen: FxHashSet<hir::def_id::DefId>,
127+
128+
floats_allowed: bool,
122129
}
123130

124131
impl<'tcx> Search<'tcx> {
@@ -192,13 +199,24 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
192199
// for empty array.
193200
return ControlFlow::CONTINUE;
194201
}
195-
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
202+
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Str | ty::Never => {
196203
// These primitive types are always structural match.
197204
//
198205
// `Never` is kind of special here, but as it is not inhabitable, this should be fine.
199206
return ControlFlow::CONTINUE;
200207
}
201208

209+
ty::Float(_) => {
210+
if self.floats_allowed {
211+
return ControlFlow::CONTINUE;
212+
} else {
213+
return ControlFlow::Break(NonStructuralMatchTy {
214+
ty,
215+
kind: NonStructuralMatchTyKind::Float,
216+
});
217+
}
218+
}
219+
202220
ty::Array(..) | ty::Slice(_) | ty::Ref(..) | ty::Tuple(..) => {
203221
// First check all contained types and then tell the caller to continue searching.
204222
return ty.super_visit_with(self);

compiler/rustc_typeck/src/check/wfcheck.rs

+49-37
Original file line numberDiff line numberDiff line change
@@ -824,50 +824,62 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
824824
}
825825

826826
if let Some(non_structural_match_ty) =
827-
traits::search_for_structural_match_violation(param.span, tcx, ty)
827+
traits::search_for_structural_match_violation(param.span, tcx, ty, false)
828828
{
829829
// We use the same error code in both branches, because this is really the same
830830
// issue: we just special-case the message for type parameters to make it
831831
// clearer.
832-
if let ty::Param(_) = ty.peel_refs().kind() {
833-
// Const parameters may not have type parameters as their types,
834-
// because we cannot be sure that the type parameter derives `PartialEq`
835-
// and `Eq` (just implementing them is not enough for `structural_match`).
836-
struct_span_err!(
837-
tcx.sess,
838-
hir_ty.span,
839-
E0741,
840-
"`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
841-
used as the type of a const parameter",
842-
ty,
843-
)
844-
.span_label(
845-
hir_ty.span,
846-
format!("`{}` may not derive both `PartialEq` and `Eq`", ty),
847-
)
848-
.note(
849-
"it is not currently possible to use a type parameter as the type of a \
850-
const parameter",
851-
)
852-
.emit();
853-
} else {
854-
let mut diag = struct_span_err!(
855-
tcx.sess,
856-
hir_ty.span,
857-
E0741,
858-
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
859-
the type of a const parameter",
860-
non_structural_match_ty.ty,
861-
);
862-
863-
if ty == non_structural_match_ty.ty {
864-
diag.span_label(
832+
match ty.peel_refs().kind() {
833+
ty::Param(_) => {
834+
// Const parameters may not have type parameters as their types,
835+
// because we cannot be sure that the type parameter derives `PartialEq`
836+
// and `Eq` (just implementing them is not enough for `structural_match`).
837+
struct_span_err!(
838+
tcx.sess,
865839
hir_ty.span,
866-
format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
867-
);
840+
E0741,
841+
"`{ty}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
842+
used as the type of a const parameter",
843+
)
844+
.span_label(
845+
hir_ty.span,
846+
format!("`{ty}` may not derive both `PartialEq` and `Eq`"),
847+
)
848+
.note(
849+
"it is not currently possible to use a type parameter as the type of a \
850+
const parameter",
851+
)
852+
.emit();
853+
}
854+
ty::Float(_) => {
855+
struct_span_err!(
856+
tcx.sess,
857+
hir_ty.span,
858+
E0741,
859+
"`{ty}` is forbidden as the type of a const generic parameter",
860+
)
861+
.note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
862+
.emit();
868863
}
864+
_ => {
865+
let mut diag = struct_span_err!(
866+
tcx.sess,
867+
hir_ty.span,
868+
E0741,
869+
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
870+
the type of a const parameter",
871+
non_structural_match_ty.ty,
872+
);
869873

870-
diag.emit();
874+
if ty == non_structural_match_ty.ty {
875+
diag.span_label(
876+
hir_ty.span,
877+
format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
878+
);
879+
}
880+
881+
diag.emit();
882+
}
871883
}
872884
}
873885
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0741]: `f32` is forbidden as the type of a const generic parameter
2+
--> $DIR/float-generic.rs:5:17
3+
|
4+
LL | fn foo<const F: f32>() {}
5+
| ^^^
6+
|
7+
= note: floats do not derive `Eq` or `Ord`, which are required for const parameters
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0741`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// revisions: simple adt_const_params
2+
#![cfg_attr(adt_const_params, feature(adt_const_params))]
3+
#![cfg_attr(adt_const_params, allow(incomplete_features))]
4+
5+
fn foo<const F: f32>() {}
6+
//~^ ERROR `f32` is forbidden as the type of a const generic parameter
7+
8+
const C: f32 = 1.0;
9+
10+
fn main() {
11+
foo::<C>();
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: `f32` is forbidden as the type of a const generic parameter
2+
--> $DIR/float-generic.rs:5:17
3+
|
4+
LL | fn foo<const F: f32>() {}
5+
| ^^^
6+
|
7+
= note: the only supported types are integers, `bool` and `char`
8+
= help: more complex types are supported with `#![feature(adt_const_params)]`
9+
10+
error: aborting due to previous error
11+

0 commit comments

Comments
 (0)