Rollup merge of #145783 - Erk-:et-cetera-span, r=compiler-errors
add span to struct pattern rest (..) Struct pattern rest (`..`) did not retain span information compared to normal fields. This patch adds span information for it. The motivation of this patch comes from when I implemented this PR for Clippy: https://github.com/rust-lang/rust-clippy/pull/15000#discussion_r2134145163 It is possible to get the span of the Et cetera in a bit roundabout way, but I thought this would be nicer.
This commit is contained in:
@@ -937,7 +937,7 @@ pub enum PatKind {
|
|||||||
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Walkable)]
|
#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Walkable)]
|
||||||
pub enum PatFieldsRest {
|
pub enum PatFieldsRest {
|
||||||
/// `module::StructName { field, ..}`
|
/// `module::StructName { field, ..}`
|
||||||
Rest,
|
Rest(Span),
|
||||||
/// `module::StructName { field, syntax error }`
|
/// `module::StructName { field, syntax error }`
|
||||||
Recovered(ErrorGuaranteed),
|
Recovered(ErrorGuaranteed),
|
||||||
/// `module::StructName { field }`
|
/// `module::StructName { field }`
|
||||||
@@ -4051,8 +4051,8 @@ mod size_asserts {
|
|||||||
static_assert_size!(Local, 96);
|
static_assert_size!(Local, 96);
|
||||||
static_assert_size!(MetaItemLit, 40);
|
static_assert_size!(MetaItemLit, 40);
|
||||||
static_assert_size!(Param, 40);
|
static_assert_size!(Param, 40);
|
||||||
static_assert_size!(Pat, 72);
|
static_assert_size!(Pat, 80);
|
||||||
static_assert_size!(PatKind, 48);
|
static_assert_size!(PatKind, 56);
|
||||||
static_assert_size!(Path, 24);
|
static_assert_size!(Path, 24);
|
||||||
static_assert_size!(PathSegment, 24);
|
static_assert_size!(PathSegment, 24);
|
||||||
static_assert_size!(Stmt, 32);
|
static_assert_size!(Stmt, 32);
|
||||||
|
|||||||
@@ -1434,10 +1434,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.dcx().emit_err(FunctionalRecordUpdateDestructuringAssignment {
|
self.dcx().emit_err(FunctionalRecordUpdateDestructuringAssignment {
|
||||||
span: e.span,
|
span: e.span,
|
||||||
});
|
});
|
||||||
true
|
Some(self.lower_span(e.span))
|
||||||
}
|
}
|
||||||
StructRest::Rest(_) => true,
|
StructRest::Rest(span) => Some(self.lower_span(*span)),
|
||||||
StructRest::None => false,
|
StructRest::None => None,
|
||||||
};
|
};
|
||||||
let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted);
|
let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted);
|
||||||
return self.pat_without_dbm(lhs.span, struct_pat);
|
return self.pat_without_dbm(lhs.span, struct_pat);
|
||||||
|
|||||||
@@ -2508,7 +2508,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
fields: &'hir [hir::PatField<'hir>],
|
fields: &'hir [hir::PatField<'hir>],
|
||||||
) -> &'hir hir::Pat<'hir> {
|
) -> &'hir hir::Pat<'hir> {
|
||||||
let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span));
|
let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span));
|
||||||
self.pat(span, hir::PatKind::Struct(qpath, fields, false))
|
self.pat(span, hir::PatKind::Struct(qpath, fields, None))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) {
|
fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) {
|
||||||
|
|||||||
@@ -106,10 +106,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
break hir::PatKind::Struct(
|
break hir::PatKind::Struct(
|
||||||
qpath,
|
qpath,
|
||||||
fs,
|
fs,
|
||||||
matches!(
|
match etc {
|
||||||
etc,
|
ast::PatFieldsRest::Rest(sp) => Some(self.lower_span(*sp)),
|
||||||
ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_)
|
ast::PatFieldsRest::Recovered(_) => Some(Span::default()),
|
||||||
),
|
_ => None,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
PatKind::Tuple(pats) => {
|
PatKind::Tuple(pats) => {
|
||||||
|
|||||||
@@ -1769,7 +1769,7 @@ impl<'a> State<'a> {
|
|||||||
},
|
},
|
||||||
|f| f.pat.span,
|
|f| f.pat.span,
|
||||||
);
|
);
|
||||||
if let ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) = etc {
|
if let ast::PatFieldsRest::Rest(_) | ast::PatFieldsRest::Recovered(_) = etc {
|
||||||
if !fields.is_empty() {
|
if !fields.is_empty() {
|
||||||
self.word_space(",");
|
self.word_space(",");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1884,8 +1884,8 @@ pub enum PatKind<'hir> {
|
|||||||
Binding(BindingMode, HirId, Ident, Option<&'hir Pat<'hir>>),
|
Binding(BindingMode, HirId, Ident, Option<&'hir Pat<'hir>>),
|
||||||
|
|
||||||
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
|
/// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
|
||||||
/// The `bool` is `true` in the presence of a `..`.
|
/// The `Option` contains the span of a possible `..`.
|
||||||
Struct(QPath<'hir>, &'hir [PatField<'hir>], bool),
|
Struct(QPath<'hir>, &'hir [PatField<'hir>], Option<Span>),
|
||||||
|
|
||||||
/// A tuple struct/variant pattern `Variant(x, y, .., z)`.
|
/// A tuple struct/variant pattern `Variant(x, y, .., z)`.
|
||||||
/// If the `..` pattern fragment is present, then `DotDotPos` denotes its position.
|
/// If the `..` pattern fragment is present, then `DotDotPos` denotes its position.
|
||||||
@@ -4979,8 +4979,8 @@ mod size_asserts {
|
|||||||
static_assert_size!(ItemKind<'_>, 64);
|
static_assert_size!(ItemKind<'_>, 64);
|
||||||
static_assert_size!(LetStmt<'_>, 72);
|
static_assert_size!(LetStmt<'_>, 72);
|
||||||
static_assert_size!(Param<'_>, 32);
|
static_assert_size!(Param<'_>, 32);
|
||||||
static_assert_size!(Pat<'_>, 72);
|
static_assert_size!(Pat<'_>, 80);
|
||||||
static_assert_size!(PatKind<'_>, 48);
|
static_assert_size!(PatKind<'_>, 56);
|
||||||
static_assert_size!(Path<'_>, 40);
|
static_assert_size!(Path<'_>, 40);
|
||||||
static_assert_size!(PathSegment<'_>, 48);
|
static_assert_size!(PathSegment<'_>, 48);
|
||||||
static_assert_size!(QPath<'_>, 24);
|
static_assert_size!(QPath<'_>, 24);
|
||||||
|
|||||||
@@ -1958,12 +1958,12 @@ impl<'a> State<'a> {
|
|||||||
self.print_qpath(qpath, true);
|
self.print_qpath(qpath, true);
|
||||||
self.nbsp();
|
self.nbsp();
|
||||||
self.word("{");
|
self.word("{");
|
||||||
let empty = fields.is_empty() && !etc;
|
let empty = fields.is_empty() && etc.is_none();
|
||||||
if !empty {
|
if !empty {
|
||||||
self.space();
|
self.space();
|
||||||
}
|
}
|
||||||
self.commasep_cmnt(Consistent, fields, |s, f| s.print_patfield(f), |f| f.pat.span);
|
self.commasep_cmnt(Consistent, fields, |s, f| s.print_patfield(f), |f| f.pat.span);
|
||||||
if etc {
|
if etc.is_some() {
|
||||||
if !fields.is_empty() {
|
if !fields.is_empty() {
|
||||||
self.word_space(",");
|
self.word_space(",");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -605,7 +605,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
},
|
},
|
||||||
PatKind::Struct(_, fields, has_rest_pat) => match opt_path_res.unwrap() {
|
PatKind::Struct(_, fields, has_rest_pat) => match opt_path_res.unwrap() {
|
||||||
Ok(ResolvedPat { ty, kind: ResolvedPatKind::Struct { variant } }) => self
|
Ok(ResolvedPat { ty, kind: ResolvedPatKind::Struct { variant } }) => self
|
||||||
.check_pat_struct(pat, fields, has_rest_pat, ty, variant, expected, pat_info),
|
.check_pat_struct(
|
||||||
|
pat,
|
||||||
|
fields,
|
||||||
|
has_rest_pat.is_some(),
|
||||||
|
ty,
|
||||||
|
variant,
|
||||||
|
expected,
|
||||||
|
pat_info,
|
||||||
|
),
|
||||||
Err(guar) => {
|
Err(guar) => {
|
||||||
let ty_err = Ty::new_error(self.tcx, guar);
|
let ty_err = Ty::new_error(self.tcx, guar);
|
||||||
for field in fields {
|
for field in fields {
|
||||||
@@ -2428,7 +2436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let len = unmentioned_fields.len();
|
let len = unmentioned_fields.len();
|
||||||
let (prefix, postfix, sp) = match fields {
|
let (prefix, postfix, sp) = match fields {
|
||||||
[] => match &pat.kind {
|
[] => match &pat.kind {
|
||||||
PatKind::Struct(path, [], false) => {
|
PatKind::Struct(path, [], None) => {
|
||||||
(" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi()))
|
(" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi()))
|
||||||
}
|
}
|
||||||
_ => return err,
|
_ => return err,
|
||||||
|
|||||||
@@ -1516,7 +1516,7 @@ impl<'a> Parser<'a> {
|
|||||||
|| self.check_noexpect(&token::DotDotDot)
|
|| self.check_noexpect(&token::DotDotDot)
|
||||||
|| self.check_keyword(exp!(Underscore))
|
|| self.check_keyword(exp!(Underscore))
|
||||||
{
|
{
|
||||||
etc = PatFieldsRest::Rest;
|
etc = PatFieldsRest::Rest(self.token.span);
|
||||||
let mut etc_sp = self.token.span;
|
let mut etc_sp = self.token.span;
|
||||||
if first_etc_and_maybe_comma_span.is_none() {
|
if first_etc_and_maybe_comma_span.is_none() {
|
||||||
if let Some(comma_tok) =
|
if let Some(comma_tok) =
|
||||||
|
|||||||
@@ -1583,7 +1583,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let can_remove = match pat.kind {
|
let can_remove = match pat.kind {
|
||||||
hir::PatKind::Struct(_, fields, true) => {
|
hir::PatKind::Struct(_, fields, Some(_)) => {
|
||||||
// if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix
|
// if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix
|
||||||
fields.iter().all(|f| f.is_shorthand)
|
fields.iter().all(|f| f.is_shorthand)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3922,7 +3922,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
|
|
||||||
fn record_patterns_with_skipped_bindings(&mut self, pat: &Pat, rest: &ast::PatFieldsRest) {
|
fn record_patterns_with_skipped_bindings(&mut self, pat: &Pat, rest: &ast::PatFieldsRest) {
|
||||||
match rest {
|
match rest {
|
||||||
ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) => {
|
ast::PatFieldsRest::Rest(_) | ast::PatFieldsRest::Recovered(_) => {
|
||||||
// Record that the pattern doesn't introduce all the bindings it could.
|
// Record that the pattern doesn't introduce all the bindings it could.
|
||||||
if let Some(partial_res) = self.r.partial_res_map.get(&pat.id)
|
if let Some(partial_res) = self.r.partial_res_map.get(&pat.id)
|
||||||
&& let Some(res) = partial_res.full_res()
|
&& let Some(res) = partial_res.full_res()
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
|
|||||||
| PatKind::Never
|
| PatKind::Never
|
||||||
| PatKind::Or(_)
|
| PatKind::Or(_)
|
||||||
| PatKind::Err(_) => false,
|
| PatKind::Err(_) => false,
|
||||||
PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
|
PatKind::Struct(_, a, etc) => etc.is_none() && 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) | PatKind::Deref(x) | PatKind::Guard(x, _) => unary_pattern(x),
|
PatKind::Ref(x, _) | PatKind::Box(x) | PatKind::Deref(x) | PatKind::Guard(x, _) => unary_pattern(x),
|
||||||
PatKind::Expr(_) => true,
|
PatKind::Expr(_) => true,
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ fn replace_in_pattern(
|
|||||||
}
|
}
|
||||||
return or_pat;
|
return or_pat;
|
||||||
},
|
},
|
||||||
PatKind::Struct(path, fields, has_dot_dot) => {
|
PatKind::Struct(path, fields, dot_dot) => {
|
||||||
let fields = fields
|
let fields = fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|fld| {
|
.map(|fld| {
|
||||||
@@ -311,7 +311,7 @@ fn replace_in_pattern(
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let fields_string = fields.join(", ");
|
let fields_string = fields.join(", ");
|
||||||
|
|
||||||
let dot_dot_str = if has_dot_dot { " .." } else { "" };
|
let dot_dot_str = if dot_dot.is_some() { " .." } else { "" };
|
||||||
let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app);
|
let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app);
|
||||||
return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}");
|
return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}");
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use super::REST_PAT_IN_FULLY_BOUND_STRUCTS;
|
|||||||
|
|
||||||
pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
|
pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
|
||||||
if !pat.span.from_expansion()
|
if !pat.span.from_expansion()
|
||||||
&& let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind
|
&& let PatKind::Struct(QPath::Resolved(_, path), fields, Some(_)) = pat.kind
|
||||||
&& let Some(def_id) = path.res.opt_def_id()
|
&& let Some(def_id) = path.res.opt_def_id()
|
||||||
&& let ty = cx.tcx.type_of(def_id).instantiate_identity()
|
&& let ty = cx.tcx.type_of(def_id).instantiate_identity()
|
||||||
&& let ty::Adt(def, _) = ty.kind()
|
&& let ty::Adt(def, _) = ty.kind()
|
||||||
|
|||||||
@@ -754,7 +754,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
|
|||||||
self.ident(name);
|
self.ident(name);
|
||||||
sub.if_some(|p| self.pat(p));
|
sub.if_some(|p| self.pat(p));
|
||||||
},
|
},
|
||||||
PatKind::Struct(ref qpath, fields, ignore) => {
|
PatKind::Struct(ref qpath, fields, etc) => {
|
||||||
|
let ignore = etc.is_some();
|
||||||
bind!(self, qpath, fields);
|
bind!(self, qpath, fields);
|
||||||
kind!("Struct(ref {qpath}, {fields}, {ignore})");
|
kind!("Struct(ref {qpath}, {fields}, {ignore})");
|
||||||
self.qpath(qpath, pat);
|
self.qpath(qpath, pat);
|
||||||
|
|||||||
@@ -2011,7 +2011,7 @@ pub fn is_expr_identity_of_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr<
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(PatKind::Struct(pat_ident, field_pats, false), ExprKind::Struct(ident, fields, hir::StructTailExpr::None))
|
(PatKind::Struct(pat_ident, field_pats, None), ExprKind::Struct(ident, fields, hir::StructTailExpr::None))
|
||||||
if field_pats.len() == fields.len() =>
|
if field_pats.len() == fields.len() =>
|
||||||
{
|
{
|
||||||
// check ident
|
// check ident
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ impl Rewrite for Pat {
|
|||||||
qself,
|
qself,
|
||||||
path,
|
path,
|
||||||
fields,
|
fields,
|
||||||
rest == ast::PatFieldsRest::Rest,
|
matches!(rest, ast::PatFieldsRest::Rest(_)),
|
||||||
self.span,
|
self.span,
|
||||||
context,
|
context,
|
||||||
shape,
|
shape,
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ ast-stats - Path 72 (NN.N%) 1
|
|||||||
ast-stats - Struct 72 (NN.N%) 1
|
ast-stats - Struct 72 (NN.N%) 1
|
||||||
ast-stats - Lit 144 (NN.N%) 2
|
ast-stats - Lit 144 (NN.N%) 2
|
||||||
ast-stats - Block 216 (NN.N%) 3
|
ast-stats - Block 216 (NN.N%) 3
|
||||||
ast-stats Pat 504 (NN.N%) 7 72
|
ast-stats Pat 560 (NN.N%) 7 80
|
||||||
ast-stats - Struct 72 (NN.N%) 1
|
ast-stats - Struct 80 (NN.N%) 1
|
||||||
ast-stats - Wild 72 (NN.N%) 1
|
ast-stats - Wild 80 (NN.N%) 1
|
||||||
ast-stats - Ident 360 (NN.N%) 5
|
ast-stats - Ident 400 (NN.N%) 5
|
||||||
ast-stats GenericParam 480 (NN.N%) 5 96
|
ast-stats GenericParam 480 (NN.N%) 5 96
|
||||||
ast-stats GenericBound 352 (NN.N%) 4 88
|
ast-stats GenericBound 352 (NN.N%) 4 88
|
||||||
ast-stats - Trait 352 (NN.N%) 4
|
ast-stats - Trait 352 (NN.N%) 4
|
||||||
@@ -57,7 +57,7 @@ ast-stats GenericArgs 40 (NN.N%) 1 40
|
|||||||
ast-stats - AngleBracketed 40 (NN.N%) 1
|
ast-stats - AngleBracketed 40 (NN.N%) 1
|
||||||
ast-stats Crate 40 (NN.N%) 1 40
|
ast-stats Crate 40 (NN.N%) 1 40
|
||||||
ast-stats ----------------------------------------------------------------
|
ast-stats ----------------------------------------------------------------
|
||||||
ast-stats Total 7_472 129
|
ast-stats Total 7_528 129
|
||||||
ast-stats ================================================================
|
ast-stats ================================================================
|
||||||
hir-stats ================================================================
|
hir-stats ================================================================
|
||||||
hir-stats HIR STATS: input_stats
|
hir-stats HIR STATS: input_stats
|
||||||
@@ -85,11 +85,11 @@ hir-stats - Ptr 48 (NN.N%) 1
|
|||||||
hir-stats - Ref 48 (NN.N%) 1
|
hir-stats - Ref 48 (NN.N%) 1
|
||||||
hir-stats - Path 624 (NN.N%) 13
|
hir-stats - Path 624 (NN.N%) 13
|
||||||
hir-stats Generics 560 (NN.N%) 10 56
|
hir-stats Generics 560 (NN.N%) 10 56
|
||||||
|
hir-stats Pat 400 (NN.N%) 5 80
|
||||||
|
hir-stats - Struct 80 (NN.N%) 1
|
||||||
|
hir-stats - Wild 80 (NN.N%) 1
|
||||||
|
hir-stats - Binding 240 (NN.N%) 3
|
||||||
hir-stats GenericParam 400 (NN.N%) 5 80
|
hir-stats GenericParam 400 (NN.N%) 5 80
|
||||||
hir-stats Pat 360 (NN.N%) 5 72
|
|
||||||
hir-stats - Struct 72 (NN.N%) 1
|
|
||||||
hir-stats - Wild 72 (NN.N%) 1
|
|
||||||
hir-stats - Binding 216 (NN.N%) 3
|
|
||||||
hir-stats Block 288 (NN.N%) 6 48
|
hir-stats Block 288 (NN.N%) 6 48
|
||||||
hir-stats GenericBound 256 (NN.N%) 4 64
|
hir-stats GenericBound 256 (NN.N%) 4 64
|
||||||
hir-stats - Trait 256 (NN.N%) 4
|
hir-stats - Trait 256 (NN.N%) 4
|
||||||
@@ -119,5 +119,5 @@ hir-stats TraitItemId 8 (NN.N%) 2 4
|
|||||||
hir-stats ImplItemId 8 (NN.N%) 2 4
|
hir-stats ImplItemId 8 (NN.N%) 2 4
|
||||||
hir-stats ForeignItemId 4 (NN.N%) 1 4
|
hir-stats ForeignItemId 4 (NN.N%) 1 4
|
||||||
hir-stats ----------------------------------------------------------------
|
hir-stats ----------------------------------------------------------------
|
||||||
hir-stats Total 8_584 173
|
hir-stats Total 8_624 173
|
||||||
hir-stats ================================================================
|
hir-stats ================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user