Skip to content

Commit 30e8ec6

Browse files
authored
Rollup merge of rust-lang#76749 - guswynn:hir_ranges, r=estebank
give *even better* suggestion when matching a const range notice that the err already has "constant defined here" so this is now *exceedingly clear* extension to rust-lang#76222 r? @estebank
2 parents d8892b4 + 230355f commit 30e8ec6

File tree

3 files changed

+75
-11
lines changed

3 files changed

+75
-11
lines changed

Diff for: compiler/rustc_typeck/src/check/pat.rs

+46-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::check::FnCtxt;
22
use rustc_ast as ast;
3+
34
use rustc_ast::util::lev_distance::find_best_match_for_name;
45
use rustc_data_structures::fx::FxHashMap;
56
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
@@ -740,6 +741,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
740741
pat_ty
741742
}
742743

744+
fn maybe_suggest_range_literal(
745+
&self,
746+
e: &mut DiagnosticBuilder<'_>,
747+
opt_def_id: Option<hir::def_id::DefId>,
748+
ident: Ident,
749+
) -> bool {
750+
match opt_def_id {
751+
Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
752+
Some(hir::Node::Item(hir::Item {
753+
kind: hir::ItemKind::Const(_, body_id), ..
754+
})) => match self.tcx.hir().get(body_id.hir_id) {
755+
hir::Node::Expr(expr) => {
756+
if hir::is_range_literal(expr) {
757+
let span = self.tcx.hir().span(body_id.hir_id);
758+
if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
759+
e.span_suggestion_verbose(
760+
ident.span,
761+
"you may want to move the range into the match block",
762+
snip,
763+
Applicability::MachineApplicable,
764+
);
765+
return true;
766+
}
767+
}
768+
}
769+
_ => (),
770+
},
771+
_ => (),
772+
},
773+
_ => (),
774+
}
775+
false
776+
}
777+
743778
fn emit_bad_pat_path(
744779
&self,
745780
mut e: DiagnosticBuilder<'_>,
@@ -772,12 +807,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
772807
);
773808
}
774809
_ => {
775-
let const_def_id = match pat_ty.kind() {
810+
let (type_def_id, item_def_id) = match pat_ty.kind() {
776811
Adt(def, _) => match res {
777-
Res::Def(DefKind::Const, _) => Some(def.did),
778-
_ => None,
812+
Res::Def(DefKind::Const, def_id) => (Some(def.did), Some(def_id)),
813+
_ => (None, None),
779814
},
780-
_ => None,
815+
_ => (None, None),
781816
};
782817

783818
let ranges = &[
@@ -788,11 +823,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
788823
self.tcx.lang_items().range_inclusive_struct(),
789824
self.tcx.lang_items().range_to_inclusive_struct(),
790825
];
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);
826+
if type_def_id != None && ranges.contains(&type_def_id) {
827+
if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
828+
let msg = "constants only support matching by type, \
829+
if you meant to match against a range of values, \
830+
consider using a range pattern like `min ..= max` in the match block";
831+
e.note(msg);
832+
}
796833
} else {
797834
let msg = "introduce a new binding instead";
798835
let sugg = format!("other_{}", ident.as_str().to_lowercase());

Diff for: src/test/ui/issues/issue-76191.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22
#![allow(non_snake_case)]
33

44
use std::ops::RangeInclusive;
5+
56
const RANGE: RangeInclusive<i32> = 0..=255;
67

8+
const RANGE2: RangeInclusive<i32> = panic!();
9+
710
fn main() {
811
let n: i32 = 1;
912
match n {
1013
RANGE => {}
1114
//~^ ERROR mismatched types
15+
RANGE2 => {}
16+
//~^ ERROR mismatched types
1217
_ => {}
1318
}
1419
}

Diff for: src/test/ui/issues/issue-76191.stderr

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/issue-76191.rs:10:9
2+
--> $DIR/issue-76191.rs:13:9
33
|
44
LL | const RANGE: RangeInclusive<i32> = 0..=255;
55
| ------------------------------------------- constant defined here
@@ -14,8 +14,30 @@ LL | RANGE => {}
1414
|
1515
= note: expected type `i32`
1616
found struct `RangeInclusive<i32>`
17+
help: you may want to move the range into the match block
18+
|
19+
LL | 0..=255 => {}
20+
| ^^^^^^^
21+
22+
error[E0308]: mismatched types
23+
--> $DIR/issue-76191.rs:15:9
24+
|
25+
LL | const RANGE2: RangeInclusive<i32> = panic!();
26+
| --------------------------------------------- constant defined here
27+
...
28+
LL | match n {
29+
| - this expression has type `i32`
30+
...
31+
LL | RANGE2 => {}
32+
| ^^^^^^
33+
| |
34+
| expected `i32`, found struct `RangeInclusive`
35+
| `RANGE2` is interpreted as a constant, not a new binding
36+
|
37+
= note: expected type `i32`
38+
found struct `RangeInclusive<i32>`
1739
= 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
1840

19-
error: aborting due to previous error
41+
error: aborting due to 2 previous errors
2042

2143
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)