Move witnesses inside push_wild_constructor
This commit is contained in:
parent
bfc0807b28
commit
4aa929cf8b
1 changed files with 41 additions and 49 deletions
|
@ -351,15 +351,38 @@ impl<'tcx> Witness<'tcx> {
|
||||||
ty: Ty<'tcx>)
|
ty: Ty<'tcx>)
|
||||||
-> Self
|
-> Self
|
||||||
{
|
{
|
||||||
let sub_pattern_tys = constructor_sub_pattern_tys(cx, ctor, ty);
|
// If we've been trying to exhaustively match over the domain of values for a type,
|
||||||
self.0.extend(sub_pattern_tys.into_iter().map(|ty| {
|
// then we can construct witnesses directly corresponding to the missing ranges of values,
|
||||||
Pattern {
|
// giving far more precise diagnostics.
|
||||||
ty,
|
// `ConstantValue` and `ConstantRange` only occur in practice when doing exhaustive value
|
||||||
span: DUMMY_SP,
|
// matching (exhaustive_integer_patterns).
|
||||||
kind: box PatternKind::Wild,
|
match ctor {
|
||||||
|
ConstantValue(value) => {
|
||||||
|
Witness(vec![Pattern {
|
||||||
|
ty,
|
||||||
|
span: DUMMY_SP,
|
||||||
|
kind: box PatternKind::Constant { value },
|
||||||
|
}])
|
||||||
}
|
}
|
||||||
}));
|
ConstantRange(lo, hi, end) => {
|
||||||
self.apply_constructor(cx, ctor, ty)
|
Witness(vec![Pattern {
|
||||||
|
ty,
|
||||||
|
span: DUMMY_SP,
|
||||||
|
kind: box PatternKind::Range { lo, hi, end: *end },
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let sub_pattern_tys = constructor_sub_pattern_tys(cx, ctor, ty);
|
||||||
|
self.0.extend(sub_pattern_tys.into_iter().map(|ty| {
|
||||||
|
Pattern {
|
||||||
|
ty,
|
||||||
|
span: DUMMY_SP,
|
||||||
|
kind: box PatternKind::Wild,
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
self.apply_constructor(cx, ctor, ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -976,7 +999,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||||
// `used_ctors` is empty.
|
// `used_ctors` is empty.
|
||||||
let new_witnesses = if is_non_exhaustive || used_ctors.is_empty() {
|
let new_witnesses = if is_non_exhaustive || used_ctors.is_empty() {
|
||||||
// All constructors are unused. Add wild patterns
|
// All constructors are unused. Add wild patterns
|
||||||
// rather than each individual constructor
|
// rather than each individual constructor.
|
||||||
pats.into_iter().map(|mut witness| {
|
pats.into_iter().map(|mut witness| {
|
||||||
witness.0.push(Pattern {
|
witness.0.push(Pattern {
|
||||||
ty: pcx.ty,
|
ty: pcx.ty,
|
||||||
|
@ -986,46 +1009,15 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
|
||||||
witness
|
witness
|
||||||
}).collect()
|
}).collect()
|
||||||
} else {
|
} else {
|
||||||
if consider_value_constructors {
|
pats.into_iter().flat_map(|witness| {
|
||||||
// If we've been trying to exhaustively match
|
missing_ctors.iter().map(move |ctor| {
|
||||||
// over the domain of values for a type,
|
// Extends the witness with a "wild" version of this
|
||||||
// then we can provide better diagnostics
|
// constructor, that matches everything that can be built with
|
||||||
// regarding which values were missing.
|
// it. For example, if `ctor` is a `Constructor::Variant` for
|
||||||
missing_ctors.into_iter().map(|ctor| {
|
// `Option::Some`, this pushes the witness for `Some(_)`.
|
||||||
match ctor {
|
witness.clone().push_wild_constructor(cx, ctor, pcx.ty)
|
||||||
// A constant range of length 1 is simply
|
})
|
||||||
// a constant value.
|
}).collect()
|
||||||
ConstantValue(value) => {
|
|
||||||
Witness(vec![Pattern {
|
|
||||||
ty: pcx.ty,
|
|
||||||
span: DUMMY_SP,
|
|
||||||
kind: box PatternKind::Constant { value },
|
|
||||||
}])
|
|
||||||
}
|
|
||||||
// We always report missing intervals
|
|
||||||
// in terms of inclusive ranges.
|
|
||||||
ConstantRange(lo, hi, end) => {
|
|
||||||
Witness(vec![Pattern {
|
|
||||||
ty: pcx.ty,
|
|
||||||
span: DUMMY_SP,
|
|
||||||
kind: box PatternKind::Range { lo, hi, end },
|
|
||||||
}])
|
|
||||||
},
|
|
||||||
_ => bug!("`ranges_subtract_pattern` should only produce \
|
|
||||||
`ConstantRange`s"),
|
|
||||||
}
|
|
||||||
}).collect()
|
|
||||||
} else {
|
|
||||||
pats.into_iter().flat_map(|witness| {
|
|
||||||
missing_ctors.iter().map(move |ctor| {
|
|
||||||
// Extends the witness with a "wild" version of this
|
|
||||||
// constructor, that matches everything that can be built with
|
|
||||||
// it. For example, if `ctor` is a `Constructor::Variant` for
|
|
||||||
// `Option::Some`, this pushes the witness for `Some(_)`.
|
|
||||||
witness.clone().push_wild_constructor(cx, ctor, pcx.ty)
|
|
||||||
})
|
|
||||||
}).collect()
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
UsefulWithWitness(new_witnesses)
|
UsefulWithWitness(new_witnesses)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue