Auto merge of #70743 - oli-obk:eager_const_to_pat_conversion, r=eddyb
Fully destructure constants into patterns r? `@varkor` as discussed in https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/constants.20in.20patterns/near/192789924 we should probably crater it once reviewed
This commit is contained in:
commit
fd15e6180d
|
@ -742,6 +742,14 @@ rustc_queries! {
|
|||
desc { "destructure constant" }
|
||||
}
|
||||
|
||||
/// Dereference a constant reference or raw pointer and turn the result into a constant
|
||||
/// again.
|
||||
query deref_const(
|
||||
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
|
||||
) -> &'tcx ty::Const<'tcx> {
|
||||
desc { "deref constant" }
|
||||
}
|
||||
|
||||
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
|
||||
desc { "get a &core::panic::Location referring to a span" }
|
||||
}
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
|
||||
|
||||
use crate::interpret::{intern_const_alloc_recursive, ConstValue, InternKind, InterpCx};
|
||||
use crate::interpret::{
|
||||
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, MemPlaceMeta, Scalar,
|
||||
};
|
||||
|
||||
mod error;
|
||||
mod eval_queries;
|
||||
|
@ -67,3 +70,39 @@ pub(crate) fn destructure_const<'tcx>(
|
|||
|
||||
mir::DestructuredConst { variant, fields }
|
||||
}
|
||||
|
||||
pub(crate) fn deref_const<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
val: &'tcx ty::Const<'tcx>,
|
||||
) -> &'tcx ty::Const<'tcx> {
|
||||
trace!("deref_const: {:?}", val);
|
||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
|
||||
let op = ecx.const_to_op(val, None).unwrap();
|
||||
let mplace = ecx.deref_operand(op).unwrap();
|
||||
if let Scalar::Ptr(ptr) = mplace.ptr {
|
||||
assert_eq!(
|
||||
ecx.memory.get_raw(ptr.alloc_id).unwrap().mutability,
|
||||
Mutability::Not,
|
||||
"deref_const cannot be used with mutable allocations as \
|
||||
that could allow pattern matching to observe mutable statics",
|
||||
);
|
||||
}
|
||||
|
||||
let ty = match mplace.meta {
|
||||
MemPlaceMeta::None => mplace.layout.ty,
|
||||
MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
|
||||
// In case of unsized types, figure out the real type behind.
|
||||
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
|
||||
ty::Str => bug!("there's no sized equivalent of a `str`"),
|
||||
ty::Slice(elem_ty) => tcx.mk_array(elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
|
||||
_ => bug!(
|
||||
"type {} should not have metadata, but had {:?}",
|
||||
mplace.layout.ty,
|
||||
mplace.meta
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
tcx.mk_const(ty::Const { val: ty::ConstKind::Value(op_to_const(&ecx, mplace.into())), ty })
|
||||
}
|
||||
|
|
|
@ -59,4 +59,8 @@ pub fn provide(providers: &mut Providers) {
|
|||
let (param_env, value) = param_env_and_value.into_parts();
|
||||
const_eval::destructure_const(tcx, param_env, value)
|
||||
};
|
||||
providers.deref_const = |tcx, param_env_and_value| {
|
||||
let (param_env, value) = param_env_and_value.into_parts();
|
||||
const_eval::deref_const(tcx, param_env, value)
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use rustc_index::vec::Idx;
|
|||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_middle::mir::Field;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::predicate_for_trait_def;
|
||||
|
@ -28,10 +28,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
|
||||
debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
|
||||
|
||||
self.tcx.infer_ctxt().enter(|infcx| {
|
||||
let pat = self.tcx.infer_ctxt().enter(|infcx| {
|
||||
let mut convert = ConstToPat::new(self, id, span, infcx);
|
||||
convert.to_pat(cv, mir_structural_match_violation)
|
||||
})
|
||||
});
|
||||
|
||||
debug!("const_to_pat: pat={:?}", pat);
|
||||
pat
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,17 +43,44 @@ struct ConstToPat<'a, 'tcx> {
|
|||
span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
||||
// This tracks if we signal some hard error for a given const value, so that
|
||||
// This tracks if we emitted some hard error for a given const value, so that
|
||||
// we will not subsequently issue an irrelevant lint for the same const
|
||||
// value.
|
||||
saw_const_match_error: Cell<bool>,
|
||||
|
||||
// This tracks if we emitted some diagnostic for a given const value, so that
|
||||
// we will not subsequently issue an irrelevant lint for the same const
|
||||
// value.
|
||||
saw_const_match_lint: Cell<bool>,
|
||||
|
||||
// For backcompat we need to keep allowing non-structurally-eq types behind references.
|
||||
// See also all the `cant-hide-behind` tests.
|
||||
behind_reference: Cell<bool>,
|
||||
|
||||
// inference context used for checking `T: Structural` bounds.
|
||||
infcx: InferCtxt<'a, 'tcx>,
|
||||
|
||||
include_lint_checks: bool,
|
||||
}
|
||||
|
||||
mod fallback_to_const_ref {
|
||||
#[derive(Debug)]
|
||||
/// This error type signals that we encountered a non-struct-eq situation behind a reference.
|
||||
/// We bubble this up in order to get back to the reference destructuring and make that emit
|
||||
/// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
|
||||
/// on such patterns (since that function takes a reference) and not have to jump through any
|
||||
/// hoops to get a reference to the value.
|
||||
pub(super) struct FallbackToConstRef(());
|
||||
|
||||
pub(super) fn fallback_to_const_ref<'a, 'tcx>(
|
||||
c2p: &super::ConstToPat<'a, 'tcx>,
|
||||
) -> FallbackToConstRef {
|
||||
assert!(c2p.behind_reference.get());
|
||||
FallbackToConstRef(())
|
||||
}
|
||||
}
|
||||
use fallback_to_const_ref::{fallback_to_const_ref, FallbackToConstRef};
|
||||
|
||||
impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||
fn new(
|
||||
pat_ctxt: &PatCtxt<'_, 'tcx>,
|
||||
|
@ -65,6 +95,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
param_env: pat_ctxt.param_env,
|
||||
include_lint_checks: pat_ctxt.include_lint_checks,
|
||||
saw_const_match_error: Cell::new(false),
|
||||
saw_const_match_lint: Cell::new(false),
|
||||
behind_reference: Cell::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,11 +104,44 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn search_for_structural_match_violation(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<traits::NonStructuralMatchTy<'tcx>> {
|
||||
traits::search_for_structural_match_violation(self.id, self.span, self.tcx(), ty)
|
||||
fn adt_derive_msg(&self, adt_def: &AdtDef) -> String {
|
||||
let path = self.tcx().def_path_str(adt_def.did);
|
||||
format!(
|
||||
"to use a constant of type `{}` in a pattern, \
|
||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||
path, path,
|
||||
)
|
||||
}
|
||||
|
||||
fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
|
||||
traits::search_for_structural_match_violation(self.id, self.span, self.tcx(), ty).map(
|
||||
|non_sm_ty| {
|
||||
with_no_trimmed_paths(|| match non_sm_ty {
|
||||
traits::NonStructuralMatchTy::Adt(adt) => self.adt_derive_msg(adt),
|
||||
traits::NonStructuralMatchTy::Dynamic => {
|
||||
"trait objects cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Opaque => {
|
||||
"opaque types cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Generator => {
|
||||
"generators cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Closure => {
|
||||
"closures cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Param => {
|
||||
bug!("use of a constant whose type is a parameter inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTy::Projection => {
|
||||
bug!("use of a constant whose type is a projection inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTy::Foreign => {
|
||||
bug!("use of a value of a foreign type inside a pattern")
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
|
||||
|
@ -95,7 +160,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
// once indirect_structural_match is a full fledged error, this
|
||||
// level of indirection can be eliminated
|
||||
|
||||
let inlined_const_as_pat = self.recur(cv);
|
||||
let inlined_const_as_pat = self.recur(cv, mir_structural_match_violation).unwrap();
|
||||
|
||||
if self.include_lint_checks && !self.saw_const_match_error.get() {
|
||||
// If we were able to successfully convert the const to some pat,
|
||||
|
@ -118,70 +183,11 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
return inlined_const_as_pat;
|
||||
}
|
||||
|
||||
if let Some(non_sm_ty) = structural {
|
||||
let msg = with_no_trimmed_paths(|| match non_sm_ty {
|
||||
traits::NonStructuralMatchTy::Adt(adt_def) => {
|
||||
let path = self.tcx().def_path_str(adt_def.did);
|
||||
format!(
|
||||
"to use a constant of type `{}` in a pattern, \
|
||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||
path, path,
|
||||
)
|
||||
}
|
||||
traits::NonStructuralMatchTy::Dynamic => {
|
||||
"trait objects cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Opaque => {
|
||||
"opaque types cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Generator => {
|
||||
"generators cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Closure => {
|
||||
"closures cannot be used in patterns".to_string()
|
||||
}
|
||||
traits::NonStructuralMatchTy::Param => {
|
||||
bug!("use of a constant whose type is a parameter inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTy::Projection => {
|
||||
bug!("use of a constant whose type is a projection inside a pattern")
|
||||
}
|
||||
traits::NonStructuralMatchTy::Foreign => {
|
||||
bug!("use of a value of a foreign type inside a pattern")
|
||||
}
|
||||
});
|
||||
|
||||
// double-check there even *is* a semantic `PartialEq` to dispatch to.
|
||||
//
|
||||
// (If there isn't, then we can safely issue a hard
|
||||
// error, because that's never worked, due to compiler
|
||||
// using `PartialEq::eq` in this scenario in the past.)
|
||||
//
|
||||
// Note: To fix rust-lang/rust#65466, one could lift this check
|
||||
// *before* any structural-match checking, and unconditionally error
|
||||
// if `PartialEq` is not implemented. However, that breaks stable
|
||||
// code at the moment, because types like `for <'a> fn(&'a ())` do
|
||||
// not *yet* implement `PartialEq`. So for now we leave this here.
|
||||
let ty_is_partial_eq: bool = {
|
||||
let partial_eq_trait_id =
|
||||
self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
|
||||
let obligation: PredicateObligation<'_> = predicate_for_trait_def(
|
||||
self.tcx(),
|
||||
self.param_env,
|
||||
ObligationCause::misc(self.span, self.id),
|
||||
partial_eq_trait_id,
|
||||
0,
|
||||
cv.ty,
|
||||
&[],
|
||||
);
|
||||
// FIXME: should this call a `predicate_must_hold` variant instead?
|
||||
self.infcx.predicate_may_hold(&obligation)
|
||||
};
|
||||
|
||||
if !ty_is_partial_eq {
|
||||
if let Some(msg) = structural {
|
||||
if !self.type_may_have_partial_eq_impl(cv.ty) {
|
||||
// span_fatal avoids ICE from resolution of non-existent method (rare case).
|
||||
self.tcx().sess.span_fatal(self.span, &msg);
|
||||
} else if mir_structural_match_violation {
|
||||
} else if mir_structural_match_violation && !self.saw_const_match_lint.get() {
|
||||
self.tcx().struct_span_lint_hir(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
self.id,
|
||||
|
@ -200,19 +206,57 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
inlined_const_as_pat
|
||||
}
|
||||
|
||||
fn type_may_have_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
|
||||
// double-check there even *is* a semantic `PartialEq` to dispatch to.
|
||||
//
|
||||
// (If there isn't, then we can safely issue a hard
|
||||
// error, because that's never worked, due to compiler
|
||||
// using `PartialEq::eq` in this scenario in the past.)
|
||||
let partial_eq_trait_id =
|
||||
self.tcx().require_lang_item(hir::LangItem::PartialEq, Some(self.span));
|
||||
let obligation: PredicateObligation<'_> = predicate_for_trait_def(
|
||||
self.tcx(),
|
||||
self.param_env,
|
||||
ObligationCause::misc(self.span, self.id),
|
||||
partial_eq_trait_id,
|
||||
0,
|
||||
ty,
|
||||
&[],
|
||||
);
|
||||
// FIXME: should this call a `predicate_must_hold` variant instead?
|
||||
|
||||
let has_impl = self.infcx.predicate_may_hold(&obligation);
|
||||
|
||||
// Note: To fix rust-lang/rust#65466, we could just remove this type
|
||||
// walk hack for function pointers, and unconditionally error
|
||||
// if `PartialEq` is not implemented. However, that breaks stable
|
||||
// code at the moment, because types like `for <'a> fn(&'a ())` do
|
||||
// not *yet* implement `PartialEq`. So for now we leave this here.
|
||||
has_impl
|
||||
|| ty.walk().any(|t| match t.unpack() {
|
||||
ty::subst::GenericArgKind::Lifetime(_) => false,
|
||||
ty::subst::GenericArgKind::Type(t) => t.is_fn_ptr(),
|
||||
ty::subst::GenericArgKind::Const(_) => false,
|
||||
})
|
||||
}
|
||||
|
||||
// Recursive helper for `to_pat`; invoke that (instead of calling this directly).
|
||||
fn recur(&self, cv: &'tcx ty::Const<'tcx>) -> Pat<'tcx> {
|
||||
fn recur(
|
||||
&self,
|
||||
cv: &'tcx ty::Const<'tcx>,
|
||||
mir_structural_match_violation: bool,
|
||||
) -> Result<Pat<'tcx>, FallbackToConstRef> {
|
||||
let id = self.id;
|
||||
let span = self.span;
|
||||
let tcx = self.tcx();
|
||||
let param_env = self.param_env;
|
||||
|
||||
let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| {
|
||||
let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| -> Result<_, _> {
|
||||
vals.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, val)| {
|
||||
let field = Field::new(idx);
|
||||
FieldPat { field, pattern: self.recur(val) }
|
||||
Ok(FieldPat { field, pattern: self.recur(val, false)? })
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
|
@ -230,10 +274,63 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
ty::Adt(adt_def, _) if adt_def.is_union() => {
|
||||
// Matching on union fields is unsafe, we can't hide it in constants
|
||||
self.saw_const_match_error.set(true);
|
||||
tcx.sess.span_err(span, "cannot use unions in constant patterns");
|
||||
let msg = "cannot use unions in constant patterns";
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, msg)
|
||||
}
|
||||
PatKind::Wild
|
||||
}
|
||||
// keep old code until future-compat upgraded to errors.
|
||||
ty::Adt(..)
|
||||
if !self.type_may_have_partial_eq_impl(cv.ty)
|
||||
// FIXME(#73448): Find a way to bring const qualification into parity with
|
||||
// `search_for_structural_match_violation` and then remove this condition.
|
||||
&& self.search_for_structural_match_violation(cv.ty).is_some() =>
|
||||
{
|
||||
// Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
|
||||
// could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
|
||||
let msg = self.search_for_structural_match_violation(cv.ty).unwrap();
|
||||
self.saw_const_match_error.set(true);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(self.span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(self.span, &msg)
|
||||
}
|
||||
PatKind::Wild
|
||||
}
|
||||
// If the type is not structurally comparable, just emit the constant directly,
|
||||
// causing the pattern match code to treat it opaquely.
|
||||
// FIXME: This code doesn't emit errors itself, the caller emits the errors.
|
||||
// So instead of specific errors, you just get blanket errors about the whole
|
||||
// const type. See
|
||||
// https://github.com/rust-lang/rust/pull/70743#discussion_r404701963 for
|
||||
// details.
|
||||
// Backwards compatibility hack because we can't cause hard errors on these
|
||||
// types, so we compare them via `PartialEq::eq` at runtime.
|
||||
ty::Adt(..) if !self.type_marked_structural(cv.ty) && self.behind_reference.get() => {
|
||||
if self.include_lint_checks
|
||||
&& !self.saw_const_match_error.get()
|
||||
&& !self.saw_const_match_lint.get()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
let msg = format!(
|
||||
"to use a constant of type `{}` in a pattern, \
|
||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||
cv.ty, cv.ty,
|
||||
);
|
||||
tcx.struct_span_lint_hir(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
id,
|
||||
span,
|
||||
|lint| lint.build(&msg).emit(),
|
||||
);
|
||||
}
|
||||
// Since we are behind a reference, we can just bubble the error up so we get a
|
||||
// constant at reference type, making it easy to let the fallback call
|
||||
// `PartialEq::eq` on it.
|
||||
return Err(fallback_to_const_ref(self));
|
||||
}
|
||||
ty::Adt(adt_def, _) if !self.type_marked_structural(cv.ty) => {
|
||||
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, cv.ty);
|
||||
let path = tcx.def_path_str(adt_def.did);
|
||||
|
@ -243,29 +340,11 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
path, path,
|
||||
);
|
||||
self.saw_const_match_error.set(true);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
PatKind::Wild
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg)
|
||||
}
|
||||
// keep old code until future-compat upgraded to errors.
|
||||
ty::Ref(_, adt_ty, _) if adt_ty.is_adt() && !self.type_marked_structural(adt_ty) => {
|
||||
let adt_def =
|
||||
if let ty::Adt(adt_def, _) = adt_ty.kind() { adt_def } else { unreachable!() };
|
||||
|
||||
debug!(
|
||||
"adt_def {:?} has !type_marked_structural for adt_ty: {:?}",
|
||||
adt_def, adt_ty
|
||||
);
|
||||
|
||||
// HACK(estebank): Side-step ICE #53708, but anything other than erroring here
|
||||
// would be wrong. Returnging `PatKind::Wild` is not technically correct.
|
||||
let path = tcx.def_path_str(adt_def.did);
|
||||
let msg = format!(
|
||||
"to use a constant of type `{}` in a pattern, \
|
||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||
path, path,
|
||||
);
|
||||
self.saw_const_match_error.set(true);
|
||||
tcx.sess.span_err(span, &msg);
|
||||
PatKind::Wild
|
||||
}
|
||||
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
|
||||
|
@ -276,30 +355,181 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
|||
variant_index: destructured
|
||||
.variant
|
||||
.expect("destructed const of adt without variant id"),
|
||||
subpatterns: field_pats(destructured.fields),
|
||||
subpatterns: field_pats(destructured.fields)?,
|
||||
}
|
||||
}
|
||||
ty::Adt(_, _) => {
|
||||
ty::Tuple(_) | ty::Adt(_, _) => {
|
||||
let destructured = tcx.destructure_const(param_env.and(cv));
|
||||
PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
|
||||
}
|
||||
ty::Tuple(_) => {
|
||||
let destructured = tcx.destructure_const(param_env.and(cv));
|
||||
PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
|
||||
PatKind::Leaf { subpatterns: field_pats(destructured.fields)? }
|
||||
}
|
||||
ty::Array(..) => PatKind::Array {
|
||||
prefix: tcx
|
||||
.destructure_const(param_env.and(cv))
|
||||
.fields
|
||||
.iter()
|
||||
.map(|val| self.recur(val))
|
||||
.collect(),
|
||||
.map(|val| self.recur(val, false))
|
||||
.collect::<Result<_, _>>()?,
|
||||
slice: None,
|
||||
suffix: Vec::new(),
|
||||
},
|
||||
_ => PatKind::Constant { value: cv },
|
||||
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
|
||||
// These are not allowed and will error elsewhere anyway.
|
||||
ty::Dynamic(..) => {
|
||||
self.saw_const_match_error.set(true);
|
||||
let msg = format!("`{}` cannot be used in patterns", cv.ty);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg)
|
||||
}
|
||||
PatKind::Wild
|
||||
}
|
||||
// `&str` and `&[u8]` are represented as `ConstValue::Slice`, let's keep using this
|
||||
// optimization for now.
|
||||
ty::Str => PatKind::Constant { value: cv },
|
||||
ty::Slice(elem_ty) if elem_ty == tcx.types.u8 => PatKind::Constant { value: cv },
|
||||
// `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
|
||||
// matching against references, you can only use byte string literals.
|
||||
// FIXME: clean this up, likely by permitting array patterns when matching on slices
|
||||
ty::Array(elem_ty, _) if elem_ty == tcx.types.u8 => PatKind::Constant { value: cv },
|
||||
// Cannot merge this with the catch all branch below, because the `const_deref`
|
||||
// changes the type from slice to array, and slice patterns behave differently from
|
||||
// array patterns.
|
||||
ty::Slice(..) => {
|
||||
let old = self.behind_reference.replace(true);
|
||||
let array = tcx.deref_const(self.param_env.and(cv));
|
||||
let val = PatKind::Deref {
|
||||
subpattern: Pat {
|
||||
kind: Box::new(PatKind::Slice {
|
||||
prefix: tcx
|
||||
.destructure_const(param_env.and(array))
|
||||
.fields
|
||||
.iter()
|
||||
.map(|val| self.recur(val, false))
|
||||
.collect::<Result<_, _>>()?,
|
||||
slice: None,
|
||||
suffix: vec![],
|
||||
}),
|
||||
span,
|
||||
ty: pointee_ty,
|
||||
},
|
||||
};
|
||||
self.behind_reference.set(old);
|
||||
val
|
||||
}
|
||||
// Backwards compatibility hack: support references to non-structural types.
|
||||
// We'll lower
|
||||
// this pattern to a `PartialEq::eq` comparison and `PartialEq::eq` takes a
|
||||
// reference. This makes the rest of the matching logic simpler as it doesn't have
|
||||
// to figure out how to get a reference again.
|
||||
ty::Adt(adt_def, _) if !self.type_marked_structural(pointee_ty) => {
|
||||
if self.behind_reference.get() {
|
||||
if self.include_lint_checks
|
||||
&& !self.saw_const_match_error.get()
|
||||
&& !self.saw_const_match_lint.get()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
let msg = self.adt_derive_msg(adt_def);
|
||||
self.tcx().struct_span_lint_hir(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
self.id,
|
||||
self.span,
|
||||
|lint| lint.build(&msg).emit(),
|
||||
);
|
||||
}
|
||||
PatKind::Constant { value: cv }
|
||||
} else {
|
||||
if !self.saw_const_match_error.get() {
|
||||
self.saw_const_match_error.set(true);
|
||||
let msg = self.adt_derive_msg(adt_def);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg)
|
||||
}
|
||||
}
|
||||
PatKind::Wild
|
||||
}
|
||||
}
|
||||
// All other references are converted into deref patterns and then recursively
|
||||
// convert the dereferenced constant to a pattern that is the sub-pattern of the
|
||||
// deref pattern.
|
||||
_ => {
|
||||
let old = self.behind_reference.replace(true);
|
||||
// In case there are structural-match violations somewhere in this subpattern,
|
||||
// we fall back to a const pattern. If we do not do this, we may end up with
|
||||
// a !structural-match constant that is not of reference type, which makes it
|
||||
// very hard to invoke `PartialEq::eq` on it as a fallback.
|
||||
let val = match self.recur(tcx.deref_const(self.param_env.and(cv)), false) {
|
||||
Ok(subpattern) => PatKind::Deref { subpattern },
|
||||
Err(_) => PatKind::Constant { value: cv },
|
||||
};
|
||||
self.behind_reference.set(old);
|
||||
val
|
||||
}
|
||||
},
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
|
||||
PatKind::Constant { value: cv }
|
||||
}
|
||||
ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => {
|
||||
PatKind::Constant { value: cv }
|
||||
}
|
||||
// FIXME: these can have very suprising behaviour where optimization levels or other
|
||||
// compilation choices change the runtime behaviour of the match.
|
||||
// See https://github.com/rust-lang/rust/issues/70861 for examples.
|
||||
ty::FnPtr(..) | ty::RawPtr(..) => {
|
||||
if self.include_lint_checks
|
||||
&& !self.saw_const_match_error.get()
|
||||
&& !self.saw_const_match_lint.get()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
let msg = "function pointers and unsized pointers in patterns behave \
|
||||
unpredictably and should not be relied upon. \
|
||||
See https://github.com/rust-lang/rust/issues/70861 for details.";
|
||||
tcx.struct_span_lint_hir(
|
||||
lint::builtin::POINTER_STRUCTURAL_MATCH,
|
||||
id,
|
||||
span,
|
||||
|lint| lint.build(&msg).emit(),
|
||||
);
|
||||
}
|
||||
PatKind::Constant { value: cv }
|
||||
}
|
||||
_ => {
|
||||
self.saw_const_match_error.set(true);
|
||||
let msg = format!("`{}` cannot be used in patterns", cv.ty);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg)
|
||||
}
|
||||
PatKind::Wild
|
||||
}
|
||||
};
|
||||
|
||||
Pat { span, ty: cv.ty, kind: Box::new(kind) }
|
||||
if self.include_lint_checks
|
||||
&& !self.saw_const_match_error.get()
|
||||
&& !self.saw_const_match_lint.get()
|
||||
&& mir_structural_match_violation
|
||||
// FIXME(#73448): Find a way to bring const qualification into parity with
|
||||
// `search_for_structural_match_violation` and then remove this condition.
|
||||
&& self.search_for_structural_match_violation(cv.ty).is_some()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
// Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
|
||||
// could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
|
||||
let msg = self.search_for_structural_match_violation(cv.ty).unwrap().replace(
|
||||
"in a pattern,",
|
||||
"in a pattern, the constant's initializer must be trivial or",
|
||||
);
|
||||
tcx.struct_span_lint_hir(
|
||||
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
id,
|
||||
span,
|
||||
|lint| lint.build(&msg).emit(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(Pat { span, ty: cv.ty, kind: Box::new(kind) })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2138,22 +2138,16 @@ declare_lint! {
|
|||
/// ```rust,compile_fail
|
||||
/// #![deny(indirect_structural_match)]
|
||||
///
|
||||
/// struct Plus(i32, i32);
|
||||
/// const ONE_PLUS_TWO: &&Plus = &&Plus(1, 2);
|
||||
///
|
||||
/// impl PartialEq for Plus {
|
||||
/// fn eq(&self, other: &Self) -> bool {
|
||||
/// self.0 + self.1 == other.0 + other.1
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Eq for Plus {}
|
||||
///
|
||||
/// struct NoDerive(i32);
|
||||
/// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
||||
/// impl Eq for NoDerive { }
|
||||
/// #[derive(PartialEq, Eq)]
|
||||
/// struct WrapParam<T>(T);
|
||||
/// const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
|
||||
/// fn main() {
|
||||
/// if let ONE_PLUS_TWO = &&Plus(3, 0) {
|
||||
/// println!("semantic!");
|
||||
/// } else {
|
||||
/// println!("structural!");
|
||||
/// match WRAP_INDIRECT_PARAM {
|
||||
/// WRAP_INDIRECT_PARAM => { }
|
||||
/// _ => { }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
|
@ -2170,9 +2164,8 @@ declare_lint! {
|
|||
/// [issue #62411]: https://github.com/rust-lang/rust/issues/62411
|
||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||
pub INDIRECT_STRUCTURAL_MATCH,
|
||||
// defaulting to allow until rust-lang/rust#62614 is fixed.
|
||||
Allow,
|
||||
"pattern with const indirectly referencing non-structural-match type",
|
||||
Warn,
|
||||
"constant used in pattern contains value of non-structural-match type in a field or a variant",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
|
||||
edition: None,
|
||||
|
@ -2197,6 +2190,83 @@ declare_lint! {
|
|||
report_in_external_macro
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `pointer_structural_match` lint detects pointers used in patterns whose behaviour
|
||||
/// cannot be relied upon across compiler versions and optimization levels.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(pointer_structural_match)]
|
||||
/// fn foo(a: usize, b: usize) -> usize { a + b }
|
||||
/// const FOO: fn(usize, usize) -> usize = foo;
|
||||
/// fn main() {
|
||||
/// match FOO {
|
||||
/// FOO => {},
|
||||
/// _ => {},
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Previous versions of Rust allowed function pointers and wide raw pointers in patterns.
|
||||
/// While these work in many cases as expected by users, it is possible that due to
|
||||
/// optimizations pointers are "not equal to themselves" or pointers to different functions
|
||||
/// compare as equal during runtime. This is because LLVM optimizations can deduplicate
|
||||
/// functions if their bodies are the same, thus also making pointers to these functions point
|
||||
/// to the same location. Additionally functions may get duplicated if they are instantiated
|
||||
/// in different crates and not deduplicated again via LTO.
|
||||
pub POINTER_STRUCTURAL_MATCH,
|
||||
Allow,
|
||||
"pointers are not structural-match",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/70861>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `nontrivial_structural_match` lint detects constants that are used in patterns,
|
||||
/// whose type is not structural-match and whose initializer body actually uses values
|
||||
/// that are not structural-match. So `Option<NotStruturalMatch>` is ok if the constant
|
||||
/// is just `None`.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail
|
||||
/// #![deny(nontrivial_structural_match)]
|
||||
///
|
||||
/// #[derive(Copy, Clone, Debug)]
|
||||
/// struct NoDerive(u32);
|
||||
/// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
||||
/// impl Eq for NoDerive { }
|
||||
/// fn main() {
|
||||
/// const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
|
||||
/// match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Previous versions of Rust accepted constants in patterns, even if those constants's types
|
||||
/// did not have `PartialEq` derived. Thus the compiler falls back to runtime execution of
|
||||
/// `PartialEq`, which can report that two constants are not equal even if they are
|
||||
/// bit-equivalent.
|
||||
pub NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
Warn,
|
||||
"constant used in pattern of non-structural-match type and the constant's initializer \
|
||||
expression contains values of non-structural-match types",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reference: "issue #73448 <https://github.com/rust-lang/rust/issues/73448>",
|
||||
edition: None,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `ambiguous_associated_items` lint detects ambiguity between
|
||||
/// [associated items] and [enum variants].
|
||||
|
@ -2630,6 +2700,8 @@ declare_lint_pass! {
|
|||
AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
||||
INDIRECT_STRUCTURAL_MATCH,
|
||||
POINTER_STRUCTURAL_MATCH,
|
||||
NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
SOFT_UNSTABLE,
|
||||
INLINE_NO_SANITIZE,
|
||||
ASM_SUB_REGISTER,
|
||||
|
|
|
@ -94,7 +94,7 @@ pub struct OsString {
|
|||
// `OsStr::from_inner` current implementation relies
|
||||
// on `OsStr` being layout-compatible with `Slice`.
|
||||
// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
|
||||
// Anyway, `OsStr` representation and layout are considered implementation detail, are
|
||||
// Anyway, `OsStr` representation and layout are considered implementation details, are
|
||||
// not documented and must not be relied upon.
|
||||
pub struct OsStr {
|
||||
inner: Slice,
|
||||
|
|
|
@ -12,7 +12,6 @@ fn main() {
|
|||
match None {
|
||||
consts::SOME => panic!(),
|
||||
//~^ must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
@ -20,7 +19,6 @@ fn main() {
|
|||
match None {
|
||||
<Defaulted as consts::AssocConst>::SOME => panic!(),
|
||||
//~^ must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -5,22 +5,10 @@ LL | consts::SOME => panic!(),
|
|||
| ^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/cross-crate-fail.rs:21:9
|
||||
--> $DIR/cross-crate-fail.rs:20:9
|
||||
|
|
||||
LL | <Defaulted as consts::AssocConst>::SOME => panic!(),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/cross-crate-fail.rs:13:9
|
||||
|
|
||||
LL | consts::SOME => panic!(),
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/cross-crate-fail.rs:21:9
|
||||
|
|
||||
LL | <Defaulted as consts::AssocConst>::SOME => panic!(),
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
// check-pass
|
||||
|
||||
#![warn(indirect_structural_match)]
|
||||
//~^ NOTE lint level is defined here
|
||||
|
||||
struct CustomEq;
|
||||
|
||||
impl Eq for CustomEq {}
|
||||
|
@ -32,7 +29,8 @@ fn main() {
|
|||
BAR_BAZ => panic!(),
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| WARN this was previously accepted
|
||||
//~| NOTE see issue #62411
|
||||
//~| NOTE see issue #73448
|
||||
//~| NOTE `#[warn(nontrivial_structural_match)]` on by default
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
warning: to use a constant of type `CustomEq` in a pattern, `CustomEq` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/custom-eq-branch-warn.rs:32:9
|
||||
warning: to use a constant of type `CustomEq` in a pattern, the constant's initializer must be trivial or `CustomEq` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/custom-eq-branch-warn.rs:29:9
|
||||
|
|
||||
LL | BAR_BAZ => panic!(),
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/custom-eq-branch-warn.rs:3:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[warn(nontrivial_structural_match)]` on by default
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
// FIXME: This still ICEs.
|
||||
//
|
||||
// ignore-test
|
||||
|
||||
#![deny(indirect_structural_match)]
|
||||
|
||||
// check-pass
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum O<T> {
|
||||
Some(*const T), // Can also use PhantomData<T>
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
error[E0601]: `main` function not found in crate `issue_65466`
|
||||
--> $DIR/issue-65466.rs:1:1
|
||||
|
|
||||
LL | / #![deny(indirect_structural_match)]
|
||||
LL | |
|
||||
LL | | #[derive(PartialEq, Eq)]
|
||||
LL | | enum O<T> {
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_^ consider adding a `main` function to `$DIR/issue-65466.rs`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0601`.
|
|
@ -20,7 +20,6 @@ fn main() {
|
|||
match Foo::Qux(NoEq) {
|
||||
BAR_BAZ => panic!(),
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,5 @@ error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated wit
|
|||
LL | BAR_BAZ => panic!(),
|
||||
| ^^^^^^^
|
||||
|
||||
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/no-eq-branch-fail.rs:21:9
|
||||
|
|
||||
LL | BAR_BAZ => panic!(),
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -39,51 +39,41 @@ fn main() {
|
|||
const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
|
||||
match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
const FIELD: OND = TrivialEq(Some(NoDerive)).0;
|
||||
match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
const NO_DERIVE_SOME: OND = Some(NoDerive);
|
||||
const INDIRECT: OND = NO_DERIVE_SOME;
|
||||
match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
const TUPLE: (OND, OND) = (None, Some(NoDerive));
|
||||
match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
const TYPE_ASCRIPTION: OND = Some(NoDerive): OND;
|
||||
match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
const ARRAY: [OND; 2] = [None, Some(NoDerive)];
|
||||
match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
const REPEAT: [OND; 2] = [Some(NoDerive); 2];
|
||||
match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
trait Trait: Sized { const ASSOC: Option<Self>; }
|
||||
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
|
||||
match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
const BLOCK: OND = { NoDerive; Some(NoDerive) };
|
||||
match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
const ADDR_OF: &OND = &Some(NoDerive);
|
||||
match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
|
||||
|
|
|
@ -5,61 +5,61 @@ LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"
|
|||
| ^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:45:28
|
||||
--> $DIR/reject_non_structural.rs:44:28
|
||||
|
|
||||
LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
|
||||
| ^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:51:27
|
||||
--> $DIR/reject_non_structural.rs:49:27
|
||||
|
|
||||
LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
|
||||
| ^^^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:56:36
|
||||
--> $DIR/reject_non_structural.rs:53:36
|
||||
|
|
||||
LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
|
||||
| ^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:61:28
|
||||
--> $DIR/reject_non_structural.rs:57:28
|
||||
|
|
||||
LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:66:36
|
||||
--> $DIR/reject_non_structural.rs:61:36
|
||||
|
|
||||
LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
|
||||
| ^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:71:33
|
||||
--> $DIR/reject_non_structural.rs:65:33
|
||||
|
|
||||
LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
|
||||
| ^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:71:33
|
||||
--> $DIR/reject_non_structural.rs:65:33
|
||||
|
|
||||
LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
|
||||
| ^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:79:28
|
||||
--> $DIR/reject_non_structural.rs:71:28
|
||||
|
|
||||
LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:84:28
|
||||
--> $DIR/reject_non_structural.rs:75:28
|
||||
|
|
||||
LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
|
||||
| ^^^^^
|
||||
|
||||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:89:29
|
||||
--> $DIR/reject_non_structural.rs:79:29
|
||||
|
|
||||
LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
|
||||
| ^^^^^^^
|
||||
|
@ -72,65 +72,5 @@ LL | #![warn(indirect_structural_match)]
|
|||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:40:36
|
||||
|
|
||||
LL | match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
|
||||
| ^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:45:28
|
||||
|
|
||||
LL | match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
|
||||
| ^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:51:27
|
||||
|
|
||||
LL | match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
|
||||
| ^^^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:56:36
|
||||
|
|
||||
LL | match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
|
||||
| ^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:61:28
|
||||
|
|
||||
LL | match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:66:36
|
||||
|
|
||||
LL | match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
|
||||
| ^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:71:33
|
||||
|
|
||||
LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
|
||||
| ^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:71:33
|
||||
|
|
||||
LL | match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
|
||||
| ^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:79:28
|
||||
|
|
||||
LL | match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/reject_non_structural.rs:84:28
|
||||
|
|
||||
LL | match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 20 previous errors; 1 warning emitted
|
||||
error: aborting due to 10 previous errors; 1 warning emitted
|
||||
|
||||
|
|
|
@ -1,34 +1,30 @@
|
|||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/warn_corner_cases.rs:26:47
|
||||
|
|
||||
LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
|
||||
| ^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/warn_corner_cases.rs:15:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[warn(nontrivial_structural_match)]` on by default
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
|
||||
|
||||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/warn_corner_cases.rs:32:47
|
||||
|
|
||||
LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
|
||||
| ^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
|
||||
|
||||
warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/warn_corner_cases.rs:38:47
|
||||
|
|
||||
LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ pub fn main() {
|
|||
assert_eq!(y, 2);
|
||||
let z = match &() {
|
||||
ZST => 9,
|
||||
// FIXME: this should not be required
|
||||
_ => 42,
|
||||
};
|
||||
assert_eq!(z, 9);
|
||||
let z = match b"" {
|
||||
|
|
|
@ -9,11 +9,10 @@ fn main() {
|
|||
const C: &S = &S;
|
||||
match C {
|
||||
C => {}
|
||||
//~^ ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
|
||||
//~| ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
}
|
||||
const K: &T = &T;
|
||||
match K { //~ ERROR non-exhaustive patterns: `&T` not covered
|
||||
match K {
|
||||
K => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,24 +4,5 @@ error: to use a constant of type `S` in a pattern, `S` must be annotated with `#
|
|||
LL | C => {}
|
||||
| ^
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&T` not covered
|
||||
--> $DIR/match_ice.rs:16:11
|
||||
|
|
||||
LL | struct T;
|
||||
| --------- `T` defined here
|
||||
...
|
||||
LL | match K {
|
||||
| ^ pattern `&T` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&T`
|
||||
error: aborting due to previous error
|
||||
|
||||
error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/match_ice.rs:11:9
|
||||
|
|
||||
LL | C => {}
|
||||
| ^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// run-pass
|
||||
|
||||
#![warn(pointer_structural_match)]
|
||||
#![allow(dead_code)]
|
||||
const C: *const u8 = &0;
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
// run-pass
|
||||
|
||||
#![warn(pointer_structural_match)]
|
||||
|
||||
type Func = fn(usize, usize) -> usize;
|
||||
|
||||
fn foo(a: usize, b: usize) -> usize { a + b }
|
||||
|
@ -13,8 +16,10 @@ const BAR: Func = bar;
|
|||
|
||||
fn main() {
|
||||
match test(std::env::consts::ARCH.len()) {
|
||||
FOO => println!("foo"),
|
||||
BAR => println!("bar"),
|
||||
FOO => println!("foo"), //~ WARN pointers in patterns behave unpredictably
|
||||
//~^ WARN will become a hard error
|
||||
BAR => println!("bar"), //~ WARN pointers in patterns behave unpredictably
|
||||
//~^ WARN will become a hard error
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-44333.rs:19:9
|
||||
|
|
||||
LL | FOO => println!("foo"),
|
||||
| ^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-44333.rs:3:9
|
||||
|
|
||||
LL | #![warn(pointer_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
|
||||
warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-44333.rs:21:9
|
||||
|
|
||||
LL | BAR => println!("bar"),
|
||||
| ^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
|
@ -4,7 +4,7 @@ fn main() {
|
|||
let a: &dyn Send = &7u32;
|
||||
match a {
|
||||
F => panic!(),
|
||||
//~^ ERROR trait objects cannot be used in patterns
|
||||
//~^ ERROR `&dyn Send` cannot be used in patterns
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: trait objects cannot be used in patterns
|
||||
error: `&dyn Send` cannot be used in patterns
|
||||
--> $DIR/issue-70972-dyn-trait.rs:6:9
|
||||
|
|
||||
LL | F => panic!(),
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// run-pass
|
||||
|
||||
fn main() {
|
||||
match b"." as &[u8] {
|
||||
b"." if true => {},
|
||||
b"." => panic!(),
|
||||
b".." => panic!(),
|
||||
b"" => panic!(),
|
||||
_ => panic!(),
|
||||
}
|
||||
match b"." as &[u8] {
|
||||
b"." if false => panic!(),
|
||||
b"." => {},
|
||||
b".." => panic!(),
|
||||
b"" => panic!(),
|
||||
_ => panic!(),
|
||||
}
|
||||
match b".." as &[u8] {
|
||||
b"." if true => panic!(), // the miscompile caused this arm to be reached
|
||||
b"." => panic!(),
|
||||
b".." => {},
|
||||
b"" => panic!(),
|
||||
_ => panic!(),
|
||||
}
|
||||
match b".." as &[u8] {
|
||||
b"." if false => panic!(),
|
||||
b"." => panic!(),
|
||||
b".." => {},
|
||||
b"" => panic!(),
|
||||
_ => panic!(),
|
||||
}
|
||||
match b"" as &[u8] {
|
||||
b"." if true => panic!(),
|
||||
b"." => panic!(),
|
||||
b".." => panic!(),
|
||||
b"" => {},
|
||||
_ => panic!(),
|
||||
}
|
||||
match b"" as &[u8] {
|
||||
b"." if false => panic!(),
|
||||
b"." => panic!(),
|
||||
b".." => panic!(),
|
||||
b"" => {},
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
|
@ -1,10 +1,4 @@
|
|||
// failure-status: 101
|
||||
// rustc-env:RUST_BACKTRACE=0
|
||||
// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET"
|
||||
// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS"
|
||||
// normalize-stderr-test "/_match.rs:[0-9]+:[0-9]+" -> "/_match.rs:LL:CC"
|
||||
|
||||
// This is a repro test for an ICE in our pattern handling of constants.
|
||||
// check-pass
|
||||
|
||||
const FOO: &&&u32 = &&&42;
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', compiler/rustc_mir_build/src/thir/pattern/_match.rs:LL:CC
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
|
||||
error: internal compiler error: unexpected panic
|
||||
|
||||
note: the compiler unexpectedly panicked. this is a bug.
|
||||
|
||||
note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
|
||||
|
||||
note: rustc VERSION running on TARGET
|
||||
|
||||
note: compiler flags: FLAGS
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
fn main() {
|
||||
const C: impl Copy = 0;
|
||||
match C {
|
||||
C | _ => {} //~ ERROR: opaque types cannot be used in patterns
|
||||
C | //~ ERROR: `impl Copy` cannot be used in patterns
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
error: opaque types cannot be used in patterns
|
||||
error: `impl Copy` cannot be used in patterns
|
||||
--> $DIR/issue-71042-opaquely-typed-constant-used-in-pattern.rs:7:9
|
||||
|
|
||||
LL | C | _ => {}
|
||||
LL | C |
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
|
@ -160,7 +160,7 @@ fn main() {
|
|||
match &0 {
|
||||
&42 => {}
|
||||
&FOO => {} //~ ERROR unreachable pattern
|
||||
BAR => {} // Not detected as unreachable because `try_eval_bits` fails on `BAR`.
|
||||
BAR => {} //~ ERROR unreachable pattern
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,12 @@ error: unreachable pattern
|
|||
LL | &FOO => {}
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
error: unreachable pattern
|
||||
--> $DIR/exhaustive_integer_patterns.rs:163:9
|
||||
|
|
||||
LL | BAR => {}
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
||||
|
|
|
@ -6,19 +6,19 @@ fn main() {
|
|||
match s {
|
||||
MAGIC_TEST => (),
|
||||
[0x00, 0x00, 0x00, 0x00] => (),
|
||||
[4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
|
||||
[4, 5, 6, 7] => (), //~ ERROR unreachable pattern
|
||||
_ => (),
|
||||
}
|
||||
match s {
|
||||
[0x00, 0x00, 0x00, 0x00] => (),
|
||||
MAGIC_TEST => (),
|
||||
[4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
|
||||
[4, 5, 6, 7] => (), //~ ERROR unreachable pattern
|
||||
_ => (),
|
||||
}
|
||||
match s {
|
||||
[0x00, 0x00, 0x00, 0x00] => (),
|
||||
[4, 5, 6, 7] => (),
|
||||
MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
|
||||
MAGIC_TEST => (), //~ ERROR unreachable pattern
|
||||
_ => (),
|
||||
}
|
||||
const FOO: [u32; 1] = [4];
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const-2.rs:28:9
|
||||
--> $DIR/slice-pattern-const-2.rs:9:9
|
||||
|
|
||||
LL | FOO => (),
|
||||
| ^^^
|
||||
LL | [4, 5, 6, 7] => (),
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/slice-pattern-const-2.rs:1:9
|
||||
|
@ -10,5 +10,23 @@ note: the lint level is defined here
|
|||
LL | #![deny(unreachable_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const-2.rs:15:9
|
||||
|
|
||||
LL | [4, 5, 6, 7] => (),
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const-2.rs:21:9
|
||||
|
|
||||
LL | MAGIC_TEST => (),
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const-2.rs:28:9
|
||||
|
|
||||
LL | FOO => (),
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -6,19 +6,19 @@ fn main() {
|
|||
match s {
|
||||
MAGIC_TEST => (),
|
||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
||||
["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
|
||||
["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern
|
||||
_ => (),
|
||||
}
|
||||
match s {
|
||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
||||
MAGIC_TEST => (),
|
||||
["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
|
||||
["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern
|
||||
_ => (),
|
||||
}
|
||||
match s {
|
||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
||||
["4", "5", "6", "7"] => (),
|
||||
MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
|
||||
MAGIC_TEST => (), //~ ERROR unreachable pattern
|
||||
_ => (),
|
||||
}
|
||||
const FOO: [&str; 1] = ["boo"];
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const-3.rs:28:9
|
||||
--> $DIR/slice-pattern-const-3.rs:9:9
|
||||
|
|
||||
LL | FOO => (),
|
||||
| ^^^
|
||||
LL | ["4", "5", "6", "7"] => (),
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/slice-pattern-const-3.rs:1:9
|
||||
|
@ -10,5 +10,23 @@ note: the lint level is defined here
|
|||
LL | #![deny(unreachable_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const-3.rs:15:9
|
||||
|
|
||||
LL | ["4", "5", "6", "7"] => (),
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const-3.rs:21:9
|
||||
|
|
||||
LL | MAGIC_TEST => (),
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/slice-pattern-const-3.rs:28:9
|
||||
|
|
||||
LL | FOO => (),
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
|
|
@ -83,14 +83,38 @@ fn main() {
|
|||
|
||||
const CONST: &[bool] = &[true];
|
||||
match s {
|
||||
//~^ ERROR `&[..]` not covered
|
||||
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||
&[true] => {}
|
||||
}
|
||||
match s {
|
||||
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||
CONST => {}
|
||||
}
|
||||
match s {
|
||||
//~^ ERROR `&[true]` not covered
|
||||
[] => {},
|
||||
[false] => {},
|
||||
CONST => {},
|
||||
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||
CONST => {}
|
||||
&[false] => {}
|
||||
}
|
||||
match s {
|
||||
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||
&[false] => {}
|
||||
CONST => {}
|
||||
}
|
||||
match s {
|
||||
//~^ ERROR `&[_, _, ..]` not covered
|
||||
&[] => {}
|
||||
CONST => {}
|
||||
}
|
||||
match s {
|
||||
//~^ ERROR `&[false]` not covered
|
||||
&[] => {}
|
||||
CONST => {}
|
||||
&[_, _, ..] => {}
|
||||
}
|
||||
match s {
|
||||
[] => {}
|
||||
[false] => {}
|
||||
CONST => {}
|
||||
[_, _, ..] => {}
|
||||
}
|
||||
const CONST1: &[bool; 1] = &[true];
|
||||
|
|
|
@ -115,26 +115,62 @@ LL | match s {
|
|||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&[bool]`
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[..]` not covered
|
||||
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:85:11
|
||||
|
|
||||
LL | match s {
|
||||
| ^ pattern `&[..]` not covered
|
||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&[bool]`
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[true]` not covered
|
||||
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:89:11
|
||||
|
|
||||
LL | match s {
|
||||
| ^ pattern `&[true]` not covered
|
||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&[bool]`
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:93:11
|
||||
|
|
||||
LL | match s {
|
||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&[bool]`
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:98:11
|
||||
|
|
||||
LL | match s {
|
||||
| ^ patterns `&[]` and `&[_, _, ..]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&[bool]`
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:103:11
|
||||
|
|
||||
LL | match s {
|
||||
| ^ pattern `&[_, _, ..]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&[bool]`
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:97:11
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:108:11
|
||||
|
|
||||
LL | match s {
|
||||
| ^ pattern `&[false]` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&[bool]`
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
||||
--> $DIR/slice-patterns-exhaustiveness.rs:121:11
|
||||
|
|
||||
LL | match s1 {
|
||||
| ^^ pattern `&[false]` not covered
|
||||
|
@ -142,6 +178,6 @@ LL | match s1 {
|
|||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `&[bool; 1]`
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: aborting due to 20 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
// run-pass
|
||||
|
||||
#![warn(pointer_structural_match)]
|
||||
|
||||
struct NoDerive(i32);
|
||||
|
||||
// This impl makes NoDerive irreflexive
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
// run-pass
|
||||
|
||||
#![warn(pointer_structural_match)]
|
||||
|
||||
struct NoDerive(i32);
|
||||
|
||||
// This impl makes NoDerive irreflexive
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
// run-pass
|
||||
|
||||
#![warn(pointer_structural_match)]
|
||||
|
||||
struct NoDerive(i32);
|
||||
|
||||
// This impl makes NoDerive irreflexive
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
// run-pass
|
||||
|
||||
#![warn(pointer_structural_match)]
|
||||
|
||||
struct NoDerive(i32);
|
||||
|
||||
// This impl makes NoDerive irreflexive
|
||||
|
|
|
@ -21,7 +21,6 @@ fn main() {
|
|||
match WRAP_DIRECT_INLINE {
|
||||
WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
_ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,5 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be ann
|
|||
LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/cant-hide-behind-direct-struct-embedded.rs:22:9
|
||||
|
|
||||
LL | WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ fn main() {
|
|||
match WRAP_DIRECT_PARAM {
|
||||
WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
_ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,5 @@ error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be ann
|
|||
LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/cant-hide-behind-direct-struct-param.rs:22:9
|
||||
|
|
||||
LL | WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
|||
match WRAP_DOUBLY_INDIRECT_INLINE {
|
||||
WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| WARN will become a hard error in a future release
|
||||
//~| WARN this was previously accepted
|
||||
_ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
|||
match WRAP_DOUBLY_INDIRECT_PARAM {
|
||||
WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| WARN will become a hard error in a future release
|
||||
//~| WARN this was previously accepted
|
||||
_ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
|||
match WRAP_INDIRECT_INLINE {
|
||||
WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| WARN will become a hard error in a future release
|
||||
//~| WARN this was previously accepted
|
||||
_ => { println!("WRAP_INDIRECT_INLINE did not match itself"); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
|||
match WRAP_INDIRECT_PARAM {
|
||||
WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| WARN will become a hard error in a future release
|
||||
//~| WARN this was previously accepted
|
||||
_ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
// Issue 62307 pointed out a case where the structural-match checking
|
||||
// was too shallow.
|
||||
#![warn(indirect_structural_match)]
|
||||
#![warn(indirect_structural_match, nontrivial_structural_match)]
|
||||
// run-pass
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -30,14 +30,14 @@ fn main() {
|
|||
match RR_B0 {
|
||||
RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| WARN will become a hard error in a future release
|
||||
//~| WARN this was previously accepted
|
||||
_ => { }
|
||||
}
|
||||
|
||||
match RR_B1 {
|
||||
RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
|
||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| WARN will become a hard error in a future release
|
||||
//~| WARN this was previously accepted
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0);
|
|||
note: the lint level is defined here
|
||||
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
|
||||
|
|
||||
LL | #![warn(indirect_structural_match)]
|
||||
LL | #![warn(indirect_structural_match, nontrivial_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
// cover the case this hit; I've since expanded it accordingly, but the
|
||||
// experience left me wary of leaving this regression test out.)
|
||||
|
||||
#![warn(pointer_structural_match)]
|
||||
|
||||
#[derive(Eq)]
|
||||
struct A {
|
||||
a: i64
|
||||
|
@ -31,6 +33,8 @@ fn main() {
|
|||
let s = B(my_fn);
|
||||
match s {
|
||||
B(TEST) => println!("matched"),
|
||||
//~^ WARN pointers in patterns behave unpredictably
|
||||
//~| WARN this was previously accepted by the compiler but is being phased out
|
||||
_ => panic!("didn't match")
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
--> $DIR/issue-63479-match-fnptr.rs:35:7
|
||||
|
|
||||
LL | B(TEST) => println!("matched"),
|
||||
| ^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-63479-match-fnptr.rs:8:9
|
||||
|
|
||||
LL | #![warn(pointer_structural_match)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
|
@ -12,7 +12,6 @@ fn main() {
|
|||
match y {
|
||||
FOO => { }
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
_ => { }
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | FOO => { }
|
|||
| ^^^
|
||||
|
||||
warning: floating-point types cannot be used in patterns
|
||||
--> $DIR/match-forbidden-without-eq.rs:21:9
|
||||
--> $DIR/match-forbidden-without-eq.rs:20:9
|
||||
|
|
||||
LL | f32::INFINITY => { }
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -14,14 +14,8 @@ LL | f32::INFINITY => { }
|
|||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
|
||||
|
||||
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/match-forbidden-without-eq.rs:13:9
|
||||
|
|
||||
LL | FOO => { }
|
||||
| ^^^
|
||||
|
||||
warning: floating-point types cannot be used in patterns
|
||||
--> $DIR/match-forbidden-without-eq.rs:21:9
|
||||
--> $DIR/match-forbidden-without-eq.rs:20:9
|
||||
|
|
||||
LL | f32::INFINITY => { }
|
||||
| ^^^^^^^^^^^^^
|
||||
|
@ -29,5 +23,5 @@ LL | f32::INFINITY => { }
|
|||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
|
||||
|
||||
error: aborting due to 2 previous errors; 2 warnings emitted
|
||||
error: aborting due to previous error; 2 warnings emitted
|
||||
|
||||
|
|
|
@ -15,6 +15,5 @@ fn main() {
|
|||
match [B(1)] {
|
||||
FOO => { }
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,5 @@ error: to use a constant of type `B` in a pattern, `B` must be annotated with `#
|
|||
LL | FOO => { }
|
||||
| ^^^
|
||||
|
||||
error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9
|
||||
|
|
||||
LL | FOO => { }
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ fn main() {
|
|||
match y {
|
||||
FOO => { }
|
||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,5 @@ error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated wit
|
|||
LL | FOO => { }
|
||||
| ^^^
|
||||
|
||||
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
--> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
|
||||
|
|
||||
LL | FOO => { }
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@ const LEAK_FREE: Bar = leak_free();
|
|||
fn leak_free_test() {
|
||||
match todo!() {
|
||||
LEAK_FREE => (),
|
||||
//~^ opaque types cannot be used in patterns
|
||||
//~^ `impl Send` cannot be used in patterns
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: opaque types cannot be used in patterns
|
||||
error: `impl Send` cannot be used in patterns
|
||||
--> $DIR/structural-match-no-leak.rs:14:9
|
||||
|
|
||||
LL | LEAK_FREE => (),
|
||||
|
|
|
@ -13,9 +13,9 @@ const VALUE: Foo = value();
|
|||
fn test() {
|
||||
match todo!() {
|
||||
VALUE => (),
|
||||
//~^ opaque types cannot be used in patterns
|
||||
//~^ `impl Send` cannot be used in patterns
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error: opaque types cannot be used in patterns
|
||||
error: `impl Send` cannot be used in patterns
|
||||
--> $DIR/structural-match.rs:15:9
|
||||
|
|
||||
LL | VALUE => (),
|
||||
|
|
|
@ -8,7 +8,6 @@ const C: U = U { a: 10 };
|
|||
fn main() {
|
||||
match C {
|
||||
C => {} //~ ERROR cannot use unions in constant patterns
|
||||
//~| ERROR cannot use unions in constant patterns
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,5 @@ error: cannot use unions in constant patterns
|
|||
LL | C => {}
|
||||
| ^
|
||||
|
||||
error: cannot use unions in constant patterns
|
||||
--> $DIR/union-const-pat.rs:10:9
|
||||
|
|
||||
LL | C => {}
|
||||
| ^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
Loading…
Reference in New Issue