fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
traits::search_for_structural_match_violation(self.span, self.tcx(), ty, false).map(
|non_sm_ty| {
- with_no_trimmed_paths!(match non_sm_ty.kind {
- traits::NonStructuralMatchTyKind::Adt(adt) => self.adt_derive_msg(adt),
- traits::NonStructuralMatchTyKind::Dynamic => {
+ with_no_trimmed_paths!(match non_sm_ty.kind() {
+ ty::Adt(adt, _) => self.adt_derive_msg(*adt),
+ ty::Dynamic(..) => {
"trait objects cannot be used in patterns".to_string()
}
- traits::NonStructuralMatchTyKind::Opaque => {
+ ty::Opaque(..) => {
"opaque types cannot be used in patterns".to_string()
}
- traits::NonStructuralMatchTyKind::Closure => {
+ ty::Closure(..) => {
"closures cannot be used in patterns".to_string()
}
- traits::NonStructuralMatchTyKind::Generator => {
+ ty::Generator(..) | ty::GeneratorWitness(..) => {
"generators cannot be used in patterns".to_string()
}
- traits::NonStructuralMatchTyKind::Float => {
+ ty::Float(..) => {
"floating-point numbers cannot be used in patterns".to_string()
}
- traits::NonStructuralMatchTyKind::FnPtr => {
+ ty::FnPtr(..) => {
"function pointers cannot be used in patterns".to_string()
}
- traits::NonStructuralMatchTyKind::RawPtr => {
+ ty::RawPtr(..) => {
"raw pointers cannot be used in patterns".to_string()
}
- traits::NonStructuralMatchTyKind::Param => {
- bug!("use of a constant whose type is a parameter inside a pattern")
- }
- traits::NonStructuralMatchTyKind::Projection => {
- bug!("use of a constant whose type is a projection inside a pattern")
- }
- traits::NonStructuralMatchTyKind::Foreign => {
- bug!("use of a value of a foreign type inside a pattern")
+ _ => {
+ bug!("use of a value of `{non_sm_ty}` inside a pattern")
}
})
},
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_span::Span;
use std::ops::ControlFlow;
-#[derive(Debug)]
-pub struct NonStructuralMatchTy<'tcx> {
- pub ty: Ty<'tcx>,
- pub kind: NonStructuralMatchTyKind<'tcx>,
-}
-
-#[derive(Debug)]
-pub enum NonStructuralMatchTyKind<'tcx> {
- Adt(AdtDef<'tcx>),
- Param,
- Dynamic,
- Foreign,
- Opaque,
- Closure,
- Generator,
- Projection,
- Float,
- FnPtr,
- RawPtr,
-}
-
/// This method traverses the structure of `ty`, trying to find an
/// instance of an ADT (i.e. struct or enum) that doesn't implement
/// the structural-match traits, or a generic type parameter
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
valtree_semantics: bool,
-) -> Option<NonStructuralMatchTy<'tcx>> {
+) -> Option<Ty<'tcx>> {
ty.visit_with(&mut Search { tcx, span, seen: FxHashSet::default(), valtree_semantics })
.break_value()
}
}
impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
- type BreakTy = NonStructuralMatchTy<'tcx>;
+ type BreakTy = Ty<'tcx>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("Search visiting ty: {:?}", ty);
let (adt_def, substs) = match *ty.kind() {
ty::Adt(adt_def, substs) => (adt_def, substs),
ty::Param(_) => {
- let kind = NonStructuralMatchTyKind::Param;
- return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+ return ControlFlow::Break(ty);
}
ty::Dynamic(..) => {
- let kind = NonStructuralMatchTyKind::Dynamic;
- return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+ return ControlFlow::Break(ty);
}
ty::Foreign(_) => {
- let kind = NonStructuralMatchTyKind::Foreign;
- return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+ return ControlFlow::Break(ty);
}
ty::Opaque(..) => {
- let kind = NonStructuralMatchTyKind::Opaque;
- return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+ return ControlFlow::Break(ty);
}
ty::Projection(..) => {
- let kind = NonStructuralMatchTyKind::Projection;
- return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+ return ControlFlow::Break(ty);
}
ty::Closure(..) => {
- let kind = NonStructuralMatchTyKind::Closure;
- return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+ return ControlFlow::Break(ty);
}
ty::Generator(..) | ty::GeneratorWitness(..) => {
- let kind = NonStructuralMatchTyKind::Generator;
- return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+ return ControlFlow::Break(ty);
}
ty::FnDef(..) => {
// Types of formals and return in `fn(_) -> _` are also irrelevant;
if !self.valtree_semantics {
return ControlFlow::CONTINUE;
} else {
- return ControlFlow::Break(NonStructuralMatchTy {
- ty,
- kind: NonStructuralMatchTyKind::FnPtr,
- });
+ return ControlFlow::Break(ty);
}
}
// pointer. Therefore, one can still use `C` in a pattern.
return ControlFlow::CONTINUE;
} else {
- return ControlFlow::Break(NonStructuralMatchTy {
- ty,
- kind: NonStructuralMatchTyKind::FnPtr,
- });
+ return ControlFlow::Break(ty);
}
}
if !self.valtree_semantics {
return ControlFlow::CONTINUE;
} else {
- return ControlFlow::Break(NonStructuralMatchTy {
- ty,
- kind: NonStructuralMatchTyKind::Float,
- });
+ return ControlFlow::Break(ty);
}
}
if !self.type_marked_structural(ty) {
debug!("Search found ty: {:?}", ty);
- let kind = NonStructuralMatchTyKind::Adt(adt_def);
- return ControlFlow::Break(NonStructuralMatchTy { ty, kind });
+ return ControlFlow::Break(ty);
}
// structural-match does not care about the
// We use the same error code in both branches, because this is really the same
// issue: we just special-case the message for type parameters to make it
// clearer.
- match non_structural_match_ty.ty.kind() {
+ match non_structural_match_ty.kind() {
ty::Param(_) => {
// Const parameters may not have type parameters as their types,
// because we cannot be sure that the type parameter derives `PartialEq`
E0741,
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
the type of a const parameter",
- non_structural_match_ty.ty,
+ non_structural_match_ty,
);
- if ty == non_structural_match_ty.ty {
+ if ty == non_structural_match_ty {
diag.span_label(
hir_ty.span,
format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),