Skip to content

Commit 2e2e7de

Browse files
committed
Auto merge of rust-lang#76222 - guswynn:const_diag, r=estebank
Give better suggestion when const Range*'s are used as patterns Fixes rust-lang#76191 let me know if there is more/different information you want to show in this case
2 parents 0f5c769 + 5e126c9 commit 2e2e7de

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed

compiler/rustc_typeck/src/check/pat.rs

+34-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_hir::{HirId, Pat, PatKind};
1010
use rustc_infer::infer;
1111
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1212
use rustc_middle::ty::subst::GenericArg;
13-
use rustc_middle::ty::{self, BindingMode, Ty, TypeFoldable};
13+
use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable};
1414
use rustc_span::hygiene::DesugaringKind;
1515
use rustc_span::source_map::{Span, Spanned};
1616
use rustc_span::symbol::Ident;
@@ -735,7 +735,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
735735
if let Some(err) =
736736
self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
737737
{
738-
self.emit_bad_pat_path(err, pat.span, res, pat_res, segments, ti.parent_pat);
738+
self.emit_bad_pat_path(err, pat.span, res, pat_res, pat_ty, segments, ti.parent_pat);
739739
}
740740
pat_ty
741741
}
@@ -746,6 +746,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
746746
pat_span: Span,
747747
res: Res,
748748
pat_res: Res,
749+
pat_ty: Ty<'tcx>,
749750
segments: &'b [hir::PathSegment<'b>],
750751
parent_pat: Option<&Pat<'_>>,
751752
) {
@@ -771,9 +772,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
771772
);
772773
}
773774
_ => {
774-
let msg = "introduce a new binding instead";
775-
let sugg = format!("other_{}", ident.as_str().to_lowercase());
776-
e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders);
775+
let const_def_id = match pat_ty.kind() {
776+
Adt(def, _) => match res {
777+
Res::Def(DefKind::Const, _) => Some(def.did),
778+
_ => None,
779+
},
780+
_ => None,
781+
};
782+
783+
let ranges = &[
784+
self.tcx.lang_items().range_struct(),
785+
self.tcx.lang_items().range_from_struct(),
786+
self.tcx.lang_items().range_to_struct(),
787+
self.tcx.lang_items().range_full_struct(),
788+
self.tcx.lang_items().range_inclusive_struct(),
789+
self.tcx.lang_items().range_to_inclusive_struct(),
790+
];
791+
if const_def_id != None && ranges.contains(&const_def_id) {
792+
let msg = "constants only support matching by type, \
793+
if you meant to match against a range of values, \
794+
consider using a range pattern like `min ..= max` in the match block";
795+
e.note(msg);
796+
} else {
797+
let msg = "introduce a new binding instead";
798+
let sugg = format!("other_{}", ident.as_str().to_lowercase());
799+
e.span_suggestion(
800+
ident.span,
801+
msg,
802+
sugg,
803+
Applicability::HasPlaceholders,
804+
);
805+
}
777806
}
778807
};
779808
}

src/test/ui/issues/issue-76191.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Regression test for diagnostic issue #76191
2+
#![allow(non_snake_case)]
3+
4+
use std::ops::RangeInclusive;
5+
const RANGE: RangeInclusive<i32> = 0..=255;
6+
7+
fn main() {
8+
let n: i32 = 1;
9+
match n {
10+
RANGE => {}
11+
//~^ ERROR mismatched types
12+
_ => {}
13+
}
14+
}

src/test/ui/issues/issue-76191.stderr

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-76191.rs:10:9
3+
|
4+
LL | const RANGE: RangeInclusive<i32> = 0..=255;
5+
| ------------------------------------------- constant defined here
6+
...
7+
LL | match n {
8+
| - this expression has type `i32`
9+
LL | RANGE => {}
10+
| ^^^^^
11+
| |
12+
| expected `i32`, found struct `RangeInclusive`
13+
| `RANGE` is interpreted as a constant, not a new binding
14+
|
15+
= note: expected type `i32`
16+
found struct `RangeInclusive<i32>`
17+
= note: constants only support matching by type, if you meant to match against a range of values, consider using a range pattern like `min ..= max` in the match block
18+
19+
error: aborting due to previous error
20+
21+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)