better diag when const ranges are used in patterns
This commit is contained in:
parent
141bb23be8
commit
5e126c944b
|
@ -10,7 +10,7 @@ use rustc_hir::{HirId, Pat, PatKind};
|
||||||
use rustc_infer::infer;
|
use rustc_infer::infer;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_middle::ty::subst::GenericArg;
|
use rustc_middle::ty::subst::GenericArg;
|
||||||
use rustc_middle::ty::{self, BindingMode, Ty, TypeFoldable};
|
use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable};
|
||||||
use rustc_span::hygiene::DesugaringKind;
|
use rustc_span::hygiene::DesugaringKind;
|
||||||
use rustc_span::source_map::{Span, Spanned};
|
use rustc_span::source_map::{Span, Spanned};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
|
@ -735,7 +735,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
if let Some(err) =
|
if let Some(err) =
|
||||||
self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
|
self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
|
||||||
{
|
{
|
||||||
self.emit_bad_pat_path(err, pat.span, res, pat_res, segments, ti.parent_pat);
|
self.emit_bad_pat_path(err, pat.span, res, pat_res, pat_ty, segments, ti.parent_pat);
|
||||||
}
|
}
|
||||||
pat_ty
|
pat_ty
|
||||||
}
|
}
|
||||||
|
@ -746,6 +746,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pat_span: Span,
|
pat_span: Span,
|
||||||
res: Res,
|
res: Res,
|
||||||
pat_res: Res,
|
pat_res: Res,
|
||||||
|
pat_ty: Ty<'tcx>,
|
||||||
segments: &'b [hir::PathSegment<'b>],
|
segments: &'b [hir::PathSegment<'b>],
|
||||||
parent_pat: Option<&Pat<'_>>,
|
parent_pat: Option<&Pat<'_>>,
|
||||||
) {
|
) {
|
||||||
|
@ -771,9 +772,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let msg = "introduce a new binding instead";
|
let const_def_id = match pat_ty.kind() {
|
||||||
let sugg = format!("other_{}", ident.as_str().to_lowercase());
|
Adt(def, _) => match res {
|
||||||
e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders);
|
Res::Def(DefKind::Const, _) => Some(def.did),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ranges = &[
|
||||||
|
self.tcx.lang_items().range_struct(),
|
||||||
|
self.tcx.lang_items().range_from_struct(),
|
||||||
|
self.tcx.lang_items().range_to_struct(),
|
||||||
|
self.tcx.lang_items().range_full_struct(),
|
||||||
|
self.tcx.lang_items().range_inclusive_struct(),
|
||||||
|
self.tcx.lang_items().range_to_inclusive_struct(),
|
||||||
|
];
|
||||||
|
if const_def_id != None && ranges.contains(&const_def_id) {
|
||||||
|
let msg = "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";
|
||||||
|
e.note(msg);
|
||||||
|
} else {
|
||||||
|
let msg = "introduce a new binding instead";
|
||||||
|
let sugg = format!("other_{}", ident.as_str().to_lowercase());
|
||||||
|
e.span_suggestion(
|
||||||
|
ident.span,
|
||||||
|
msg,
|
||||||
|
sugg,
|
||||||
|
Applicability::HasPlaceholders,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Regression test for diagnostic issue #76191
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
|
use std::ops::RangeInclusive;
|
||||||
|
const RANGE: RangeInclusive<i32> = 0..=255;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let n: i32 = 1;
|
||||||
|
match n {
|
||||||
|
RANGE => {}
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-76191.rs:10:9
|
||||||
|
|
|
||||||
|
LL | const RANGE: RangeInclusive<i32> = 0..=255;
|
||||||
|
| ------------------------------------------- constant defined here
|
||||||
|
...
|
||||||
|
LL | match n {
|
||||||
|
| - this expression has type `i32`
|
||||||
|
LL | RANGE => {}
|
||||||
|
| ^^^^^
|
||||||
|
| |
|
||||||
|
| expected `i32`, found struct `RangeInclusive`
|
||||||
|
| `RANGE` 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
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue