Rollup merge of #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 #76222 r? @estebank
This commit is contained in:
commit
5631b5d684
|
@ -1,5 +1,6 @@
|
||||||
use crate::check::FnCtxt;
|
use crate::check::FnCtxt;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
|
|
||||||
use rustc_ast::util::lev_distance::find_best_match_for_name;
|
use rustc_ast::util::lev_distance::find_best_match_for_name;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
|
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
|
||||||
|
@ -740,6 +741,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pat_ty
|
pat_ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn maybe_suggest_range_literal(
|
||||||
|
&self,
|
||||||
|
e: &mut DiagnosticBuilder<'_>,
|
||||||
|
opt_def_id: Option<hir::def_id::DefId>,
|
||||||
|
ident: Ident,
|
||||||
|
) -> bool {
|
||||||
|
match opt_def_id {
|
||||||
|
Some(def_id) => match self.tcx.hir().get_if_local(def_id) {
|
||||||
|
Some(hir::Node::Item(hir::Item {
|
||||||
|
kind: hir::ItemKind::Const(_, body_id), ..
|
||||||
|
})) => match self.tcx.hir().get(body_id.hir_id) {
|
||||||
|
hir::Node::Expr(expr) => {
|
||||||
|
if hir::is_range_literal(expr) {
|
||||||
|
let span = self.tcx.hir().span(body_id.hir_id);
|
||||||
|
if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
|
||||||
|
e.span_suggestion_verbose(
|
||||||
|
ident.span,
|
||||||
|
"you may want to move the range into the match block",
|
||||||
|
snip,
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_bad_pat_path(
|
fn emit_bad_pat_path(
|
||||||
&self,
|
&self,
|
||||||
mut e: DiagnosticBuilder<'_>,
|
mut e: DiagnosticBuilder<'_>,
|
||||||
|
@ -772,12 +807,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let const_def_id = match pat_ty.kind() {
|
let (type_def_id, item_def_id) = match pat_ty.kind() {
|
||||||
Adt(def, _) => match res {
|
Adt(def, _) => match res {
|
||||||
Res::Def(DefKind::Const, _) => Some(def.did),
|
Res::Def(DefKind::Const, def_id) => (Some(def.did), Some(def_id)),
|
||||||
_ => None,
|
_ => (None, None),
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => (None, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ranges = &[
|
let ranges = &[
|
||||||
|
@ -788,11 +823,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.tcx.lang_items().range_inclusive_struct(),
|
self.tcx.lang_items().range_inclusive_struct(),
|
||||||
self.tcx.lang_items().range_to_inclusive_struct(),
|
self.tcx.lang_items().range_to_inclusive_struct(),
|
||||||
];
|
];
|
||||||
if const_def_id != None && ranges.contains(&const_def_id) {
|
if type_def_id != None && ranges.contains(&type_def_id) {
|
||||||
let msg = "constants only support matching by type, \
|
if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
|
||||||
if you meant to match against a range of values, \
|
let msg = "constants only support matching by type, \
|
||||||
consider using a range pattern like `min ..= max` in the match block";
|
if you meant to match against a range of values, \
|
||||||
e.note(msg);
|
consider using a range pattern like `min ..= max` in the match block";
|
||||||
|
e.note(msg);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let msg = "introduce a new binding instead";
|
let msg = "introduce a new binding instead";
|
||||||
let sugg = format!("other_{}", ident.as_str().to_lowercase());
|
let sugg = format!("other_{}", ident.as_str().to_lowercase());
|
||||||
|
|
|
@ -2,13 +2,18 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
const RANGE: RangeInclusive<i32> = 0..=255;
|
const RANGE: RangeInclusive<i32> = 0..=255;
|
||||||
|
|
||||||
|
const RANGE2: RangeInclusive<i32> = panic!();
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let n: i32 = 1;
|
let n: i32 = 1;
|
||||||
match n {
|
match n {
|
||||||
RANGE => {}
|
RANGE => {}
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
|
RANGE2 => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/issue-76191.rs:10:9
|
--> $DIR/issue-76191.rs:13:9
|
||||||
|
|
|
|
||||||
LL | const RANGE: RangeInclusive<i32> = 0..=255;
|
LL | const RANGE: RangeInclusive<i32> = 0..=255;
|
||||||
| ------------------------------------------- constant defined here
|
| ------------------------------------------- constant defined here
|
||||||
|
@ -14,8 +14,30 @@ LL | RANGE => {}
|
||||||
|
|
|
|
||||||
= note: expected type `i32`
|
= note: expected type `i32`
|
||||||
found struct `RangeInclusive<i32>`
|
found struct `RangeInclusive<i32>`
|
||||||
|
help: you may want to move the range into the match block
|
||||||
|
|
|
||||||
|
LL | 0..=255 => {}
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-76191.rs:15:9
|
||||||
|
|
|
||||||
|
LL | const RANGE2: RangeInclusive<i32> = panic!();
|
||||||
|
| --------------------------------------------- constant defined here
|
||||||
|
...
|
||||||
|
LL | match n {
|
||||||
|
| - this expression has type `i32`
|
||||||
|
...
|
||||||
|
LL | RANGE2 => {}
|
||||||
|
| ^^^^^^
|
||||||
|
| |
|
||||||
|
| expected `i32`, found struct `RangeInclusive`
|
||||||
|
| `RANGE2` is interpreted as a constant, not a new binding
|
||||||
|
|
|
||||||
|
= note: expected type `i32`
|
||||||
|
found struct `RangeInclusive<i32>`
|
||||||
= 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
|
= 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
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
Loading…
Reference in New Issue