forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.rs
133 lines (110 loc) · 4.5 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Analysis of patterns, notably match exhaustiveness checking.
pub mod constructor;
#[cfg(feature = "rustc")]
pub mod errors;
#[cfg(feature = "rustc")]
pub(crate) mod lints;
pub mod pat;
#[cfg(feature = "rustc")]
pub mod rustc;
pub mod usefulness;
#[macro_use]
extern crate tracing;
#[cfg(feature = "rustc")]
#[macro_use]
extern crate rustc_middle;
#[cfg(feature = "rustc")]
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
use std::fmt;
use rustc_index::Idx;
#[cfg(feature = "rustc")]
use rustc_middle::ty::Ty;
use crate::constructor::{Constructor, ConstructorSet};
#[cfg(feature = "rustc")]
use crate::lints::{
lint_nonexhaustive_missing_variants, lint_overlapping_range_endpoints, PatternColumn,
};
use crate::pat::DeconstructedPat;
#[cfg(feature = "rustc")]
use crate::rustc::RustcMatchCheckCtxt;
#[cfg(feature = "rustc")]
use crate::usefulness::{compute_match_usefulness, ValidityConstraint};
// It's not possible to only enable the `typed_arena` dependency when the `rustc` feature is off, so
// we use another feature instead. The crate won't compile if one of these isn't enabled.
#[cfg(feature = "rustc")]
pub(crate) use rustc_arena::TypedArena;
#[cfg(feature = "stable")]
pub(crate) use typed_arena::Arena as TypedArena;
pub trait Captures<'a> {}
impl<'a, T: ?Sized> Captures<'a> for T {}
/// Context that provides type information about constructors.
///
/// Most of the crate is parameterized on a type that implements this trait.
pub trait TypeCx: Sized + fmt::Debug {
/// The type of a pattern.
type Ty: Copy + Clone + fmt::Debug; // FIXME: remove Copy
/// The index of an enum variant.
type VariantIdx: Clone + Idx;
/// A string literal
type StrLit: Clone + PartialEq + fmt::Debug;
/// Extra data to store in a match arm.
type ArmData: Copy + Clone + fmt::Debug;
/// Extra data to store in a pattern.
type PatData: Clone;
fn is_exhaustive_patterns_feature_on(&self) -> bool;
/// The number of fields for this constructor.
fn ctor_arity(&self, ctor: &Constructor<Self>, ty: Self::Ty) -> usize;
/// The types of the fields for this constructor. The result must have a length of
/// `ctor_arity()`.
fn ctor_sub_tys(&self, ctor: &Constructor<Self>, ty: Self::Ty) -> &[Self::Ty];
/// The set of all the constructors for `ty`.
///
/// This must follow the invariants of `ConstructorSet`
fn ctors_for_ty(&self, ty: Self::Ty) -> ConstructorSet<Self>;
/// Best-effort `Debug` implementation.
fn debug_pat(f: &mut fmt::Formatter<'_>, pat: &DeconstructedPat<'_, Self>) -> fmt::Result;
/// Raise a bug.
fn bug(&self, fmt: fmt::Arguments<'_>) -> !;
}
/// Context that provides information global to a match.
#[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub struct MatchCtxt<'a, 'p, Cx: TypeCx> {
/// The context for type information.
pub tycx: &'a Cx,
/// An arena to store the wildcards we produce during analysis.
pub wildcard_arena: &'p TypedArena<DeconstructedPat<'p, Cx>>,
}
/// The arm of a match expression.
#[derive(Debug)]
#[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Copy(bound = ""))]
pub struct MatchArm<'p, Cx: TypeCx> {
pub pat: &'p DeconstructedPat<'p, Cx>,
pub has_guard: bool,
pub arm_data: Cx::ArmData,
}
/// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are
/// useful, and runs some lints.
#[cfg(feature = "rustc")]
pub fn analyze_match<'p, 'tcx>(
tycx: &RustcMatchCheckCtxt<'p, 'tcx>,
arms: &[rustc::MatchArm<'p, 'tcx>],
scrut_ty: Ty<'tcx>,
) -> rustc::UsefulnessReport<'p, 'tcx> {
// Arena to store the extra wildcards we construct during analysis.
let wildcard_arena = tycx.pattern_arena;
let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee);
let cx = MatchCtxt { tycx, wildcard_arena };
let report = compute_match_usefulness(cx, arms, scrut_ty, scrut_validity);
let pat_column = PatternColumn::new(arms);
// Lint on ranges that overlap on their endpoints, which is likely a mistake.
lint_overlapping_range_endpoints(cx, &pat_column);
// Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
// `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
if tycx.refutable && report.non_exhaustiveness_witnesses.is_empty() {
lint_nonexhaustive_missing_variants(cx, arms, &pat_column, scrut_ty)
}
report
}