Add PatKind::Err

This commit is contained in:
Lieselotte 2024-01-17 03:14:16 +01:00
parent 6ed31aba1a
commit 7889e99b55
No known key found for this signature in database
GPG key ID: 43A6A32F83A6F9B1
23 changed files with 66 additions and 24 deletions

View file

@ -625,7 +625,8 @@ impl Pat {
| PatKind::Range(..) | PatKind::Range(..)
| PatKind::Ident(..) | PatKind::Ident(..)
| PatKind::Path(..) | PatKind::Path(..)
| PatKind::MacCall(_) => {} | PatKind::MacCall(_)
| PatKind::Err(_) => {}
} }
} }
@ -809,6 +810,9 @@ pub enum PatKind {
/// A macro pattern; pre-expansion. /// A macro pattern; pre-expansion.
MacCall(P<MacCall>), MacCall(P<MacCall>),
/// Placeholder for a pattern that wasn't syntactically well formed in some way.
Err(ErrorGuaranteed),
} }
/// Whether the `..` is present in a struct fields pattern. /// Whether the `..` is present in a struct fields pattern.

View file

@ -1267,7 +1267,7 @@ pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
let Pat { id, kind, span, tokens } = pat.deref_mut(); let Pat { id, kind, span, tokens } = pat.deref_mut();
vis.visit_id(id); vis.visit_id(id);
match kind { match kind {
PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
PatKind::Ident(_binding_mode, ident, sub) => { PatKind::Ident(_binding_mode, ident, sub) => {
vis.visit_ident(ident); vis.visit_ident(ident);
visit_opt(sub, |sub| vis.visit_pat(sub)); visit_opt(sub, |sub| vis.visit_pat(sub));

View file

@ -568,7 +568,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, lower_bound);
walk_list!(visitor, visit_expr, upper_bound); walk_list!(visitor, visit_expr, upper_bound);
} }
PatKind::Wild | PatKind::Rest | PatKind::Never => {} PatKind::Wild | PatKind::Rest | PatKind::Never | PatKind::Err(_) => {}
PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => { PatKind::Tuple(elems) | PatKind::Slice(elems) | PatKind::Or(elems) => {
walk_list!(visitor, visit_pat, elems); walk_list!(visitor, visit_pat, elems);
} }

View file

@ -109,6 +109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// return inner to be processed in next loop // return inner to be processed in next loop
PatKind::Paren(inner) => pattern = inner, PatKind::Paren(inner) => pattern = inner,
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
PatKind::Err(guar) => break hir::PatKind::Err(*guar),
} }
}; };

View file

@ -1519,6 +1519,11 @@ impl<'a> State<'a> {
self.pclose(); self.pclose();
} }
PatKind::MacCall(m) => self.print_mac(m), PatKind::MacCall(m) => self.print_mac(m),
PatKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
self.pclose();
}
} }
self.ann.post(self, AnnNode::Pat(pat)) self.ann.post(self, AnnNode::Pat(pat))
} }

View file

@ -1015,7 +1015,7 @@ impl<'hir> Pat<'hir> {
use PatKind::*; use PatKind::*;
match self.kind { match self.kind {
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it), Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
@ -1042,7 +1042,7 @@ impl<'hir> Pat<'hir> {
use PatKind::*; use PatKind::*;
match self.kind { match self.kind {
Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {} Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it), Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
@ -1205,6 +1205,9 @@ pub enum PatKind<'hir> {
/// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)]) /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)])
/// ``` /// ```
Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]), Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]),
/// A placeholder for a pattern that wasn't well formed in some way.
Err(ErrorGuaranteed),
} }
/// A statement. /// A statement.

View file

@ -655,7 +655,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
walk_list!(visitor, visit_expr, lower_bound); walk_list!(visitor, visit_expr, lower_bound);
walk_list!(visitor, visit_expr, upper_bound); walk_list!(visitor, visit_expr, upper_bound);
} }
PatKind::Never | PatKind::Wild => (), PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => { PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
walk_list!(visitor, visit_pat, prepatterns); walk_list!(visitor, visit_pat, prepatterns);
walk_list!(visitor, visit_pat, slice_pattern); walk_list!(visitor, visit_pat, slice_pattern);

View file

@ -681,7 +681,8 @@ fn resolve_local<'tcx>(
| PatKind::Never | PatKind::Never
| PatKind::Path(_) | PatKind::Path(_)
| PatKind::Lit(_) | PatKind::Lit(_)
| PatKind::Range(_, _, _) => false, | PatKind::Range(_, _, _)
| PatKind::Err(_) => false,
} }
} }

View file

@ -1838,6 +1838,11 @@ impl<'a> State<'a> {
self.commasep(Inconsistent, after, |s, p| s.print_pat(p)); self.commasep(Inconsistent, after, |s, p| s.print_pat(p));
self.word("]"); self.word("]");
} }
PatKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
self.pclose();
}
} }
self.ann.post(self, AnnNode::Pat(pat)) self.ann.post(self, AnnNode::Pat(pat))
} }

View file

@ -458,11 +458,15 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
needs_to_be_read = true; needs_to_be_read = true;
} }
} }
PatKind::Or(_) | PatKind::Box(_) | PatKind::Ref(..) | PatKind::Wild => { PatKind::Or(_)
| PatKind::Box(_)
| PatKind::Ref(..)
| PatKind::Wild
| PatKind::Err(_) => {
// If the PatKind is Or, Box, or Ref, the decision is made later // If the PatKind is Or, Box, or Ref, the decision is made later
// as these patterns contains subpatterns // as these patterns contains subpatterns
// If the PatKind is Wild, the decision is made based on the other patterns being // If the PatKind is Wild or Err, the decision is made based on the other patterns
// examined // being examined
} }
} }
})? })?

View file

@ -767,7 +767,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
| PatKind::Lit(..) | PatKind::Lit(..)
| PatKind::Range(..) | PatKind::Range(..)
| PatKind::Never | PatKind::Never
| PatKind::Wild => { | PatKind::Wild
| PatKind::Err(_) => {
// always ok // always ok
} }
} }

View file

@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin }; PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin };
let ty = match pat.kind { let ty = match pat.kind {
PatKind::Wild => expected, PatKind::Wild | PatKind::Err(_) => expected,
// FIXME(never_patterns): check the type is uninhabited. If that is not possible within // FIXME(never_patterns): check the type is uninhabited. If that is not possible within
// typeck, do that in a later phase. // typeck, do that in a later phase.
PatKind::Never => expected, PatKind::Never => expected,
@ -325,6 +325,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PatKind::Ref(..) => AdjustMode::Reset, PatKind::Ref(..) => AdjustMode::Reset,
// A `_` pattern works with any expected type, so there's no need to do anything. // A `_` pattern works with any expected type, so there's no need to do anything.
PatKind::Wild PatKind::Wild
// A malformed pattern doesn't have an expected type, so let's just accept any type.
| PatKind::Err(_)
// Bindings also work with whatever the expected type is, // Bindings also work with whatever the expected type is,
// and moreover if we peel references off, that will give us the wrong binding type. // and moreover if we peel references off, that will give us the wrong binding type.
// Also, we can have a subpattern `binding @ pat`. // Also, we can have a subpattern `binding @ pat`.
@ -754,7 +756,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| PatKind::Box(..) | PatKind::Box(..)
| PatKind::Ref(..) | PatKind::Ref(..)
| PatKind::Lit(..) | PatKind::Lit(..)
| PatKind::Range(..) => break 'block None, | PatKind::Range(..)
| PatKind::Err(_) => break 'block None,
}, },
// Don't provide suggestions in other cases // Don't provide suggestions in other cases

View file

@ -1166,7 +1166,7 @@ impl EarlyLintPass for UnusedParens {
// Do not lint on `(..)` as that will result in the other arms being useless. // Do not lint on `(..)` as that will result in the other arms being useless.
Paren(_) Paren(_)
// The other cases do not contain sub-patterns. // The other cases do not contain sub-patterns.
| Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {}, | Wild | Never | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) | Err(_) => {},
// These are list-like patterns; parens can always be removed. // These are list-like patterns; parens can always be removed.
TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
self.check_unused_parens_pat(cx, p, false, false, keep_space); self.check_unused_parens_pat(cx, p, false, false, keep_space);

View file

@ -345,6 +345,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
} }
hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) }, hir::PatKind::Or(pats) => PatKind::Or { pats: self.lower_patterns(pats) },
hir::PatKind::Err(guar) => PatKind::Error(guar),
}; };
Box::new(Pat { span, ty, kind }) Box::new(Pat { span, ty, kind })

View file

@ -303,7 +303,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
Ref, Ref,
Lit, Lit,
Range, Range,
Slice Slice,
Err
] ]
); );
hir_visit::walk_pat(self, p) hir_visit::walk_pat(self, p)
@ -576,7 +577,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
Rest, Rest,
Never, Never,
Paren, Paren,
MacCall MacCall,
Err
] ]
); );
ast_visit::walk_pat(self, p) ast_visit::walk_pat(self, p)

View file

@ -312,7 +312,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
Symbol::intern(&match p.kind { Symbol::intern(&match p.kind {
// FIXME(never_patterns): does this make sense? // FIXME(never_patterns): does this make sense?
PatKind::Wild | PatKind::Never | PatKind::Struct(..) => return kw::Underscore, PatKind::Wild | PatKind::Err(_) | PatKind::Never | PatKind::Struct(..) => {
return kw::Underscore;
}
PatKind::Binding(_, _, ident, _) => return ident.name, PatKind::Binding(_, _, ident, _) => return ident.name,
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
PatKind::Or(pats) => { PatKind::Or(pats) => {

View file

@ -51,7 +51,8 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
| PatKind::Binding(..) | PatKind::Binding(..)
| PatKind::Wild | PatKind::Wild
| PatKind::Never | PatKind::Never
| PatKind::Or(_) => false, | PatKind::Or(_)
| PatKind::Err(_) => false,
PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a),
PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x), PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),

View file

@ -11,7 +11,7 @@ use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, P
use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty; use rustc_middle::ty;
use rustc_span::Symbol; use rustc_span::{ErrorGuaranteed, Symbol};
use super::MATCH_SAME_ARMS; use super::MATCH_SAME_ARMS;
@ -167,6 +167,8 @@ enum NormalizedPat<'a> {
/// contains everything afterwards. Note that either side, or both sides, may contain zero /// contains everything afterwards. Note that either side, or both sides, may contain zero
/// patterns. /// patterns.
Slice(&'a [Self], Option<&'a [Self]>), Slice(&'a [Self], Option<&'a [Self]>),
/// A placeholder for a pattern that wasn't well formed in some way.
Err(ErrorGuaranteed),
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -329,6 +331,7 @@ impl<'a> NormalizedPat<'a> {
arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))), arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))),
wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))), wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))),
), ),
PatKind::Err(guar) => Self::Err(guar),
} }
} }

View file

@ -226,7 +226,7 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
// Therefore they are not some form of constructor `C`, // Therefore they are not some form of constructor `C`,
// with which a pattern `C(p_0)` may be formed, // with which a pattern `C(p_0)` may be formed,
// which we would want to join with other `C(p_j)`s. // which we would want to join with other `C(p_j)`s.
Ident(.., None) | Lit(_) | Wild | Never | Path(..) | Range(..) | Rest | MacCall(_) Ident(.., None) | Lit(_) | Wild | Err(_) | Never | Path(..) | Range(..) | Rest | MacCall(_)
// Skip immutable refs, as grouping them saves few characters, // Skip immutable refs, as grouping them saves few characters,
// and almost always requires adding parens (increasing noisiness). // and almost always requires adding parens (increasing noisiness).
// In the case of only two patterns, replacement adds net characters. // In the case of only two patterns, replacement adds net characters.

View file

@ -710,6 +710,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
self.slice(start, |pat| self.pat(pat)); self.slice(start, |pat| self.pat(pat));
self.slice(end, |pat| self.pat(pat)); self.slice(end, |pat| self.pat(pat));
}, },
PatKind::Err(_) => kind!("Err"),
} }
} }

View file

@ -1007,7 +1007,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
} }
e.hash(&mut self.s); e.hash(&mut self.s);
}, },
PatKind::Never | PatKind::Wild => {}, PatKind::Never | PatKind::Wild | PatKind::Err(_) => {},
} }
} }

View file

@ -1733,6 +1733,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
}, },
} }
}, },
PatKind::Err(_) => true,
} }
} }

View file

@ -40,9 +40,11 @@ pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool {
fn is_short_pattern_inner(pat: &ast::Pat) -> bool { fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
match pat.kind { match pat.kind {
ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Lit(_) => { ast::PatKind::Rest
true | ast::PatKind::Never
} | ast::PatKind::Wild
| ast::PatKind::Err(_)
| ast::PatKind::Lit(_) => true,
ast::PatKind::Ident(_, _, ref pat) => pat.is_none(), ast::PatKind::Ident(_, _, ref pat) => pat.is_none(),
ast::PatKind::Struct(..) ast::PatKind::Struct(..)
| ast::PatKind::MacCall(..) | ast::PatKind::MacCall(..)
@ -274,6 +276,7 @@ impl Rewrite for Pat {
PatKind::Paren(ref pat) => pat PatKind::Paren(ref pat) => pat
.rewrite(context, shape.offset_left(1)?.sub_width(1)?) .rewrite(context, shape.offset_left(1)?.sub_width(1)?)
.map(|inner_pat| format!("({})", inner_pat)), .map(|inner_pat| format!("({})", inner_pat)),
PatKind::Err(_) => None,
} }
} }
} }