Cleanup PatCtxt.

This commit is contained in:
Camille GILLOT 2023-02-26 20:42:46 +00:00
parent 05082f57af
commit 4240a0bed0
2 changed files with 23 additions and 73 deletions

View File

@ -59,8 +59,6 @@ struct ConstToPat<'tcx> {
// inference context used for checking `T: Structural` bounds.
infcx: InferCtxt<'tcx>,
include_lint_checks: bool,
treat_byte_string_as_slice: bool,
}
@ -93,7 +91,6 @@ impl<'tcx> ConstToPat<'tcx> {
span,
infcx,
param_env: pat_ctxt.param_env,
include_lint_checks: pat_ctxt.include_lint_checks,
saw_const_match_error: Cell::new(false),
saw_const_match_lint: Cell::new(false),
behind_reference: Cell::new(false),
@ -134,7 +131,7 @@ impl<'tcx> ConstToPat<'tcx> {
})
});
if self.include_lint_checks && !self.saw_const_match_error.get() {
if !self.saw_const_match_error.get() {
// If we were able to successfully convert the const to some pat,
// double-check that all types in the const implement `Structural`.
@ -239,21 +236,19 @@ impl<'tcx> ConstToPat<'tcx> {
let kind = match cv.ty().kind() {
ty::Float(_) => {
if self.include_lint_checks {
tcx.emit_spanned_lint(
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
id,
span,
FloatPattern,
);
}
PatKind::Constant { value: cv }
}
ty::Adt(adt_def, _) if adt_def.is_union() => {
// Matching on union fields is unsafe, we can't hide it in constants
self.saw_const_match_error.set(true);
let err = UnionPattern { span };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.emit_err(err);
PatKind::Wild
}
ty::Adt(..)
@ -267,7 +262,7 @@ impl<'tcx> ConstToPat<'tcx> {
{
self.saw_const_match_error.set(true);
let err = TypeNotStructural { span, non_sm_ty };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.emit_err(err);
PatKind::Wild
}
// If the type is not structurally comparable, just emit the constant directly,
@ -280,8 +275,7 @@ impl<'tcx> ConstToPat<'tcx> {
// 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()
if !self.saw_const_match_error.get()
&& !self.saw_const_match_lint.get()
{
self.saw_const_match_lint.set(true);
@ -305,7 +299,7 @@ impl<'tcx> ConstToPat<'tcx> {
);
self.saw_const_match_error.set(true);
let err = TypeNotStructural { span, non_sm_ty: cv.ty() };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.emit_err(err);
PatKind::Wild
}
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
@ -339,7 +333,7 @@ impl<'tcx> ConstToPat<'tcx> {
ty::Dynamic(..) => {
self.saw_const_match_error.set(true);
let err = InvalidPattern { span, non_sm_ty: cv.ty() };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.emit_err(err);
PatKind::Wild
}
// `&str` is represented as `ConstValue::Slice`, let's keep using this
@ -406,8 +400,7 @@ impl<'tcx> ConstToPat<'tcx> {
// to figure out how to get a reference again.
ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => {
if self.behind_reference.get() {
if self.include_lint_checks
&& !self.saw_const_match_error.get()
if !self.saw_const_match_error.get()
&& !self.saw_const_match_lint.get()
{
self.saw_const_match_lint.set(true);
@ -423,7 +416,7 @@ impl<'tcx> ConstToPat<'tcx> {
if !self.saw_const_match_error.get() {
self.saw_const_match_error.set(true);
let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.emit_err(err);
}
PatKind::Wild
}
@ -437,7 +430,7 @@ impl<'tcx> ConstToPat<'tcx> {
// (except slices, which are handled in a separate arm above).
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.emit_err(err);
PatKind::Wild
} else {
@ -465,8 +458,7 @@ impl<'tcx> ConstToPat<'tcx> {
// 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()
if !self.saw_const_match_error.get()
&& !self.saw_const_match_lint.get()
{
self.saw_const_match_lint.set(true);
@ -482,13 +474,12 @@ impl<'tcx> ConstToPat<'tcx> {
_ => {
self.saw_const_match_error.set(true);
let err = InvalidPattern { span, non_sm_ty: cv.ty() };
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
tcx.sess.emit_err(err);
PatKind::Wild
}
};
if self.include_lint_checks
&& !self.saw_const_match_error.get()
if !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

View File

@ -31,20 +31,10 @@ use rustc_target::abi::FieldIdx;
use std::cmp::Ordering;
#[derive(Clone, Debug)]
enum PatternError {
AssocConstInPattern(Span),
ConstParamInPattern(Span),
StaticInPattern(Span),
NonConstPath(Span),
}
struct PatCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
errors: Vec<PatternError>,
include_lint_checks: bool,
}
pub(super) fn pat_from_hir<'a, 'tcx>(
@ -53,47 +43,13 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
typeck_results: &'a ty::TypeckResults<'tcx>,
pat: &'tcx hir::Pat<'tcx>,
) -> Box<Pat<'tcx>> {
let mut pcx = PatCtxt::new(tcx, param_env, typeck_results);
pcx.include_lint_checks();
let mut pcx = PatCtxt { tcx, param_env, typeck_results };
let result = pcx.lower_pattern(pat);
pcx.report_inlining_errors();
debug!("pat_from_hir({:?}) = {:?}", pat, result);
result
}
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
fn new(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
) -> Self {
PatCtxt { tcx, param_env, typeck_results, errors: vec![], include_lint_checks: false }
}
fn include_lint_checks(&mut self) -> &mut Self {
self.include_lint_checks = true;
self
}
fn report_inlining_errors(&self) {
for error in &self.errors {
match *error {
PatternError::StaticInPattern(span) => {
self.tcx.sess.emit_err(StaticInPattern { span });
}
PatternError::AssocConstInPattern(span) => {
self.tcx.sess.emit_err(AssocConstInPattern { span });
}
PatternError::ConstParamInPattern(span) => {
self.tcx.sess.emit_err(ConstParamInPattern { span });
}
PatternError::NonConstPath(span) => {
self.tcx.sess.emit_err(NonConstPath { span });
}
}
}
}
fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
// When implicit dereferences have been inserted in this pattern, the unadjusted lowered
// pattern has the type that results *after* dereferencing. For example, in this code:
@ -490,12 +446,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
| Res::SelfTyAlias { .. }
| Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
_ => {
let pattern_error = match res {
Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
Res::Def(DefKind::Static(_), _) => PatternError::StaticInPattern(span),
_ => PatternError::NonConstPath(span),
match res {
Res::Def(DefKind::ConstParam, _) => {
self.tcx.sess.emit_err(ConstParamInPattern { span })
}
Res::Def(DefKind::Static(_), _) => {
self.tcx.sess.emit_err(StaticInPattern { span })
}
_ => self.tcx.sess.emit_err(NonConstPath { span }),
};
self.errors.push(pattern_error);
PatKind::Wild
}
};
@ -548,7 +507,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
// It should be assoc consts if there's no error but we cannot resolve it.
debug_assert!(is_associated_const);
self.errors.push(PatternError::AssocConstInPattern(span));
self.tcx.sess.emit_err(AssocConstInPattern { span });
return pat_from_kind(PatKind::Wild);
}
@ -626,7 +585,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
match value {
mir::ConstantKind::Ty(c) => match c.kind() {
ConstKind::Param(_) => {
self.errors.push(PatternError::ConstParamInPattern(span));
self.tcx.sess.emit_err(ConstParamInPattern { span });
return PatKind::Wild;
}
ConstKind::Error(_) => {