Auto merge of #70743 - oli-obk:eager_const_to_pat_conversion, r=eddyb
Fully destructure constants into patterns
r? `@varkor`
as discussed in 192789924
we should probably crater it once reviewed
This commit is contained in:
commit
fd15e6180d
66 changed files with 796 additions and 435 deletions
|
@ -742,6 +742,14 @@ rustc_queries! {
|
||||||
desc { "destructure constant" }
|
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> {
|
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
|
||||||
desc { "get a &core::panic::Location referring to a span" }
|
desc { "get a &core::panic::Location referring to a span" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,14 @@
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
use rustc_hir::Mutability;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
|
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 error;
|
||||||
mod eval_queries;
|
mod eval_queries;
|
||||||
|
@ -67,3 +70,39 @@ pub(crate) fn destructure_const<'tcx>(
|
||||||
|
|
||||||
mir::DestructuredConst { variant, fields }
|
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();
|
let (param_env, value) = param_env_and_value.into_parts();
|
||||||
const_eval::destructure_const(tcx, param_env, value)
|
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_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_middle::mir::Field;
|
use rustc_middle::mir::Field;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
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_session::lint;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::traits::predicate_for_trait_def;
|
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={:#?} id={:?}", cv, id);
|
||||||
debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
|
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);
|
let mut convert = ConstToPat::new(self, id, span, infcx);
|
||||||
convert.to_pat(cv, mir_structural_match_violation)
|
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,
|
span: Span,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
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
|
// we will not subsequently issue an irrelevant lint for the same const
|
||||||
// value.
|
// value.
|
||||||
saw_const_match_error: Cell<bool>,
|
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.
|
// inference context used for checking `T: Structural` bounds.
|
||||||
infcx: InferCtxt<'a, 'tcx>,
|
infcx: InferCtxt<'a, 'tcx>,
|
||||||
|
|
||||||
include_lint_checks: bool,
|
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> {
|
impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
fn new(
|
fn new(
|
||||||
pat_ctxt: &PatCtxt<'_, 'tcx>,
|
pat_ctxt: &PatCtxt<'_, 'tcx>,
|
||||||
|
@ -65,6 +95,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
param_env: pat_ctxt.param_env,
|
param_env: pat_ctxt.param_env,
|
||||||
include_lint_checks: pat_ctxt.include_lint_checks,
|
include_lint_checks: pat_ctxt.include_lint_checks,
|
||||||
saw_const_match_error: Cell::new(false),
|
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
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_for_structural_match_violation(
|
fn adt_derive_msg(&self, adt_def: &AdtDef) -> String {
|
||||||
&self,
|
let path = self.tcx().def_path_str(adt_def.did);
|
||||||
ty: Ty<'tcx>,
|
format!(
|
||||||
) -> Option<traits::NonStructuralMatchTy<'tcx>> {
|
"to use a constant of type `{}` in a pattern, \
|
||||||
traits::search_for_structural_match_violation(self.id, self.span, self.tcx(), ty)
|
`{}` 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 {
|
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
|
// once indirect_structural_match is a full fledged error, this
|
||||||
// level of indirection can be eliminated
|
// 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 self.include_lint_checks && !self.saw_const_match_error.get() {
|
||||||
// If we were able to successfully convert the const to some pat,
|
// 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;
|
return inlined_const_as_pat;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(non_sm_ty) = structural {
|
if let Some(msg) = structural {
|
||||||
let msg = with_no_trimmed_paths(|| match non_sm_ty {
|
if !self.type_may_have_partial_eq_impl(cv.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 {
|
|
||||||
// span_fatal avoids ICE from resolution of non-existent method (rare case).
|
// span_fatal avoids ICE from resolution of non-existent method (rare case).
|
||||||
self.tcx().sess.span_fatal(self.span, &msg);
|
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(
|
self.tcx().struct_span_lint_hir(
|
||||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||||
self.id,
|
self.id,
|
||||||
|
@ -200,19 +206,57 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
inlined_const_as_pat
|
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).
|
// 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 id = self.id;
|
||||||
let span = self.span;
|
let span = self.span;
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let param_env = self.param_env;
|
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()
|
vals.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, val)| {
|
.map(|(idx, val)| {
|
||||||
let field = Field::new(idx);
|
let field = Field::new(idx);
|
||||||
FieldPat { field, pattern: self.recur(val) }
|
Ok(FieldPat { field, pattern: self.recur(val, false)? })
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
@ -230,10 +274,63 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
ty::Adt(adt_def, _) if adt_def.is_union() => {
|
ty::Adt(adt_def, _) if adt_def.is_union() => {
|
||||||
// Matching on union fields is unsafe, we can't hide it in constants
|
// Matching on union fields is unsafe, we can't hide it in constants
|
||||||
self.saw_const_match_error.set(true);
|
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
|
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) => {
|
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);
|
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, cv.ty);
|
||||||
let path = tcx.def_path_str(adt_def.did);
|
let path = tcx.def_path_str(adt_def.did);
|
||||||
|
@ -243,29 +340,11 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
path, path,
|
path, path,
|
||||||
);
|
);
|
||||||
self.saw_const_match_error.set(true);
|
self.saw_const_match_error.set(true);
|
||||||
tcx.sess.span_err(span, &msg);
|
if self.include_lint_checks {
|
||||||
PatKind::Wild
|
tcx.sess.span_err(span, &msg);
|
||||||
}
|
} else {
|
||||||
// keep old code until future-compat upgraded to errors.
|
tcx.sess.delay_span_bug(span, &msg)
|
||||||
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
|
PatKind::Wild
|
||||||
}
|
}
|
||||||
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
|
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
|
||||||
|
@ -276,30 +355,181 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
variant_index: destructured
|
variant_index: destructured
|
||||||
.variant
|
.variant
|
||||||
.expect("destructed const of adt without variant id"),
|
.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));
|
let destructured = tcx.destructure_const(param_env.and(cv));
|
||||||
PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
|
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) }
|
|
||||||
}
|
}
|
||||||
ty::Array(..) => PatKind::Array {
|
ty::Array(..) => PatKind::Array {
|
||||||
prefix: tcx
|
prefix: tcx
|
||||||
.destructure_const(param_env.and(cv))
|
.destructure_const(param_env.and(cv))
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|val| self.recur(val))
|
.map(|val| self.recur(val, false))
|
||||||
.collect(),
|
.collect::<Result<_, _>>()?,
|
||||||
slice: None,
|
slice: None,
|
||||||
suffix: Vec::new(),
|
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
|
/// ```rust,compile_fail
|
||||||
/// #![deny(indirect_structural_match)]
|
/// #![deny(indirect_structural_match)]
|
||||||
///
|
///
|
||||||
/// struct Plus(i32, i32);
|
/// struct NoDerive(i32);
|
||||||
/// const ONE_PLUS_TWO: &&Plus = &&Plus(1, 2);
|
/// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
|
||||||
///
|
/// impl Eq for NoDerive { }
|
||||||
/// impl PartialEq for Plus {
|
/// #[derive(PartialEq, Eq)]
|
||||||
/// fn eq(&self, other: &Self) -> bool {
|
/// struct WrapParam<T>(T);
|
||||||
/// self.0 + self.1 == other.0 + other.1
|
/// const WRAP_INDIRECT_PARAM: & &WrapParam<NoDerive> = & &WrapParam(NoDerive(0));
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// impl Eq for Plus {}
|
|
||||||
///
|
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// if let ONE_PLUS_TWO = &&Plus(3, 0) {
|
/// match WRAP_INDIRECT_PARAM {
|
||||||
/// println!("semantic!");
|
/// WRAP_INDIRECT_PARAM => { }
|
||||||
/// } else {
|
/// _ => { }
|
||||||
/// println!("structural!");
|
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -2170,9 +2164,8 @@ declare_lint! {
|
||||||
/// [issue #62411]: https://github.com/rust-lang/rust/issues/62411
|
/// [issue #62411]: https://github.com/rust-lang/rust/issues/62411
|
||||||
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
/// [future-incompatible]: ../index.md#future-incompatible-lints
|
||||||
pub INDIRECT_STRUCTURAL_MATCH,
|
pub INDIRECT_STRUCTURAL_MATCH,
|
||||||
// defaulting to allow until rust-lang/rust#62614 is fixed.
|
Warn,
|
||||||
Allow,
|
"constant used in pattern contains value of non-structural-match type in a field or a variant",
|
||||||
"pattern with const indirectly referencing non-structural-match type",
|
|
||||||
@future_incompatible = FutureIncompatibleInfo {
|
@future_incompatible = FutureIncompatibleInfo {
|
||||||
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
|
reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
|
||||||
edition: None,
|
edition: None,
|
||||||
|
@ -2197,6 +2190,83 @@ declare_lint! {
|
||||||
report_in_external_macro
|
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! {
|
declare_lint! {
|
||||||
/// The `ambiguous_associated_items` lint detects ambiguity between
|
/// The `ambiguous_associated_items` lint detects ambiguity between
|
||||||
/// [associated items] and [enum variants].
|
/// [associated items] and [enum variants].
|
||||||
|
@ -2630,6 +2700,8 @@ declare_lint_pass! {
|
||||||
AMBIGUOUS_ASSOCIATED_ITEMS,
|
AMBIGUOUS_ASSOCIATED_ITEMS,
|
||||||
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
MUTABLE_BORROW_RESERVATION_CONFLICT,
|
||||||
INDIRECT_STRUCTURAL_MATCH,
|
INDIRECT_STRUCTURAL_MATCH,
|
||||||
|
POINTER_STRUCTURAL_MATCH,
|
||||||
|
NONTRIVIAL_STRUCTURAL_MATCH,
|
||||||
SOFT_UNSTABLE,
|
SOFT_UNSTABLE,
|
||||||
INLINE_NO_SANITIZE,
|
INLINE_NO_SANITIZE,
|
||||||
ASM_SUB_REGISTER,
|
ASM_SUB_REGISTER,
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub struct OsString {
|
||||||
// `OsStr::from_inner` current implementation relies
|
// `OsStr::from_inner` current implementation relies
|
||||||
// on `OsStr` being layout-compatible with `Slice`.
|
// on `OsStr` being layout-compatible with `Slice`.
|
||||||
// When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
|
// 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.
|
// not documented and must not be relied upon.
|
||||||
pub struct OsStr {
|
pub struct OsStr {
|
||||||
inner: Slice,
|
inner: Slice,
|
||||||
|
|
|
@ -12,7 +12,6 @@ fn main() {
|
||||||
match None {
|
match None {
|
||||||
consts::SOME => panic!(),
|
consts::SOME => panic!(),
|
||||||
//~^ must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ must be annotated with `#[derive(PartialEq, Eq)]`
|
||||||
//~| must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +19,6 @@ fn main() {
|
||||||
match None {
|
match None {
|
||||||
<Defaulted as consts::AssocConst>::SOME => panic!(),
|
<Defaulted as consts::AssocConst>::SOME => panic!(),
|
||||||
//~^ must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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)]`
|
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!(),
|
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)]`
|
error: aborting due to 2 previous errors
|
||||||
--> $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
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
// check-pass
|
// check-pass
|
||||||
|
|
||||||
#![warn(indirect_structural_match)]
|
|
||||||
//~^ NOTE lint level is defined here
|
|
||||||
|
|
||||||
struct CustomEq;
|
struct CustomEq;
|
||||||
|
|
||||||
impl Eq for CustomEq {}
|
impl Eq for CustomEq {}
|
||||||
|
@ -32,7 +29,8 @@ fn main() {
|
||||||
BAR_BAZ => panic!(),
|
BAR_BAZ => panic!(),
|
||||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
||||||
//~| WARN this was previously accepted
|
//~| 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)]`
|
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:32:9
|
--> $DIR/custom-eq-branch-warn.rs:29:9
|
||||||
|
|
|
|
||||||
LL | BAR_BAZ => panic!(),
|
LL | BAR_BAZ => panic!(),
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
= note: `#[warn(nontrivial_structural_match)]` on by default
|
||||||
--> $DIR/custom-eq-branch-warn.rs:3:9
|
|
||||||
|
|
|
||||||
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!
|
= 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
|
warning: 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
// FIXME: This still ICEs.
|
|
||||||
//
|
|
||||||
// ignore-test
|
|
||||||
|
|
||||||
#![deny(indirect_structural_match)]
|
#![deny(indirect_structural_match)]
|
||||||
|
|
||||||
|
// check-pass
|
||||||
|
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq)]
|
||||||
enum O<T> {
|
enum O<T> {
|
||||||
Some(*const T), // Can also use PhantomData<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) {
|
match Foo::Qux(NoEq) {
|
||||||
BAR_BAZ => panic!(),
|
BAR_BAZ => panic!(),
|
||||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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!(),
|
LL | BAR_BAZ => panic!(),
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
||||||
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
|
error: aborting due to previous error
|
||||||
--> $DIR/no-eq-branch-fail.rs:21:9
|
|
||||||
|
|
|
||||||
LL | BAR_BAZ => panic!(),
|
|
||||||
| ^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -39,51 +39,41 @@ fn main() {
|
||||||
const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
|
const ENUM: Derive<NoDerive> = Derive::Some(NoDerive);
|
||||||
match Derive::Some(NoDerive) { ENUM => dbg!(ENUM), _ => panic!("whoops"), };
|
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)]`
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
|
|
||||||
const FIELD: OND = TrivialEq(Some(NoDerive)).0;
|
const FIELD: OND = TrivialEq(Some(NoDerive)).0;
|
||||||
match Some(NoDerive) { FIELD => dbg!(FIELD), _ => panic!("whoops"), };
|
match Some(NoDerive) { FIELD => dbg!(FIELD), _ => 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)]`
|
|
||||||
|
|
||||||
const NO_DERIVE_SOME: OND = Some(NoDerive);
|
const NO_DERIVE_SOME: OND = Some(NoDerive);
|
||||||
const INDIRECT: OND = NO_DERIVE_SOME;
|
const INDIRECT: OND = NO_DERIVE_SOME;
|
||||||
match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => panic!("whoops"), };
|
match Some(NoDerive) {INDIRECT => dbg!(INDIRECT), _ => 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)]`
|
|
||||||
|
|
||||||
const TUPLE: (OND, OND) = (None, Some(NoDerive));
|
const TUPLE: (OND, OND) = (None, Some(NoDerive));
|
||||||
match (None, Some(NoDerive)) { TUPLE => dbg!(TUPLE), _ => panic!("whoops"), };
|
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)]`
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
|
|
||||||
const TYPE_ASCRIPTION: OND = Some(NoDerive): OND;
|
const TYPE_ASCRIPTION: OND = Some(NoDerive): OND;
|
||||||
match Some(NoDerive) { TYPE_ASCRIPTION => dbg!(TYPE_ASCRIPTION), _ => panic!("whoops"), };
|
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)]`
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
|
|
||||||
const ARRAY: [OND; 2] = [None, Some(NoDerive)];
|
const ARRAY: [OND; 2] = [None, Some(NoDerive)];
|
||||||
match [None, Some(NoDerive)] { ARRAY => dbg!(ARRAY), _ => panic!("whoops"), };
|
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)]`
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
|
|
||||||
const REPEAT: [OND; 2] = [Some(NoDerive); 2];
|
const REPEAT: [OND; 2] = [Some(NoDerive); 2];
|
||||||
match [Some(NoDerive); 2] { REPEAT => dbg!(REPEAT), _ => panic!("whoops"), };
|
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)]`
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
|
|
||||||
trait Trait: Sized { const ASSOC: Option<Self>; }
|
trait Trait: Sized { const ASSOC: Option<Self>; }
|
||||||
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
|
impl Trait for NoDerive { const ASSOC: Option<NoDerive> = Some(NoDerive); }
|
||||||
match Some(NoDerive) { NoDerive::ASSOC => dbg!(NoDerive::ASSOC), _ => panic!("whoops"), };
|
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)]`
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
|
|
||||||
const BLOCK: OND = { NoDerive; Some(NoDerive) };
|
const BLOCK: OND = { NoDerive; Some(NoDerive) };
|
||||||
match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => panic!("whoops"), };
|
match Some(NoDerive) { BLOCK => dbg!(BLOCK), _ => 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)]`
|
|
||||||
|
|
||||||
const ADDR_OF: &OND = &Some(NoDerive);
|
const ADDR_OF: &OND = &Some(NoDerive);
|
||||||
match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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)]`
|
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"), };
|
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!
|
= 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 #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)]`
|
error: aborting due to 10 previous errors; 1 warning emitted
|
||||||
--> $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
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
--> $DIR/warn_corner_cases.rs:26:47
|
||||||
|
|
|
|
||||||
LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
|
LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
= note: `#[warn(nontrivial_structural_match)]` on by default
|
||||||
--> $DIR/warn_corner_cases.rs:15:9
|
|
||||||
|
|
|
||||||
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!
|
= 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
|
--> $DIR/warn_corner_cases.rs:32:47
|
||||||
|
|
|
|
||||||
LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
|
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!
|
= 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
|
--> $DIR/warn_corner_cases.rs:38:47
|
||||||
|
|
|
|
||||||
LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
|
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!
|
= 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
|
warning: 3 warnings emitted
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@ pub fn main() {
|
||||||
assert_eq!(y, 2);
|
assert_eq!(y, 2);
|
||||||
let z = match &() {
|
let z = match &() {
|
||||||
ZST => 9,
|
ZST => 9,
|
||||||
// FIXME: this should not be required
|
|
||||||
_ => 42,
|
|
||||||
};
|
};
|
||||||
assert_eq!(z, 9);
|
assert_eq!(z, 9);
|
||||||
let z = match b"" {
|
let z = match b"" {
|
||||||
|
|
|
@ -9,11 +9,10 @@ fn main() {
|
||||||
const C: &S = &S;
|
const C: &S = &S;
|
||||||
match C {
|
match C {
|
||||||
C => {}
|
C => {}
|
||||||
//~^ ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
|
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
||||||
//~| ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
|
|
||||||
}
|
}
|
||||||
const K: &T = &T;
|
const K: &T = &T;
|
||||||
match K { //~ ERROR non-exhaustive patterns: `&T` not covered
|
match K {
|
||||||
K => {}
|
K => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,5 @@ error: to use a constant of type `S` in a pattern, `S` must be annotated with `#
|
||||||
LL | C => {}
|
LL | C => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&T` not covered
|
error: aborting due to previous error
|
||||||
--> $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: 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
|
// run-pass
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
const C: *const u8 = &0;
|
const C: *const u8 = &0;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
|
|
||||||
type Func = fn(usize, usize) -> usize;
|
type Func = fn(usize, usize) -> usize;
|
||||||
|
|
||||||
fn foo(a: usize, b: usize) -> usize { a + b }
|
fn foo(a: usize, b: usize) -> usize { a + b }
|
||||||
|
@ -13,8 +16,10 @@ const BAR: Func = bar;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match test(std::env::consts::ARCH.len()) {
|
match test(std::env::consts::ARCH.len()) {
|
||||||
FOO => println!("foo"),
|
FOO => println!("foo"), //~ WARN pointers in patterns behave unpredictably
|
||||||
BAR => println!("bar"),
|
//~^ WARN will become a hard error
|
||||||
|
BAR => println!("bar"), //~ WARN pointers in patterns behave unpredictably
|
||||||
|
//~^ WARN will become a hard error
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/test/ui/issues/issue-44333.stderr
Normal file
25
src/test/ui/issues/issue-44333.stderr
Normal file
|
@ -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;
|
let a: &dyn Send = &7u32;
|
||||||
match a {
|
match a {
|
||||||
F => panic!(),
|
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
|
--> $DIR/issue-70972-dyn-trait.rs:6:9
|
||||||
|
|
|
|
||||||
LL | F => panic!(),
|
LL | F => panic!(),
|
||||||
|
|
46
src/test/ui/match/pattern-deref-miscompile.rs
Normal file
46
src/test/ui/match/pattern-deref-miscompile.rs
Normal file
|
@ -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
|
// check-pass
|
||||||
// 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.
|
|
||||||
|
|
||||||
const FOO: &&&u32 = &&&42;
|
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() {
|
fn main() {
|
||||||
const C: impl Copy = 0;
|
const C: impl Copy = 0;
|
||||||
match C {
|
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
|
--> $DIR/issue-71042-opaquely-typed-constant-used-in-pattern.rs:7:9
|
||||||
|
|
|
|
||||||
LL | C | _ => {}
|
LL | C |
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
|
@ -160,7 +160,7 @@ fn main() {
|
||||||
match &0 {
|
match &0 {
|
||||||
&42 => {}
|
&42 => {}
|
||||||
&FOO => {} //~ ERROR unreachable pattern
|
&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 => {}
|
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`.
|
For more information about this error, try `rustc --explain E0004`.
|
||||||
|
|
|
@ -6,19 +6,19 @@ fn main() {
|
||||||
match s {
|
match s {
|
||||||
MAGIC_TEST => (),
|
MAGIC_TEST => (),
|
||||||
[0x00, 0x00, 0x00, 0x00] => (),
|
[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 {
|
match s {
|
||||||
[0x00, 0x00, 0x00, 0x00] => (),
|
[0x00, 0x00, 0x00, 0x00] => (),
|
||||||
MAGIC_TEST => (),
|
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 {
|
match s {
|
||||||
[0x00, 0x00, 0x00, 0x00] => (),
|
[0x00, 0x00, 0x00, 0x00] => (),
|
||||||
[4, 5, 6, 7] => (),
|
[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];
|
const FOO: [u32; 1] = [4];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: unreachable pattern
|
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
|
note: the lint level is defined here
|
||||||
--> $DIR/slice-pattern-const-2.rs:1:9
|
--> $DIR/slice-pattern-const-2.rs:1:9
|
||||||
|
@ -10,5 +10,23 @@ note: the lint level is defined here
|
||||||
LL | #![deny(unreachable_patterns)]
|
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 {
|
match s {
|
||||||
MAGIC_TEST => (),
|
MAGIC_TEST => (),
|
||||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
["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 {
|
match s {
|
||||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
["0x00", "0x00", "0x00", "0x00"] => (),
|
||||||
MAGIC_TEST => (),
|
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 {
|
match s {
|
||||||
["0x00", "0x00", "0x00", "0x00"] => (),
|
["0x00", "0x00", "0x00", "0x00"] => (),
|
||||||
["4", "5", "6", "7"] => (),
|
["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"];
|
const FOO: [&str; 1] = ["boo"];
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: unreachable pattern
|
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
|
note: the lint level is defined here
|
||||||
--> $DIR/slice-pattern-const-3.rs:1:9
|
--> $DIR/slice-pattern-const-3.rs:1:9
|
||||||
|
@ -10,5 +10,23 @@ note: the lint level is defined here
|
||||||
LL | #![deny(unreachable_patterns)]
|
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
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,15 @@ fn main() {
|
||||||
let s10: &[bool; 10] = &[false; 10];
|
let s10: &[bool; 10] = &[false; 10];
|
||||||
|
|
||||||
match s2 {
|
match s2 {
|
||||||
//~^ ERROR `&[false, _]` not covered
|
//~^ ERROR `&[false, _]` not covered
|
||||||
[true, .., true] => {}
|
[true, .., true] => {}
|
||||||
}
|
}
|
||||||
match s3 {
|
match s3 {
|
||||||
//~^ ERROR `&[false, ..]` not covered
|
//~^ ERROR `&[false, ..]` not covered
|
||||||
[true, .., true] => {}
|
[true, .., true] => {}
|
||||||
}
|
}
|
||||||
match s10 {
|
match s10 {
|
||||||
//~^ ERROR `&[false, ..]` not covered
|
//~^ ERROR `&[false, ..]` not covered
|
||||||
[true, .., true] => {}
|
[true, .., true] => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,58 +23,58 @@ fn main() {
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
match s2 {
|
match s2 {
|
||||||
//~^ ERROR `&[false, true]` not covered
|
//~^ ERROR `&[false, true]` not covered
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
match s3 {
|
match s3 {
|
||||||
//~^ ERROR `&[false, .., true]` not covered
|
//~^ ERROR `&[false, .., true]` not covered
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[false, .., true]` not covered
|
//~^ ERROR `&[false, .., true]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, ..]` not covered
|
//~^ ERROR `&[_, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, _, ..]` not covered
|
//~^ ERROR `&[_, _, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[false, ..]` not covered
|
//~^ ERROR `&[false, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[false, _, ..]` not covered
|
//~^ ERROR `&[false, _, ..]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
[true, ..] => {}
|
[true, ..] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, .., false]` not covered
|
//~^ ERROR `&[_, .., false]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
[.., true] => {}
|
[.., true] => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[_, _, .., true]` not covered
|
//~^ ERROR `&[_, _, .., true]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
[_, _] => {}
|
[_, _] => {}
|
||||||
[.., false] => {}
|
[.., false] => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[true, _, .., _]` not covered
|
//~^ ERROR `&[true, _, .., _]` not covered
|
||||||
[] => {}
|
[] => {}
|
||||||
[_] => {}
|
[_] => {}
|
||||||
[_, _] => {}
|
[_, _] => {}
|
||||||
|
@ -83,19 +83,43 @@ fn main() {
|
||||||
|
|
||||||
const CONST: &[bool] = &[true];
|
const CONST: &[bool] = &[true];
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[..]` not covered
|
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||||
|
&[true] => {}
|
||||||
|
}
|
||||||
|
match s {
|
||||||
|
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||||
CONST => {}
|
CONST => {}
|
||||||
}
|
}
|
||||||
match s {
|
match s {
|
||||||
//~^ ERROR `&[true]` not covered
|
//~^ ERROR `&[]` and `&[_, _, ..]` not covered
|
||||||
[] => {},
|
CONST => {}
|
||||||
[false] => {},
|
&[false] => {}
|
||||||
CONST => {},
|
}
|
||||||
|
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];
|
const CONST1: &[bool; 1] = &[true];
|
||||||
match s1 {
|
match s1 {
|
||||||
//~^ ERROR `&[false]` not covered
|
//~^ ERROR `&[false]` not covered
|
||||||
CONST1 => {}
|
CONST1 => {}
|
||||||
}
|
}
|
||||||
match s1 {
|
match s1 {
|
||||||
|
|
|
@ -115,26 +115,62 @@ LL | match s {
|
||||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
= 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]`
|
= 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
|
--> $DIR/slice-patterns-exhaustiveness.rs:85:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
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
|
= 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]`
|
= 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
|
--> $DIR/slice-patterns-exhaustiveness.rs:89:11
|
||||||
|
|
|
|
||||||
LL | match s {
|
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
|
= 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]`
|
= note: the matched value is of type `&[bool]`
|
||||||
|
|
||||||
error[E0004]: non-exhaustive patterns: `&[false]` not covered
|
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 {
|
LL | match s1 {
|
||||||
| ^^ pattern `&[false]` not covered
|
| ^^ 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
|
= 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]`
|
= 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`.
|
For more information about this error, try `rustc --explain E0004`.
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
|
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
||||||
// This impl makes NoDerive irreflexive
|
// This impl makes NoDerive irreflexive
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
|
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
||||||
// This impl makes NoDerive irreflexive
|
// This impl makes NoDerive irreflexive
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
|
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
||||||
// This impl makes NoDerive irreflexive
|
// This impl makes NoDerive irreflexive
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
|
|
||||||
struct NoDerive(i32);
|
struct NoDerive(i32);
|
||||||
|
|
||||||
// This impl makes NoDerive irreflexive
|
// This impl makes NoDerive irreflexive
|
||||||
|
|
|
@ -21,7 +21,6 @@ fn main() {
|
||||||
match WRAP_DIRECT_INLINE {
|
match WRAP_DIRECT_INLINE {
|
||||||
WRAP_DIRECT_INLINE => { panic!("WRAP_DIRECT_INLINE matched itself"); }
|
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)]`
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
_ => { println!("WRAP_DIRECT_INLINE did not match itself"); }
|
_ => { 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"); }
|
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)]`
|
error: aborting due to previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ fn main() {
|
||||||
match WRAP_DIRECT_PARAM {
|
match WRAP_DIRECT_PARAM {
|
||||||
WRAP_DIRECT_PARAM => { panic!("WRAP_DIRECT_PARAM matched itself"); }
|
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)]`
|
||||||
//~| ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
|
||||||
_ => { println!("WRAP_DIRECT_PARAM did not match itself"); }
|
_ => { 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"); }
|
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)]`
|
error: aborting due to previous error
|
||||||
--> $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
|
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
||||||
match WRAP_DOUBLY_INDIRECT_INLINE {
|
match WRAP_DOUBLY_INDIRECT_INLINE {
|
||||||
WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
|
WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
|
||||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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"); }
|
_ => { println!("WRAP_DOUBLY_INDIRECT_INLINE correctly did not match itself"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
||||||
match WRAP_DOUBLY_INDIRECT_PARAM {
|
match WRAP_DOUBLY_INDIRECT_PARAM {
|
||||||
WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
|
WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
|
||||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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"); }
|
_ => { println!("WRAP_DOUBLY_INDIRECT_PARAM correctly did not match itself"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
||||||
match WRAP_INDIRECT_INLINE {
|
match WRAP_INDIRECT_INLINE {
|
||||||
WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
|
WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
|
||||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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"); }
|
_ => { println!("WRAP_INDIRECT_INLINE did not match itself"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ fn main() {
|
||||||
match WRAP_INDIRECT_PARAM {
|
match WRAP_INDIRECT_PARAM {
|
||||||
WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
|
WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
|
||||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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"); }
|
_ => { println!("WRAP_INDIRECT_PARAM correctly did not match itself"); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
// Issue 62307 pointed out a case where the structural-match checking
|
// Issue 62307 pointed out a case where the structural-match checking
|
||||||
// was too shallow.
|
// was too shallow.
|
||||||
#![warn(indirect_structural_match)]
|
#![warn(indirect_structural_match, nontrivial_structural_match)]
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -30,14 +30,14 @@ fn main() {
|
||||||
match RR_B0 {
|
match RR_B0 {
|
||||||
RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
|
RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
|
||||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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 {
|
match RR_B1 {
|
||||||
RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
|
RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
|
||||||
//~^ WARN must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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
|
note: the lint level is defined here
|
||||||
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
|
--> $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!
|
= 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 #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
|
// cover the case this hit; I've since expanded it accordingly, but the
|
||||||
// experience left me wary of leaving this regression test out.)
|
// experience left me wary of leaving this regression test out.)
|
||||||
|
|
||||||
|
#![warn(pointer_structural_match)]
|
||||||
|
|
||||||
#[derive(Eq)]
|
#[derive(Eq)]
|
||||||
struct A {
|
struct A {
|
||||||
a: i64
|
a: i64
|
||||||
|
@ -31,6 +33,8 @@ fn main() {
|
||||||
let s = B(my_fn);
|
let s = B(my_fn);
|
||||||
match s {
|
match s {
|
||||||
B(TEST) => println!("matched"),
|
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")
|
_ => panic!("didn't match")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
16
src/test/ui/rfc1445/issue-63479-match-fnptr.stderr
Normal file
16
src/test/ui/rfc1445/issue-63479-match-fnptr.stderr
Normal file
|
@ -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 {
|
match y {
|
||||||
FOO => { }
|
FOO => { }
|
||||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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
|
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 => { }
|
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!
|
= 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>
|
= 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
|
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 => { }
|
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!
|
= 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>
|
= 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)] {
|
match [B(1)] {
|
||||||
FOO => { }
|
FOO => { }
|
||||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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 => { }
|
LL | FOO => { }
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
|
error: aborting due to previous error
|
||||||
--> $DIR/match-nonempty-array-forbidden-without-eq.rs:16:9
|
|
||||||
|
|
|
||||||
LL | FOO => { }
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ fn main() {
|
||||||
match y {
|
match y {
|
||||||
FOO => { }
|
FOO => { }
|
||||||
//~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
|
//~^ 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 => { }
|
LL | FOO => { }
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
|
error: aborting due to previous error
|
||||||
--> $DIR/match-requires-both-partialeq-and-eq.rs:17:9
|
|
||||||
|
|
|
||||||
LL | FOO => { }
|
|
||||||
| ^^^
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ const LEAK_FREE: Bar = leak_free();
|
||||||
fn leak_free_test() {
|
fn leak_free_test() {
|
||||||
match todo!() {
|
match todo!() {
|
||||||
LEAK_FREE => (),
|
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
|
--> $DIR/structural-match-no-leak.rs:14:9
|
||||||
|
|
|
|
||||||
LL | LEAK_FREE => (),
|
LL | LEAK_FREE => (),
|
||||||
|
|
|
@ -13,9 +13,9 @@ const VALUE: Foo = value();
|
||||||
fn test() {
|
fn test() {
|
||||||
match todo!() {
|
match todo!() {
|
||||||
VALUE => (),
|
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
|
--> $DIR/structural-match.rs:15:9
|
||||||
|
|
|
|
||||||
LL | VALUE => (),
|
LL | VALUE => (),
|
||||||
|
|
|
@ -8,7 +8,6 @@ const C: U = U { a: 10 };
|
||||||
fn main() {
|
fn main() {
|
||||||
match C {
|
match C {
|
||||||
C => {} //~ ERROR cannot use unions in constant patterns
|
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 => {}
|
LL | C => {}
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: cannot use unions in constant patterns
|
error: aborting due to previous error
|
||||||
--> $DIR/union-const-pat.rs:10:9
|
|
||||||
|
|
|
||||||
LL | C => {}
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue