Rollup merge of #106097 - mejrs:mir_build2, r=oli-obk
Migrate mir_build diagnostics 2 of 3 The first three commits are fairly boring, however I've made some changes to the output of the match checking diagnostics.
This commit is contained in:
commit
83d3b76ac2
39 changed files with 568 additions and 488 deletions
|
@ -303,3 +303,64 @@ mir_build_multiple_mut_borrows = cannot borrow value as mutable more than once a
|
|||
.mutable_borrow = another mutable borrow, by `{$name_mut}`, occurs here
|
||||
.immutable_borrow = also borrowed as immutable, by `{$name_immut}`, here
|
||||
.moved = also moved into `{$name_moved}` here
|
||||
|
||||
mir_build_union_pattern = cannot use unions in constant patterns
|
||||
|
||||
mir_build_type_not_structural =
|
||||
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
mir_build_unsized_pattern = cannot use unsized non-slice type `{$non_sm_ty}` in constant patterns
|
||||
|
||||
mir_build_invalid_pattern = `{$non_sm_ty}` cannot be used in patterns
|
||||
|
||||
mir_build_float_pattern = floating-point types cannot be used in patterns
|
||||
|
||||
mir_build_pointer_pattern = function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
|
||||
|
||||
mir_build_indirect_structural_match =
|
||||
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
mir_build_nontrivial_structural_match =
|
||||
to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]`
|
||||
|
||||
mir_build_overlapping_range_endpoints = multiple patterns overlap on their endpoints
|
||||
.range = ... with this range
|
||||
.note = you likely meant to write mutually exclusive ranges
|
||||
|
||||
mir_build_non_exhaustive_omitted_pattern = some variants are not matched explicitly
|
||||
.help = ensure that all variants are matched explicitly by adding the suggested match arms
|
||||
.note = the matched value is of type `{$scrut_ty}` and the `non_exhaustive_omitted_patterns` attribute was found
|
||||
|
||||
mir_build_uncovered = {$count ->
|
||||
[1] pattern `{$witness_1}`
|
||||
[2] patterns `{$witness_1}` and `{$witness_2}`
|
||||
[3] patterns `{$witness_1}`, `{$witness_2}` and `{$witness_3}`
|
||||
*[other] patterns `{$witness_1}`, `{$witness_2}`, `{$witness_3}` and {$remainder} more
|
||||
} not covered
|
||||
|
||||
mir_build_pattern_not_covered = refutable pattern in {$origin}
|
||||
.pattern_ty = the matched value is of type `{$pattern_ty}`
|
||||
|
||||
mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
|
||||
mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
|
||||
mir_build_res_defined_here = {$res} defined here
|
||||
|
||||
mir_build_adt_defined_here = `{$ty}` defined here
|
||||
|
||||
mir_build_variant_defined_here = not covered
|
||||
|
||||
mir_build_interpreted_as_const = introduce a variable instead
|
||||
|
||||
mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as {$article} {$res} pattern, not a new variable
|
||||
|
||||
mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count ->
|
||||
[one] variant that isn't
|
||||
*[other] variants that aren't
|
||||
} matched
|
||||
|
||||
mir_build_suggest_let_else = you might want to use `let else` to handle the {$count ->
|
||||
[one] variant that isn't
|
||||
*[other] variants that aren't
|
||||
} matched
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
|
||||
|
||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::RangeEnd;
|
||||
|
@ -575,6 +576,12 @@ impl<'tcx> Pat<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
format!("{}", self).into_diagnostic_arg()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable)]
|
||||
pub struct Ascription<'tcx> {
|
||||
pub annotation: CanonicalUserTypeAnnotation<'tcx>,
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
use crate::thir::pattern::deconstruct_pat::DeconstructedPat;
|
||||
use crate::thir::pattern::MatchCheckCtxt;
|
||||
use rustc_errors::Handler;
|
||||
use rustc_errors::{
|
||||
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan,
|
||||
error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
||||
IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
|
||||
};
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::thir::Pat;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{symbol::Ident, Span};
|
||||
|
||||
|
@ -624,3 +628,223 @@ pub enum MultipleMutBorrowOccurence {
|
|||
name_moved: Ident,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_union_pattern)]
|
||||
pub struct UnionPattern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_type_not_structural)]
|
||||
pub struct TypeNotStructural<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub non_sm_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_invalid_pattern)]
|
||||
pub struct InvalidPattern<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub non_sm_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_unsized_pattern)]
|
||||
pub struct UnsizedPattern<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub non_sm_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_float_pattern)]
|
||||
pub struct FloatPattern;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_pointer_pattern)]
|
||||
pub struct PointerPattern;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_indirect_structural_match)]
|
||||
pub struct IndirectStructuralMatch<'tcx> {
|
||||
pub non_sm_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_nontrivial_structural_match)]
|
||||
pub struct NontrivialStructuralMatch<'tcx> {
|
||||
pub non_sm_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_overlapping_range_endpoints)]
|
||||
#[note]
|
||||
pub struct OverlappingRangeEndpoints<'tcx> {
|
||||
#[label(range)]
|
||||
pub range: Span,
|
||||
#[subdiagnostic]
|
||||
pub overlap: Vec<Overlap<'tcx>>,
|
||||
}
|
||||
|
||||
pub struct Overlap<'tcx> {
|
||||
pub span: Span,
|
||||
pub range: Pat<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
let Overlap { span, range } = self;
|
||||
|
||||
// FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]`
|
||||
// does not support `#[subdiagnostic(eager)]`...
|
||||
let message = format!("this range overlaps on `{range}`...");
|
||||
diag.span_label(span, message);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(mir_build_non_exhaustive_omitted_pattern)]
|
||||
#[help]
|
||||
#[note]
|
||||
pub(crate) struct NonExhaustiveOmittedPattern<'tcx> {
|
||||
pub scrut_ty: Ty<'tcx>,
|
||||
#[subdiagnostic]
|
||||
pub uncovered: Uncovered<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[label(mir_build_uncovered)]
|
||||
pub(crate) struct Uncovered<'tcx> {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
count: usize,
|
||||
witness_1: Pat<'tcx>,
|
||||
witness_2: Pat<'tcx>,
|
||||
witness_3: Pat<'tcx>,
|
||||
remainder: usize,
|
||||
}
|
||||
|
||||
impl<'tcx> Uncovered<'tcx> {
|
||||
pub fn new<'p>(
|
||||
span: Span,
|
||||
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||
witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
|
||||
) -> Self {
|
||||
let witness_1 = witnesses.get(0).unwrap().to_pat(cx);
|
||||
Self {
|
||||
span,
|
||||
count: witnesses.len(),
|
||||
// Substitute dummy values if witnesses is smaller than 3. These will never be read.
|
||||
witness_2: witnesses.get(1).map(|w| w.to_pat(cx)).unwrap_or_else(|| witness_1.clone()),
|
||||
witness_3: witnesses.get(2).map(|w| w.to_pat(cx)).unwrap_or_else(|| witness_1.clone()),
|
||||
witness_1,
|
||||
remainder: witnesses.len().saturating_sub(3),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_pattern_not_covered, code = "E0005")]
|
||||
pub(crate) struct PatternNotCovered<'s, 'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub origin: &'s str,
|
||||
#[subdiagnostic]
|
||||
pub uncovered: Uncovered<'tcx>,
|
||||
#[subdiagnostic]
|
||||
pub inform: Option<Inform>,
|
||||
#[subdiagnostic]
|
||||
pub interpreted_as_const: Option<InterpretedAsConst>,
|
||||
#[subdiagnostic]
|
||||
pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
|
||||
#[note(pattern_ty)]
|
||||
pub _p: (),
|
||||
pub pattern_ty: Ty<'tcx>,
|
||||
#[subdiagnostic]
|
||||
pub let_suggestion: Option<SuggestLet>,
|
||||
#[subdiagnostic]
|
||||
pub res_defined_here: Option<ResDefinedHere>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[note(mir_build_inform_irrefutable)]
|
||||
#[note(mir_build_more_information)]
|
||||
pub struct Inform;
|
||||
|
||||
pub struct AdtDefinedHere<'tcx> {
|
||||
pub adt_def_span: Span,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub variants: Vec<Variant>,
|
||||
}
|
||||
|
||||
pub struct Variant {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
|
||||
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||
where
|
||||
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||
{
|
||||
diag.set_arg("ty", self.ty);
|
||||
let mut spans = MultiSpan::from(self.adt_def_span);
|
||||
|
||||
for Variant { span } in self.variants {
|
||||
spans.push_span_label(span, rustc_errors::fluent::mir_build_variant_defined_here);
|
||||
}
|
||||
|
||||
diag.span_note(spans, rustc_errors::fluent::mir_build_adt_defined_here);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[label(mir_build_res_defined_here)]
|
||||
pub struct ResDefinedHere {
|
||||
#[primary_span]
|
||||
pub def_span: Span,
|
||||
pub res: Res,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
mir_build_interpreted_as_const,
|
||||
code = "{variable}_var",
|
||||
applicability = "maybe-incorrect"
|
||||
)]
|
||||
#[label(mir_build_confused)]
|
||||
pub struct InterpretedAsConst {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub article: &'static str,
|
||||
pub variable: String,
|
||||
pub res: Res,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum SuggestLet {
|
||||
#[multipart_suggestion(mir_build_suggest_if_let, applicability = "has-placeholders")]
|
||||
If {
|
||||
#[suggestion_part(code = "if ")]
|
||||
start_span: Span,
|
||||
#[suggestion_part(code = " {{ todo!() }}")]
|
||||
semi_span: Span,
|
||||
count: usize,
|
||||
},
|
||||
#[suggestion(
|
||||
mir_build_suggest_let_else,
|
||||
code = " else {{ todo!() }}",
|
||||
applicability = "has-placeholders"
|
||||
)]
|
||||
Else {
|
||||
#[primary_span]
|
||||
end_span: Span,
|
||||
count: usize,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -9,8 +9,7 @@ use crate::errors::*;
|
|||
use rustc_arena::TypedArena;
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_errors::{
|
||||
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
|
||||
MultiSpan,
|
||||
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::*;
|
||||
|
@ -378,8 +377,8 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||
|
||||
let pattern = self.lower_pattern(&mut cx, pat, &mut false);
|
||||
let pattern_ty = pattern.ty();
|
||||
let arms = vec![MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false }];
|
||||
let report = compute_match_usefulness(&cx, &arms, pat.hir_id, pattern_ty);
|
||||
let arm = MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false };
|
||||
let report = compute_match_usefulness(&cx, &[arm], pat.hir_id, pattern_ty);
|
||||
|
||||
// Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We
|
||||
// only care about exhaustiveness here.
|
||||
|
@ -390,145 +389,73 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
let joined_patterns = joined_uncovered_patterns(&cx, &witnesses);
|
||||
|
||||
let mut bindings = vec![];
|
||||
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess,
|
||||
pat.span,
|
||||
E0005,
|
||||
"refutable pattern in {}: {} not covered",
|
||||
origin,
|
||||
joined_patterns
|
||||
);
|
||||
let suggest_if_let = match &pat.kind {
|
||||
hir::PatKind::Path(hir::QPath::Resolved(None, path))
|
||||
if path.segments.len() == 1 && path.segments[0].args.is_none() =>
|
||||
let (inform, interpreted_as_const, res_defined_here,let_suggestion) =
|
||||
if let hir::PatKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
hir::Path {
|
||||
segments: &[hir::PathSegment { args: None, res, ident, .. }],
|
||||
..
|
||||
},
|
||||
)) = &pat.kind
|
||||
{
|
||||
const_not_var(&mut err, cx.tcx, pat, path);
|
||||
false
|
||||
(
|
||||
None,
|
||||
Some(InterpretedAsConst {
|
||||
span: pat.span,
|
||||
article: res.article(),
|
||||
variable: ident.to_string().to_lowercase(),
|
||||
res,
|
||||
}),
|
||||
try {
|
||||
ResDefinedHere {
|
||||
def_span: cx.tcx.hir().res_span(res)?,
|
||||
res,
|
||||
}
|
||||
_ => {
|
||||
pat.walk(&mut |pat: &hir::Pat<'_>| {
|
||||
match pat.kind {
|
||||
hir::PatKind::Binding(_, _, ident, _) => {
|
||||
},
|
||||
None,
|
||||
)
|
||||
} else if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) {
|
||||
let mut bindings = vec![];
|
||||
pat.walk_always(&mut |pat: &hir::Pat<'_>| {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
|
||||
bindings.push(ident);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
true
|
||||
});
|
||||
|
||||
err.span_label(pat.span, pattern_not_covered_label(&witnesses, &joined_patterns));
|
||||
true
|
||||
}
|
||||
};
|
||||
|
||||
if let (Some(span), true) = (sp, suggest_if_let) {
|
||||
err.note(
|
||||
"`let` bindings require an \"irrefutable pattern\", like a `struct` or \
|
||||
an `enum` with only one variant",
|
||||
);
|
||||
if self.tcx.sess.source_map().is_span_accessible(span) {
|
||||
let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1));
|
||||
let start_span = span.shrink_to_lo();
|
||||
let end_span = semi_span.shrink_to_lo();
|
||||
err.multipart_suggestion(
|
||||
&format!(
|
||||
"you might want to use `if let` to ignore the variant{} that {} matched",
|
||||
pluralize!(witnesses.len()),
|
||||
match witnesses.len() {
|
||||
1 => "isn't",
|
||||
_ => "aren't",
|
||||
},
|
||||
),
|
||||
vec![
|
||||
match &bindings[..] {
|
||||
[] => (start_span, "if ".to_string()),
|
||||
[binding] => (start_span, format!("let {} = if ", binding)),
|
||||
bindings => (
|
||||
start_span,
|
||||
format!(
|
||||
"let ({}) = if ",
|
||||
bindings
|
||||
.iter()
|
||||
.map(|ident| ident.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
),
|
||||
},
|
||||
match &bindings[..] {
|
||||
[] => (semi_span, " { todo!() }".to_string()),
|
||||
[binding] => {
|
||||
(end_span, format!(" {{ {} }} else {{ todo!() }}", binding))
|
||||
}
|
||||
bindings => (
|
||||
end_span,
|
||||
format!(
|
||||
" {{ ({}) }} else {{ todo!() }}",
|
||||
bindings
|
||||
.iter()
|
||||
.map(|ident| ident.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
),
|
||||
},
|
||||
],
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
if !bindings.is_empty() {
|
||||
err.span_suggestion_verbose(
|
||||
semi_span.shrink_to_lo(),
|
||||
&format!(
|
||||
"alternatively, you might want to use \
|
||||
let else to handle the variant{} that {} matched",
|
||||
pluralize!(witnesses.len()),
|
||||
match witnesses.len() {
|
||||
1 => "isn't",
|
||||
_ => "aren't",
|
||||
},
|
||||
),
|
||||
" else { todo!() }",
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
err.note(
|
||||
"for more information, visit \
|
||||
https://doc.rust-lang.org/book/ch18-02-refutability.html",
|
||||
);
|
||||
}
|
||||
let count = witnesses.len();
|
||||
|
||||
adt_defined_here(&cx, &mut err, pattern_ty, &witnesses);
|
||||
err.note(&format!("the matched value is of type `{}`", pattern_ty));
|
||||
err.emit();
|
||||
let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }};
|
||||
(sp.map(|_|Inform), None, None, Some(let_suggestion))
|
||||
} else{
|
||||
(sp.map(|_|Inform), None, None, None)
|
||||
};
|
||||
|
||||
let adt_defined_here = try {
|
||||
let ty = pattern_ty.peel_refs();
|
||||
let ty::Adt(def, _) = ty.kind() else { None? };
|
||||
let adt_def_span = cx.tcx.hir().get_if_local(def.did())?.ident()?.span;
|
||||
let mut variants = vec![];
|
||||
|
||||
for span in maybe_point_at_variant(&cx, *def, witnesses.iter().take(5)) {
|
||||
variants.push(Variant { span });
|
||||
}
|
||||
}
|
||||
AdtDefinedHere { adt_def_span, ty, variants }
|
||||
};
|
||||
|
||||
/// A path pattern was interpreted as a constant, not a new variable.
|
||||
/// This caused an irrefutable match failure in e.g. `let`.
|
||||
fn const_not_var(err: &mut Diagnostic, tcx: TyCtxt<'_>, pat: &Pat<'_>, path: &hir::Path<'_>) {
|
||||
let descr = path.res.descr();
|
||||
err.span_label(
|
||||
pat.span,
|
||||
format!("interpreted as {} {} pattern, not a new variable", path.res.article(), descr,),
|
||||
);
|
||||
|
||||
err.span_suggestion(
|
||||
pat.span,
|
||||
"introduce a variable instead",
|
||||
format!("{}_var", path.segments[0].ident).to_lowercase(),
|
||||
// Cannot use `MachineApplicable` as it's not really *always* correct
|
||||
// because there may be such an identifier in scope or the user maybe
|
||||
// really wanted to match against the constant. This is quite unlikely however.
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
if let Some(span) = tcx.hir().res_span(path.res) {
|
||||
err.span_label(span, format!("{} defined here", descr));
|
||||
self.tcx.sess.emit_err(PatternNotCovered {
|
||||
span: pat.span,
|
||||
origin,
|
||||
uncovered: Uncovered::new(pat.span, &cx, witnesses),
|
||||
inform,
|
||||
interpreted_as_const,
|
||||
_p: (),
|
||||
pattern_ty,
|
||||
let_suggestion,
|
||||
res_defined_here,
|
||||
adt_defined_here,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use rustc_errors::DelayDm;
|
||||
use rustc_hir as hir;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use rustc_middle::mir::{self, Field};
|
||||
use rustc_middle::thir::{FieldPat, Pat, PatKind};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::traits::predicate_for_trait_def;
|
||||
|
@ -15,6 +13,10 @@ use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation};
|
|||
use std::cell::Cell;
|
||||
|
||||
use super::PatCtxt;
|
||||
use crate::errors::{
|
||||
FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch,
|
||||
PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
|
||||
};
|
||||
|
||||
impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
/// Converts an evaluated constant to a pattern (if possible).
|
||||
|
@ -105,47 +107,6 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn adt_derive_msg(&self, adt_def: AdtDef<'tcx>) -> String {
|
||||
let path = self.tcx().def_path_str(adt_def.did());
|
||||
format!(
|
||||
"to use a constant of type `{}` in a pattern, \
|
||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||
path, path,
|
||||
)
|
||||
}
|
||||
|
||||
fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option<String> {
|
||||
traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| {
|
||||
with_no_trimmed_paths!(match non_sm_ty.kind() {
|
||||
ty::Adt(adt, _) => self.adt_derive_msg(*adt),
|
||||
ty::Dynamic(..) => {
|
||||
"trait objects cannot be used in patterns".to_string()
|
||||
}
|
||||
ty::Alias(ty::Opaque, ..) => {
|
||||
"opaque types cannot be used in patterns".to_string()
|
||||
}
|
||||
ty::Closure(..) => {
|
||||
"closures cannot be used in patterns".to_string()
|
||||
}
|
||||
ty::Generator(..) | ty::GeneratorWitness(..) => {
|
||||
"generators cannot be used in patterns".to_string()
|
||||
}
|
||||
ty::Float(..) => {
|
||||
"floating-point numbers cannot be used in patterns".to_string()
|
||||
}
|
||||
ty::FnPtr(..) => {
|
||||
"function pointers cannot be used in patterns".to_string()
|
||||
}
|
||||
ty::RawPtr(..) => {
|
||||
"raw pointers cannot be used in patterns".to_string()
|
||||
}
|
||||
_ => {
|
||||
bug!("use of a value of `{non_sm_ty}` inside a pattern")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
|
||||
ty.is_structural_eq_shallow(self.infcx.tcx)
|
||||
}
|
||||
|
@ -176,7 +137,8 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
// If we were able to successfully convert the const to some pat,
|
||||
// double-check that all types in the const implement `Structural`.
|
||||
|
||||
let structural = self.search_for_structural_match_violation(cv.ty());
|
||||
let structural =
|
||||
traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty());
|
||||
debug!(
|
||||
"search_for_structural_match_violation cv.ty: {:?} returned: {:?}",
|
||||
cv.ty(),
|
||||
|
@ -194,17 +156,18 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
return inlined_const_as_pat;
|
||||
}
|
||||
|
||||
if let Some(msg) = structural {
|
||||
if let Some(non_sm_ty) = structural {
|
||||
if !self.type_may_have_partial_eq_impl(cv.ty()) {
|
||||
// span_fatal avoids ICE from resolution of non-existent method (rare case).
|
||||
self.tcx().sess.span_fatal(self.span, &msg);
|
||||
// fatal avoids ICE from resolution of non-existent method (rare case).
|
||||
self.tcx()
|
||||
.sess
|
||||
.emit_fatal(TypeNotStructural { span: self.span, non_sm_ty: non_sm_ty });
|
||||
} else if mir_structural_match_violation && !self.saw_const_match_lint.get() {
|
||||
self.tcx().struct_span_lint_hir(
|
||||
self.tcx().emit_spanned_lint(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
self.id,
|
||||
self.span,
|
||||
msg,
|
||||
|lint| lint,
|
||||
IndirectStructuralMatch { non_sm_ty },
|
||||
);
|
||||
} else {
|
||||
debug!(
|
||||
|
@ -278,12 +241,11 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
let kind = match cv.ty().kind() {
|
||||
ty::Float(_) => {
|
||||
if self.include_lint_checks {
|
||||
tcx.struct_span_lint_hir(
|
||||
tcx.emit_spanned_lint(
|
||||
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
|
||||
id,
|
||||
span,
|
||||
"floating-point types cannot be used in patterns",
|
||||
|lint| lint,
|
||||
FloatPattern,
|
||||
);
|
||||
}
|
||||
PatKind::Constant { value: cv }
|
||||
|
@ -291,29 +253,22 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
ty::Adt(adt_def, _) if adt_def.is_union() => {
|
||||
// Matching on union fields is unsafe, we can't hide it in constants
|
||||
self.saw_const_match_error.set(true);
|
||||
let msg = "cannot use unions in constant patterns";
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, msg);
|
||||
}
|
||||
let err = UnionPattern { span };
|
||||
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
|
||||
PatKind::Wild
|
||||
}
|
||||
ty::Adt(..)
|
||||
if !self.type_may_have_partial_eq_impl(cv.ty())
|
||||
// FIXME(#73448): Find a way to bring const qualification into parity with
|
||||
// `search_for_structural_match_violation` and then remove this condition.
|
||||
&& self.search_for_structural_match_violation(cv.ty()).is_some() =>
|
||||
{
|
||||
|
||||
// Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
|
||||
// could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
|
||||
let msg = self.search_for_structural_match_violation(cv.ty()).unwrap();
|
||||
&& let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty()) =>
|
||||
{
|
||||
self.saw_const_match_error.set(true);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(self.span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(self.span, &msg);
|
||||
}
|
||||
let err = TypeNotStructural { span, non_sm_ty };
|
||||
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
|
||||
PatKind::Wild
|
||||
}
|
||||
// If the type is not structurally comparable, just emit the constant directly,
|
||||
|
@ -331,19 +286,11 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
&& !self.saw_const_match_lint.get()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
tcx.struct_span_lint_hir(
|
||||
tcx.emit_spanned_lint(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
id,
|
||||
span,
|
||||
DelayDm(|| {
|
||||
format!(
|
||||
"to use a constant of type `{}` in a pattern, \
|
||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||
cv.ty(),
|
||||
cv.ty(),
|
||||
)
|
||||
}),
|
||||
|lint| lint,
|
||||
IndirectStructuralMatch { non_sm_ty: cv.ty() },
|
||||
);
|
||||
}
|
||||
// Since we are behind a reference, we can just bubble the error up so we get a
|
||||
|
@ -357,18 +304,9 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
adt_def,
|
||||
cv.ty()
|
||||
);
|
||||
let path = tcx.def_path_str(adt_def.did());
|
||||
let msg = format!(
|
||||
"to use a constant of type `{}` in a pattern, \
|
||||
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
|
||||
path, path,
|
||||
);
|
||||
self.saw_const_match_error.set(true);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg);
|
||||
}
|
||||
let err = TypeNotStructural { span, non_sm_ty: cv.ty() };
|
||||
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
|
||||
PatKind::Wild
|
||||
}
|
||||
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
|
||||
|
@ -401,12 +339,8 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
// These are not allowed and will error elsewhere anyway.
|
||||
ty::Dynamic(..) => {
|
||||
self.saw_const_match_error.set(true);
|
||||
let msg = format!("`{}` cannot be used in patterns", cv.ty());
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg);
|
||||
}
|
||||
let err = InvalidPattern { span, non_sm_ty: cv.ty() };
|
||||
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
|
||||
PatKind::Wild
|
||||
}
|
||||
// `&str` is represented as `ConstValue::Slice`, let's keep using this
|
||||
|
@ -471,32 +405,26 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
// this pattern to a `PartialEq::eq` comparison and `PartialEq::eq` takes a
|
||||
// reference. This makes the rest of the matching logic simpler as it doesn't have
|
||||
// to figure out how to get a reference again.
|
||||
ty::Adt(adt_def, _) if !self.type_marked_structural(*pointee_ty) => {
|
||||
ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => {
|
||||
if self.behind_reference.get() {
|
||||
if self.include_lint_checks
|
||||
&& !self.saw_const_match_error.get()
|
||||
&& !self.saw_const_match_lint.get()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
let msg = self.adt_derive_msg(adt_def);
|
||||
self.tcx().struct_span_lint_hir(
|
||||
tcx.emit_spanned_lint(
|
||||
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
|
||||
self.id,
|
||||
self.span,
|
||||
msg,
|
||||
|lint| lint,
|
||||
span,
|
||||
IndirectStructuralMatch { non_sm_ty: *pointee_ty },
|
||||
);
|
||||
}
|
||||
PatKind::Constant { value: cv }
|
||||
} else {
|
||||
if !self.saw_const_match_error.get() {
|
||||
self.saw_const_match_error.set(true);
|
||||
let msg = self.adt_derive_msg(adt_def);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg);
|
||||
}
|
||||
let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
|
||||
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
|
||||
}
|
||||
PatKind::Wild
|
||||
}
|
||||
|
@ -508,12 +436,10 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
if !pointee_ty.is_sized(tcx, param_env) {
|
||||
// `tcx.deref_mir_constant()` below will ICE with an unsized type
|
||||
// (except slices, which are handled in a separate arm above).
|
||||
let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg);
|
||||
}
|
||||
|
||||
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
|
||||
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
|
||||
|
||||
PatKind::Wild
|
||||
} else {
|
||||
let old = self.behind_reference.replace(true);
|
||||
|
@ -545,27 +471,19 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
&& !self.saw_const_match_lint.get()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
let msg = "function pointers and unsized pointers in patterns behave \
|
||||
unpredictably and should not be relied upon. \
|
||||
See https://github.com/rust-lang/rust/issues/70861 for details.";
|
||||
tcx.struct_span_lint_hir(
|
||||
tcx.emit_spanned_lint(
|
||||
lint::builtin::POINTER_STRUCTURAL_MATCH,
|
||||
id,
|
||||
span,
|
||||
msg,
|
||||
|lint| lint,
|
||||
PointerPattern
|
||||
);
|
||||
}
|
||||
PatKind::Constant { value: cv }
|
||||
}
|
||||
_ => {
|
||||
self.saw_const_match_error.set(true);
|
||||
let msg = format!("`{}` cannot be used in patterns", cv.ty());
|
||||
if self.include_lint_checks {
|
||||
tcx.sess.span_err(span, &msg);
|
||||
} else {
|
||||
tcx.sess.delay_span_bug(span, &msg);
|
||||
}
|
||||
let err = InvalidPattern { span, non_sm_ty: cv.ty() };
|
||||
tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
|
||||
PatKind::Wild
|
||||
}
|
||||
};
|
||||
|
@ -576,21 +494,17 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||
&& mir_structural_match_violation
|
||||
// FIXME(#73448): Find a way to bring const qualification into parity with
|
||||
// `search_for_structural_match_violation` and then remove this condition.
|
||||
&& self.search_for_structural_match_violation(cv.ty()).is_some()
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
|
||||
// Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
|
||||
// could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
|
||||
let msg = self.search_for_structural_match_violation(cv.ty()).unwrap().replace(
|
||||
"in a pattern,",
|
||||
"in a pattern, the constant's initializer must be trivial or",
|
||||
);
|
||||
tcx.struct_span_lint_hir(
|
||||
&& let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty())
|
||||
{
|
||||
self.saw_const_match_lint.set(true);
|
||||
tcx.emit_spanned_lint(
|
||||
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
|
||||
id,
|
||||
span,
|
||||
msg,
|
||||
|lint| lint,
|
||||
NontrivialStructuralMatch {non_sm_ty}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ use self::SliceKind::*;
|
|||
|
||||
use super::compare_const_vals;
|
||||
use super::usefulness::{MatchCheckCtxt, PatCtxt};
|
||||
use crate::errors::{Overlap, OverlappingRangeEndpoints};
|
||||
|
||||
/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
|
||||
fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
|
||||
|
@ -96,7 +97,7 @@ fn expand_or_pat<'p, 'tcx>(pat: &'p Pat<'tcx>) -> Vec<&'p Pat<'tcx>> {
|
|||
/// `IntRange` is never used to encode an empty range or a "range" that wraps
|
||||
/// around the (offset) space: i.e., `range.lo <= range.hi`.
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub(super) struct IntRange {
|
||||
pub(crate) struct IntRange {
|
||||
range: RangeInclusive<u128>,
|
||||
/// Keeps the bias used for encoding the range. It depends on the type of the range and
|
||||
/// possibly the pointer size of the current architecture. The algorithm ensures we never
|
||||
|
@ -284,32 +285,21 @@ impl IntRange {
|
|||
return;
|
||||
}
|
||||
|
||||
let overlaps: Vec<_> = pats
|
||||
let overlap: Vec<_> = pats
|
||||
.filter_map(|pat| Some((pat.ctor().as_int_range()?, pat.span())))
|
||||
.filter(|(range, _)| self.suspicious_intersection(range))
|
||||
.map(|(range, span)| (self.intersection(&range).unwrap(), span))
|
||||
.map(|(range, span)| Overlap {
|
||||
range: self.intersection(&range).unwrap().to_pat(pcx.cx.tcx, pcx.ty),
|
||||
span,
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !overlaps.is_empty() {
|
||||
pcx.cx.tcx.struct_span_lint_hir(
|
||||
if !overlap.is_empty() {
|
||||
pcx.cx.tcx.emit_spanned_lint(
|
||||
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
|
||||
hir_id,
|
||||
pcx.span,
|
||||
"multiple patterns overlap on their endpoints",
|
||||
|lint| {
|
||||
for (int_range, span) in overlaps {
|
||||
lint.span_label(
|
||||
span,
|
||||
&format!(
|
||||
"this range overlaps on `{}`...",
|
||||
int_range.to_pat(pcx.cx.tcx, pcx.ty)
|
||||
),
|
||||
);
|
||||
}
|
||||
lint.span_label(pcx.span, "... with this range");
|
||||
lint.note("you likely meant to write mutually exclusive ranges");
|
||||
lint
|
||||
},
|
||||
OverlappingRangeEndpoints { overlap, range: pcx.span },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
mod check_match;
|
||||
mod const_to_pat;
|
||||
mod deconstruct_pat;
|
||||
pub(crate) mod deconstruct_pat;
|
||||
mod usefulness;
|
||||
|
||||
pub(crate) use self::check_match::check_match;
|
||||
|
|
|
@ -291,9 +291,8 @@
|
|||
|
||||
use self::ArmType::*;
|
||||
use self::Usefulness::*;
|
||||
|
||||
use super::check_match::{joined_uncovered_patterns, pattern_not_covered_label};
|
||||
use super::deconstruct_pat::{Constructor, DeconstructedPat, Fields, SplitWildcard};
|
||||
use crate::errors::{NonExhaustiveOmittedPattern, Uncovered};
|
||||
|
||||
use rustc_data_structures::captures::Captures;
|
||||
|
||||
|
@ -743,31 +742,6 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
|
||||
/// is not exhaustive enough.
|
||||
///
|
||||
/// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
|
||||
fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
|
||||
cx: &MatchCheckCtxt<'p, 'tcx>,
|
||||
scrut_ty: Ty<'tcx>,
|
||||
sp: Span,
|
||||
hir_id: HirId,
|
||||
witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
|
||||
) {
|
||||
cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, "some variants are not matched explicitly", |lint| {
|
||||
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
|
||||
lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
|
||||
lint.help(
|
||||
"ensure that all variants are matched explicitly by adding the suggested match arms",
|
||||
);
|
||||
lint.note(&format!(
|
||||
"the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
|
||||
scrut_ty,
|
||||
));
|
||||
lint
|
||||
});
|
||||
}
|
||||
|
||||
/// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>.
|
||||
/// The algorithm from the paper has been modified to correctly handle empty
|
||||
/// types. The changes are:
|
||||
|
@ -913,7 +887,19 @@ fn is_useful<'p, 'tcx>(
|
|||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
lint_non_exhaustive_omitted_patterns(pcx.cx, pcx.ty, pcx.span, hir_id, patterns);
|
||||
// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
|
||||
// is not exhaustive enough.
|
||||
//
|
||||
// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
|
||||
cx.tcx.emit_spanned_lint(
|
||||
NON_EXHAUSTIVE_OMITTED_PATTERNS,
|
||||
hir_id,
|
||||
pcx.span,
|
||||
NonExhaustiveOmittedPattern {
|
||||
scrut_ty: pcx.ty,
|
||||
uncovered: Uncovered::new(pcx.span, pcx.cx, patterns),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
ret.extend(usefulness);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-match-check.rs:25:15
|
||||
|
|
||||
LL | A = { let 0 = 0; 0 },
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-match-check.rs:31:24
|
||||
|
|
||||
LL | let x: [i32; { let 0 = 0; 0 }] = [];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-match-check.rs:4:22
|
||||
|
|
||||
LL | const X: i32 = { let 0 = 0; 0 };
|
||||
|
@ -12,7 +12,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
|||
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
|
||||
| ++ ~~~~~~~~~~~
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-match-check.rs:8:23
|
||||
|
|
||||
LL | static Y: i32 = { let 0 = 0; 0 };
|
||||
|
@ -26,7 +26,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
|||
LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 };
|
||||
| ++ ~~~~~~~~~~~
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-match-check.rs:13:26
|
||||
|
|
||||
LL | const X: i32 = { let 0 = 0; 0 };
|
||||
|
@ -40,7 +40,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
|
|||
LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
|
||||
| ++ ~~~~~~~~~~~
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-match-check.rs:19:26
|
||||
|
|
||||
LL | const X: i32 = { let 0 = 0; 0 };
|
||||
|
|
|
@ -9,8 +9,20 @@ use foo::d;
|
|||
const a: u8 = 2;
|
||||
|
||||
fn main() {
|
||||
let a = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
|
||||
let c = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
|
||||
let d = 4; //~ ERROR refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX
|
||||
let a = 4;
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
//~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
|
||||
//~| HELP introduce a variable instead
|
||||
let c = 4;
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
//~| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
|
||||
//~| HELP introduce a variable instead
|
||||
let d = 4;
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
//~| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
|
||||
//~| HELP introduce a variable instead
|
||||
fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-pattern-irrefutable.rs:12:9
|
||||
|
|
||||
LL | const a: u8 = 2;
|
||||
|
@ -7,13 +7,14 @@ LL | const a: u8 = 2;
|
|||
LL | let a = 4;
|
||||
| ^
|
||||
| |
|
||||
| interpreted as a constant pattern, not a new variable
|
||||
| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
|
||||
| help: introduce a variable instead: `a_var`
|
||||
|
|
||||
= note: the matched value is of type `u8`
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
--> $DIR/const-pattern-irrefutable.rs:13:9
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-pattern-irrefutable.rs:17:9
|
||||
|
|
||||
LL | pub const b: u8 = 2;
|
||||
| --------------- constant defined here
|
||||
|
@ -21,13 +22,14 @@ LL | pub const b: u8 = 2;
|
|||
LL | let c = 4;
|
||||
| ^
|
||||
| |
|
||||
| interpreted as a constant pattern, not a new variable
|
||||
| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
| missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
|
||||
| help: introduce a variable instead: `c_var`
|
||||
|
|
||||
= note: the matched value is of type `u8`
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
--> $DIR/const-pattern-irrefutable.rs:14:9
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-pattern-irrefutable.rs:22:9
|
||||
|
|
||||
LL | pub const d: u8 = 2;
|
||||
| --------------- constant defined here
|
||||
|
@ -35,7 +37,8 @@ LL | pub const d: u8 = 2;
|
|||
LL | let d = 4;
|
||||
| ^
|
||||
| |
|
||||
| interpreted as a constant pattern, not a new variable
|
||||
| patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered
|
||||
| missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
|
||||
| help: introduce a variable instead: `d_var`
|
||||
|
|
||||
= note: the matched value is of type `u8`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
|
||||
error[E0005]: refutable pattern in function argument
|
||||
--> $DIR/const_let_refutable.rs:3:16
|
||||
|
|
||||
LL | const fn slice(&[a, b]: &[i32]) -> i32 {
|
||||
|
|
|
@ -8,7 +8,8 @@ enum Helper<T, U> {
|
|||
|
||||
fn transmute<T, U>(t: T) -> U {
|
||||
let Helper::U(u) = Helper::T(t, []);
|
||||
//~^ ERROR refutable pattern in local binding: `Helper::T(_, _)` not covered
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| `Helper::T(_, _)` not covered
|
||||
u
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `Helper::T(_, _)` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/empty-never-array.rs:10:9
|
||||
|
|
||||
LL | let Helper::U(u) = Helper::T(t, []);
|
||||
|
@ -7,18 +7,14 @@ LL | let Helper::U(u) = Helper::T(t, []);
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Helper<T, U>` defined here
|
||||
--> $DIR/empty-never-array.rs:4:5
|
||||
--> $DIR/empty-never-array.rs:3:6
|
||||
|
|
||||
LL | enum Helper<T, U> {
|
||||
| ------
|
||||
| ^^^^^^
|
||||
LL | T(T, [!; 0]),
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
= note: the matched value is of type `Helper<T, U>`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() };
|
||||
| ++++++++++ ++++++++++++++++++++++
|
||||
help: alternatively, you might want to use let else to handle the variant that isn't matched
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Helper::U(u) = Helper::T(t, []) else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `None` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/E0005.rs:3:9
|
||||
|
|
||||
LL | let Some(y) = x;
|
||||
|
@ -6,17 +6,8 @@ LL | let Some(y) = x;
|
|||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Option<i32>` defined here
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: not covered
|
||||
= note: the matched value is of type `Option<i32>`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | let y = if let Some(y) = x { y } else { todo!() };
|
||||
| ++++++++++ ++++++++++++++++++++++
|
||||
help: alternatively, you might want to use let else to handle the variant that isn't matched
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Some(y) = x else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
error[E0005]: refutable pattern in `for` loop binding: `None` not covered
|
||||
error[E0005]: refutable pattern in `for` loop binding
|
||||
--> $DIR/E0297.rs:4:9
|
||||
|
|
||||
LL | for Some(x) in xs {}
|
||||
| ^^^^^^^ pattern `None` not covered
|
||||
|
|
||||
note: `Option<i32>` defined here
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: not covered
|
||||
= note: the matched value is of type `Option<i32>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/feature-gate-exhaustive-patterns.rs:8:9
|
||||
|
|
||||
LL | let Ok(_x) = foo();
|
||||
|
@ -6,17 +6,8 @@ LL | let Ok(_x) = foo();
|
|||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Result<u32, !>` defined here
|
||||
--> $SRC_DIR/core/src/result.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/result.rs:LL:COL
|
||||
|
|
||||
= note: not covered
|
||||
= note: the matched value is of type `Result<u32, !>`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | let _x = if let Ok(_x) = foo() { _x } else { todo!() };
|
||||
| +++++++++++ +++++++++++++++++++++++
|
||||
help: alternatively, you might want to use let else to handle the variant that isn't matched
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(_x) = foo() else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in `for` loop binding: `&i32::MIN..=0_i32` and `&2_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in `for` loop binding
|
||||
--> $DIR/for-loop-refutable-pattern-error-message.rs:2:9
|
||||
|
|
||||
LL | for &1 in [1].iter() {}
|
||||
|
|
|
@ -2,7 +2,8 @@ fn main() {
|
|||
let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
|
||||
|
||||
for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
|
||||
//~^ ERROR refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not
|
||||
//~^ ERROR refutable pattern in `for` loop binding
|
||||
//~| patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
|
||||
println!("y={}", y);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in `for` loop binding: `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
|
||||
error[E0005]: refutable pattern in `for` loop binding
|
||||
--> $DIR/issue-15381.rs:4:9
|
||||
|
|
||||
LL | for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `Either::B(_)` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/exhaustive_patterns.rs:20:9
|
||||
|
|
||||
LL | let Either::A(()) = foo();
|
||||
|
@ -7,13 +7,13 @@ LL | let Either::A(()) = foo();
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Either<(), !>` defined here
|
||||
--> $DIR/exhaustive_patterns.rs:12:5
|
||||
--> $DIR/exhaustive_patterns.rs:10:6
|
||||
|
|
||||
LL | enum Either<A, B> {
|
||||
| ------
|
||||
| ^^^^^^
|
||||
LL | A(A),
|
||||
LL | B(inner::Wrapper<B>),
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
= note: the matched value is of type `Either<(), !>`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:2:10
|
||||
|
|
||||
LL | let (0 | (1 | 2)) = 0;
|
||||
|
|
|
@ -6,5 +6,6 @@ enum Thing {
|
|||
|
||||
fn main() {
|
||||
let Thing::Foo(y) = Thing::Foo(1);
|
||||
//~^ ERROR refutable pattern in local binding: `Thing::Bar` and `Thing::Baz` not covered
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| `Thing::Bar` and `Thing::Baz` not covered
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `Thing::Bar` and `Thing::Baz` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/issue-31561.rs:8:9
|
||||
|
|
||||
LL | let Thing::Foo(y) = Thing::Foo(1);
|
||||
|
@ -7,21 +7,17 @@ LL | let Thing::Foo(y) = Thing::Foo(1);
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Thing` defined here
|
||||
--> $DIR/issue-31561.rs:3:5
|
||||
--> $DIR/issue-31561.rs:1:6
|
||||
|
|
||||
LL | enum Thing {
|
||||
| -----
|
||||
| ^^^^^
|
||||
LL | Foo(u8),
|
||||
LL | Bar,
|
||||
| ^^^ not covered
|
||||
| --- not covered
|
||||
LL | Baz
|
||||
| ^^^ not covered
|
||||
| --- not covered
|
||||
= note: the matched value is of type `Thing`
|
||||
help: you might want to use `if let` to ignore the variants that aren't matched
|
||||
|
|
||||
LL | let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() };
|
||||
| ++++++++++ ++++++++++++++++++++++
|
||||
help: alternatively, you might want to use let else to handle the variants that aren't matched
|
||||
help: you might want to use `let else` to handle the variants that aren't matched
|
||||
|
|
||||
LL | let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
@ -15,9 +15,6 @@ enum E {
|
|||
//~^ NOTE `E` defined here
|
||||
//~| NOTE `E` defined here
|
||||
//~| NOTE `E` defined here
|
||||
//~| NOTE `E` defined here
|
||||
//~| NOTE `E` defined here
|
||||
//~| NOTE `E` defined here
|
||||
//~| NOTE not covered
|
||||
//~| NOTE not covered
|
||||
//~| NOTE not covered
|
||||
|
@ -41,37 +38,41 @@ fn by_val(e: E) {
|
|||
E::A => {}
|
||||
}
|
||||
|
||||
let E::A = e; //~ ERROR refutable pattern in local binding: `E::B` and `E::C` not covered
|
||||
//~^ NOTE patterns `E::B` and `E::C` not covered
|
||||
let E::A = e;
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| patterns `E::B` and `E::C` not covered
|
||||
//~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
|
||||
//~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
//~| NOTE the matched value is of type `E`
|
||||
}
|
||||
|
||||
fn by_ref_once(e: &E) {
|
||||
match e { //~ ERROR non-exhaustive patterns: `&E::B` and `&E::C` not covered
|
||||
//~^ NOTE patterns `&E::B` and `&E::C` not covered
|
||||
match e {
|
||||
//~^ ERROR non-exhaustive patterns
|
||||
//~| patterns `&E::B` and `&E::C` not covered
|
||||
//~| NOTE the matched value is of type `&E`
|
||||
E::A => {}
|
||||
}
|
||||
|
||||
let E::A = e; //~ ERROR refutable pattern in local binding: `&E::B` and `&E::C` not covered
|
||||
//~^ NOTE patterns `&E::B` and `&E::C` not covered
|
||||
let E::A = e;
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| patterns `&E::B` and `&E::C` not covered
|
||||
//~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
|
||||
//~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
//~| NOTE the matched value is of type `&E`
|
||||
}
|
||||
|
||||
fn by_ref_thrice(e: & &mut &E) {
|
||||
match e { //~ ERROR non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered
|
||||
//~^ NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered
|
||||
match e {
|
||||
//~^ ERROR non-exhaustive patterns
|
||||
//~| patterns `&&mut &E::B` and `&&mut &E::C` not covered
|
||||
//~| NOTE the matched value is of type `&&mut &E`
|
||||
E::A => {}
|
||||
}
|
||||
|
||||
let E::A = e;
|
||||
//~^ ERROR refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered
|
||||
//~| NOTE patterns `&&mut &E::B` and `&&mut &E::C` not covered
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| patterns `&&mut &E::B` and `&&mut &E::C` not covered
|
||||
//~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
|
||||
//~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
//~| NOTE the matched value is of type `&&mut &E`
|
||||
|
@ -83,20 +84,21 @@ enum Opt {
|
|||
Some(u8),
|
||||
None,
|
||||
//~^ NOTE `Opt` defined here
|
||||
//~| NOTE `Opt` defined here
|
||||
//~| NOTE not covered
|
||||
//~| NOTE not covered
|
||||
}
|
||||
|
||||
fn ref_pat(e: Opt) {
|
||||
match e {//~ ERROR non-exhaustive patterns: `Opt::None` not covered
|
||||
//~^ NOTE pattern `Opt::None` not covered
|
||||
match e {
|
||||
//~^ ERROR non-exhaustive patterns
|
||||
//~| pattern `Opt::None` not covered
|
||||
//~| NOTE the matched value is of type `Opt`
|
||||
Opt::Some(ref _x) => {}
|
||||
}
|
||||
|
||||
let Opt::Some(ref _x) = e; //~ ERROR refutable pattern in local binding: `Opt::None` not covered
|
||||
//~^ NOTE the matched value is of type `Opt`
|
||||
let Opt::Some(ref _x) = e;
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| NOTE the matched value is of type `Opt`
|
||||
//~| NOTE pattern `Opt::None` not covered
|
||||
//~| NOTE `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with
|
||||
//~| NOTE for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0004]: non-exhaustive patterns: `E::B` and `E::C` not covered
|
||||
--> $DIR/non-exhaustive-defined-here.rs:38:11
|
||||
--> $DIR/non-exhaustive-defined-here.rs:35:11
|
||||
|
|
||||
LL | match e1 {
|
||||
| ^^ patterns `E::B` and `E::C` not covered
|
||||
|
@ -22,8 +22,8 @@ LL ~ E::A => {}
|
|||
LL + E::B | E::C => todo!()
|
||||
|
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `E::B` and `E::C` not covered
|
||||
--> $DIR/non-exhaustive-defined-here.rs:44:9
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/non-exhaustive-defined-here.rs:41:9
|
||||
|
|
||||
LL | let E::A = e;
|
||||
| ^^^^ patterns `E::B` and `E::C` not covered
|
||||
|
@ -31,16 +31,16 @@ LL | let E::A = e;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `E` defined here
|
||||
--> $DIR/non-exhaustive-defined-here.rs:14:5
|
||||
--> $DIR/non-exhaustive-defined-here.rs:6:6
|
||||
|
|
||||
LL | enum E {
|
||||
| -
|
||||
| ^
|
||||
...
|
||||
LL | B,
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
...
|
||||
LL | C
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
= note: the matched value is of type `E`
|
||||
help: you might want to use `if let` to ignore the variants that aren't matched
|
||||
|
|
||||
|
@ -48,7 +48,7 @@ LL | if let E::A = e { todo!() }
|
|||
| ++ ~~~~~~~~~~~
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered
|
||||
--> $DIR/non-exhaustive-defined-here.rs:52:11
|
||||
--> $DIR/non-exhaustive-defined-here.rs:50:11
|
||||
|
|
||||
LL | match e {
|
||||
| ^ patterns `&E::B` and `&E::C` not covered
|
||||
|
@ -71,8 +71,8 @@ LL ~ E::A => {}
|
|||
LL + &E::B | &E::C => todo!()
|
||||
|
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `&E::B` and `&E::C` not covered
|
||||
--> $DIR/non-exhaustive-defined-here.rs:58:9
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/non-exhaustive-defined-here.rs:57:9
|
||||
|
|
||||
LL | let E::A = e;
|
||||
| ^^^^ patterns `&E::B` and `&E::C` not covered
|
||||
|
@ -80,16 +80,16 @@ LL | let E::A = e;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `E` defined here
|
||||
--> $DIR/non-exhaustive-defined-here.rs:14:5
|
||||
--> $DIR/non-exhaustive-defined-here.rs:6:6
|
||||
|
|
||||
LL | enum E {
|
||||
| -
|
||||
| ^
|
||||
...
|
||||
LL | B,
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
...
|
||||
LL | C
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
= note: the matched value is of type `&E`
|
||||
help: you might want to use `if let` to ignore the variants that aren't matched
|
||||
|
|
||||
|
@ -120,8 +120,8 @@ LL ~ E::A => {}
|
|||
LL + &&mut &E::B | &&mut &E::C => todo!()
|
||||
|
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `&&mut &E::B` and `&&mut &E::C` not covered
|
||||
--> $DIR/non-exhaustive-defined-here.rs:72:9
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/non-exhaustive-defined-here.rs:73:9
|
||||
|
|
||||
LL | let E::A = e;
|
||||
| ^^^^ patterns `&&mut &E::B` and `&&mut &E::C` not covered
|
||||
|
@ -129,16 +129,16 @@ LL | let E::A = e;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `E` defined here
|
||||
--> $DIR/non-exhaustive-defined-here.rs:14:5
|
||||
--> $DIR/non-exhaustive-defined-here.rs:6:6
|
||||
|
|
||||
LL | enum E {
|
||||
| -
|
||||
| ^
|
||||
...
|
||||
LL | B,
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
...
|
||||
LL | C
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
= note: the matched value is of type `&&mut &E`
|
||||
help: you might want to use `if let` to ignore the variants that aren't matched
|
||||
|
|
||||
|
@ -152,7 +152,7 @@ LL | match e {
|
|||
| ^ pattern `Opt::None` not covered
|
||||
|
|
||||
note: `Opt` defined here
|
||||
--> $DIR/non-exhaustive-defined-here.rs:84:5
|
||||
--> $DIR/non-exhaustive-defined-here.rs:85:5
|
||||
|
|
||||
LL | enum Opt {
|
||||
| ---
|
||||
|
@ -166,8 +166,8 @@ LL ~ Opt::Some(ref _x) => {}
|
|||
LL + Opt::None => todo!()
|
||||
|
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `Opt::None` not covered
|
||||
--> $DIR/non-exhaustive-defined-here.rs:98:9
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/non-exhaustive-defined-here.rs:99:9
|
||||
|
|
||||
LL | let Opt::Some(ref _x) = e;
|
||||
| ^^^^^^^^^^^^^^^^^ pattern `Opt::None` not covered
|
||||
|
@ -175,19 +175,15 @@ LL | let Opt::Some(ref _x) = e;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Opt` defined here
|
||||
--> $DIR/non-exhaustive-defined-here.rs:84:5
|
||||
--> $DIR/non-exhaustive-defined-here.rs:81:6
|
||||
|
|
||||
LL | enum Opt {
|
||||
| ---
|
||||
| ^^^
|
||||
...
|
||||
LL | None,
|
||||
| ^^^^ not covered
|
||||
| ---- not covered
|
||||
= note: the matched value is of type `Opt`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() };
|
||||
| +++++++++++ +++++++++++++++++++++++
|
||||
help: alternatively, you might want to use let else to handle the variant that isn't matched
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Opt::Some(ref _x) = e else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
|
||||
//~^ ERROR refutable pattern in function argument: `(_, _)` not covered
|
||||
//~^ ERROR refutable pattern in function argument
|
||||
//~| `(_, _)` not covered
|
||||
|
||||
fn main() {
|
||||
let (1, (Some(1), 2..=3)) = (1, (None, 2));
|
||||
//~^ ERROR refutable pattern in local binding: `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in function argument: `(_, _)` not covered
|
||||
error[E0005]: refutable pattern in function argument
|
||||
--> $DIR/refutable-pattern-errors.rs:1:9
|
||||
|
|
||||
LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
|
||||
|
@ -6,8 +6,8 @@ LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
|
|||
|
|
||||
= note: the matched value is of type `(isize, (Option<isize>, isize))`
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
|
||||
--> $DIR/refutable-pattern-errors.rs:5:9
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/refutable-pattern-errors.rs:6:9
|
||||
|
|
||||
LL | let (1, (Some(1), 2..=3)) = (1, (None, 2));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0_i32, _)` and `(2_i32..=i32::MAX, _)` not covered
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
fn main() {
|
||||
let f = |3: isize| println!("hello");
|
||||
//~^ ERROR refutable pattern in function argument: `_` not covered
|
||||
//~^ ERROR refutable pattern in function argument
|
||||
//~| `_` not covered
|
||||
f(4);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in function argument: `_` not covered
|
||||
error[E0005]: refutable pattern in function argument
|
||||
--> $DIR/refutable-pattern-in-fn-arg.rs:2:14
|
||||
|
|
||||
LL | let f = |3: isize| println!("hello");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/recursive-types-are-not-uninhabited.rs:6:9
|
||||
|
|
||||
LL | let Ok(x) = res;
|
||||
|
@ -6,17 +6,8 @@ LL | let Ok(x) = res;
|
|||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Result<u32, &R<'_>>` defined here
|
||||
--> $SRC_DIR/core/src/result.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/result.rs:LL:COL
|
||||
|
|
||||
= note: not covered
|
||||
= note: the matched value is of type `Result<u32, &R<'_>>`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | let x = if let Ok(x) = res { x } else { todo!() };
|
||||
| ++++++++++ ++++++++++++++++++++++
|
||||
help: alternatively, you might want to use let else to handle the variant that isn't matched
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(x) = res else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
fn main() {
|
||||
let A = 3;
|
||||
//~^ ERROR refutable pattern in local binding: `i32::MIN..=1_i32` and
|
||||
//~| interpreted as a constant pattern, not a new variable
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
|
||||
//~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
|
||||
//~| HELP introduce a variable instead
|
||||
//~| SUGGESTION a_var
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
error[E0005]: refutable pattern in local binding: `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9
|
||||
|
|
||||
LL | let A = 3;
|
||||
| ^
|
||||
| |
|
||||
| interpreted as a constant pattern, not a new variable
|
||||
| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
|
||||
| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
|
||||
| help: introduce a variable instead: `a_var`
|
||||
...
|
||||
LL | const A: i32 = 2;
|
||||
|
|
|
@ -24,5 +24,7 @@ enum Foo {
|
|||
|
||||
fn main() {
|
||||
let x: Foo = Foo::D(123, 456);
|
||||
let Foo::D(_y, _z) = x; //~ ERROR refutable pattern in local binding: `Foo::A(_)` not covered
|
||||
let Foo::D(_y, _z) = x;
|
||||
//~^ ERROR refutable pattern in local binding
|
||||
//~| `Foo::A(_)` not covered
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0005]: refutable pattern in local binding: `Foo::A(_)` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/uninhabited-irrefutable.rs:27:9
|
||||
|
|
||||
LL | let Foo::D(_y, _z) = x;
|
||||
|
@ -7,18 +7,14 @@ LL | let Foo::D(_y, _z) = x;
|
|||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Foo` defined here
|
||||
--> $DIR/uninhabited-irrefutable.rs:19:5
|
||||
--> $DIR/uninhabited-irrefutable.rs:18:6
|
||||
|
|
||||
LL | enum Foo {
|
||||
| ---
|
||||
| ^^^
|
||||
LL | A(foo::SecretlyEmpty),
|
||||
| ^ not covered
|
||||
| - not covered
|
||||
= note: the matched value is of type `Foo`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() };
|
||||
| +++++++++++++++++ +++++++++++++++++++++++++++++
|
||||
help: alternatively, you might want to use let else to handle the variant that isn't matched
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Foo::D(_y, _z) = x else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
|
@ -95,7 +95,7 @@ LL ~ Ok(x) => x,
|
|||
LL ~ Err(_) => todo!(),
|
||||
|
|
||||
|
||||
error[E0005]: refutable pattern in local binding: `Err(_)` not covered
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> $DIR/uninhabited-matches-feature-gated.rs:37:9
|
||||
|
|
||||
LL | let Ok(x) = x;
|
||||
|
@ -103,17 +103,8 @@ LL | let Ok(x) = x;
|
|||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
|
||||
note: `Result<u32, Void>` defined here
|
||||
--> $SRC_DIR/core/src/result.rs:LL:COL
|
||||
::: $SRC_DIR/core/src/result.rs:LL:COL
|
||||
|
|
||||
= note: not covered
|
||||
= note: the matched value is of type `Result<u32, Void>`
|
||||
help: you might want to use `if let` to ignore the variant that isn't matched
|
||||
|
|
||||
LL | let x = if let Ok(x) = x { x } else { todo!() };
|
||||
| ++++++++++ ++++++++++++++++++++++
|
||||
help: alternatively, you might want to use let else to handle the variant that isn't matched
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
LL | let Ok(x) = x else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue