Skip to content

Commit 696f182

Browse files
committed
Fix non_exhaustive_omitted_patterns lint span
1 parent a5a690c commit 696f182

File tree

4 files changed

+46
-21
lines changed

4 files changed

+46
-21
lines changed

Diff for: compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

+19-16
Original file line numberDiff line numberDiff line change
@@ -1154,8 +1154,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11541154
fn wildcards_from_tys(
11551155
cx: &MatchCheckCtxt<'p, 'tcx>,
11561156
tys: impl IntoIterator<Item = Ty<'tcx>>,
1157+
span: Span,
11571158
) -> Self {
1158-
Fields::from_iter(cx, tys.into_iter().map(DeconstructedPat::wildcard))
1159+
Fields::from_iter(cx, tys.into_iter().map(|ty| DeconstructedPat::wildcard(ty, span)))
11591160
}
11601161

11611162
// In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
@@ -1191,26 +1192,26 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
11911192
pub(super) fn wildcards(pcx: &PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
11921193
let ret = match constructor {
11931194
Single | Variant(_) => match pcx.ty.kind() {
1194-
ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter()),
1195-
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty)),
1195+
ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter(), pcx.span),
1196+
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty), pcx.span),
11961197
ty::Adt(adt, substs) => {
11971198
if adt.is_box() {
11981199
// The only legal patterns of type `Box` (outside `std`) are `_` and box
11991200
// patterns. If we're here we can assume this is a box pattern.
1200-
Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)))
1201+
Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)), pcx.span)
12011202
} else {
12021203
let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
12031204
let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant)
12041205
.map(|(_, ty)| ty);
1205-
Fields::wildcards_from_tys(pcx.cx, tys)
1206+
Fields::wildcards_from_tys(pcx.cx, tys, pcx.span)
12061207
}
12071208
}
12081209
_ => bug!("Unexpected type for `Single` constructor: {:?}", pcx),
12091210
},
12101211
Slice(slice) => match *pcx.ty.kind() {
12111212
ty::Slice(ty) | ty::Array(ty, _) => {
12121213
let arity = slice.arity();
1213-
Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty))
1214+
Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty), pcx.span)
12141215
}
12151216
_ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
12161217
},
@@ -1251,8 +1252,8 @@ pub(crate) struct DeconstructedPat<'p, 'tcx> {
12511252
}
12521253

12531254
impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
1254-
pub(super) fn wildcard(ty: Ty<'tcx>) -> Self {
1255-
Self::new(Wildcard, Fields::empty(), ty, DUMMY_SP)
1255+
pub(super) fn wildcard(ty: Ty<'tcx>, span: Span) -> Self {
1256+
Self::new(Wildcard, Fields::empty(), ty, span)
12561257
}
12571258

12581259
pub(super) fn new(
@@ -1269,7 +1270,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
12691270
/// `Some(_)`.
12701271
pub(super) fn wild_from_ctor(pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self {
12711272
let fields = Fields::wildcards(pcx, &ctor);
1272-
DeconstructedPat::new(ctor, fields, pcx.ty, DUMMY_SP)
1273+
DeconstructedPat::new(ctor, fields, pcx.ty, pcx.span)
12731274
}
12741275

12751276
/// Clone this value. This method emphasizes that cloning loses reachability information and
@@ -1298,7 +1299,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
12981299
ty::Tuple(fs) => {
12991300
ctor = Single;
13001301
let mut wilds: SmallVec<[_; 2]> =
1301-
fs.iter().map(DeconstructedPat::wildcard).collect();
1302+
fs.iter().map(|ty| DeconstructedPat::wildcard(ty, pat.span)).collect();
13021303
for pat in subpatterns {
13031304
wilds[pat.field.index()] = mkpat(&pat.pattern);
13041305
}
@@ -1317,11 +1318,11 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
13171318
// normally or through box-patterns. We'll have to figure out a proper
13181319
// solution when we introduce generalized deref patterns. Also need to
13191320
// prevent mixing of those two options.
1320-
let pat = subpatterns.into_iter().find(|pat| pat.field.index() == 0);
1321-
let pat = if let Some(pat) = pat {
1321+
let pattern = subpatterns.into_iter().find(|pat| pat.field.index() == 0);
1322+
let pat = if let Some(pat) = pattern {
13221323
mkpat(&pat.pattern)
13231324
} else {
1324-
DeconstructedPat::wildcard(substs.type_at(0))
1325+
DeconstructedPat::wildcard(substs.type_at(0), pat.span)
13251326
};
13261327
ctor = Single;
13271328
fields = Fields::singleton(cx, pat);
@@ -1343,7 +1344,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
13431344
ty
13441345
});
13451346
let mut wilds: SmallVec<[_; 2]> =
1346-
tys.map(DeconstructedPat::wildcard).collect();
1347+
tys.map(|ty| DeconstructedPat::wildcard(ty, pat.span)).collect();
13471348
for pat in subpatterns {
13481349
if let Some(i) = field_id_to_id[pat.field.index()] {
13491350
wilds[i] = mkpat(&pat.pattern);
@@ -1566,8 +1567,10 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
15661567
};
15671568
let prefix = &self.fields.fields[..prefix];
15681569
let suffix = &self.fields.fields[self_slice.arity() - suffix..];
1569-
let wildcard: &_ =
1570-
pcx.cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
1570+
let wildcard: &_ = pcx
1571+
.cx
1572+
.pattern_arena
1573+
.alloc(DeconstructedPat::wildcard(inner_ty, pcx.span));
15711574
let extra_wildcards = other_slice.arity() - self_slice.arity();
15721575
let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
15731576
prefix.iter().chain(extra_wildcards).chain(suffix).collect()

Diff for: compiler/rustc_mir_build/src/thir/pattern/usefulness.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
604604
let new_patterns = if pcx.is_non_exhaustive {
605605
// Here we don't want the user to try to list all variants, we want them to add
606606
// a wildcard, so we only suggest that.
607-
vec![DeconstructedPat::wildcard(pcx.ty)]
607+
vec![DeconstructedPat::wildcard(pcx.ty, pcx.span)]
608608
} else {
609609
let mut split_wildcard = SplitWildcard::new(pcx);
610610
split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor));
@@ -631,7 +631,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
631631
.collect();
632632

633633
if hide_variant_show_wild {
634-
new.push(DeconstructedPat::wildcard(pcx.ty));
634+
new.push(DeconstructedPat::wildcard(pcx.ty, pcx.span));
635635
}
636636

637637
new
@@ -734,7 +734,7 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
734734
let arity = ctor.arity(pcx);
735735
let pats = self.0.drain((len - arity)..).rev();
736736
let fields = Fields::from_iter(pcx.cx, pats);
737-
DeconstructedPat::new(ctor.clone(), fields, pcx.ty, DUMMY_SP)
737+
DeconstructedPat::new(ctor.clone(), fields, pcx.ty, pcx.span)
738738
};
739739

740740
self.0.push(pat);
@@ -977,7 +977,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
977977
})
978978
.collect();
979979

980-
let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty));
980+
let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty, DUMMY_SP));
981981
let v = PatStack::from_pattern(wild_pattern);
982982
let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, scrut_hir_id, false, true);
983983
let non_exhaustiveness_witnesses = match usefulness {

Diff for: tests/ui/rfc-2008-non-exhaustive/omitted-patterns.rs

+8
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ fn main() {
194194
let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
195195
//~^ refutable pattern in local binding
196196

197+
// Check that matching on a reference results in a correctly spanned diagnostic
198+
#[deny(non_exhaustive_omitted_patterns)]
199+
match &non_enum {
200+
NonExhaustiveEnum::Unit => {}
201+
NonExhaustiveEnum::Tuple(_) => {}
202+
_ => {}
203+
}
204+
//~^^ some variants are not matched explicitly
197205
}
198206

199207
#[deny(non_exhaustive_omitted_patterns)]

Diff for: tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr

+15-1
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,20 @@ help: you might want to use `let else` to handle the variant that isn't matched
198198
LL | let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit else { todo!() };
199199
| ++++++++++++++++
200200

201-
error: aborting due to 9 previous errors; 6 warnings emitted
201+
error: some variants are not matched explicitly
202+
--> $DIR/omitted-patterns.rs:202:9
203+
|
204+
LL | _ => {}
205+
| ^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
206+
|
207+
= help: ensure that all variants are matched explicitly by adding the suggested match arms
208+
= note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
209+
note: the lint level is defined here
210+
--> $DIR/omitted-patterns.rs:198:12
211+
|
212+
LL | #[deny(non_exhaustive_omitted_patterns)]
213+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
214+
215+
error: aborting due to 10 previous errors; 6 warnings emitted
202216

203217
For more information about this error, try `rustc --explain E0005`.

0 commit comments

Comments
 (0)