1+ #![ allow( dead_code, unreachable_pub) ]
12use rustc_pattern_analysis:: constructor:: {
23 Constructor , ConstructorSet , IntRange , MaybeInfiniteInt , RangeEnd , VariantVisibility ,
34} ;
@@ -22,8 +23,10 @@ fn init_tracing() {
2223 . try_init ( ) ;
2324}
2425
26+ pub ( super ) const UNIT : Ty = Ty :: Tuple ( & [ ] ) ;
27+ pub ( super ) const NEVER : Ty = Ty :: Enum ( & [ ] ) ;
28+
2529/// A simple set of types.
26- #[ allow( dead_code) ]
2730#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
2831pub ( super ) enum Ty {
2932 /// Booleans
@@ -38,6 +41,8 @@ pub(super) enum Ty {
3841 BigStruct { arity : usize , ty : & ' static Ty } ,
3942 /// A enum with `arity` variants of type `ty`.
4043 BigEnum { arity : usize , ty : & ' static Ty } ,
44+ /// Like `Enum` but non-exhaustive.
45+ NonExhaustiveEnum ( & ' static [ Ty ] ) ,
4146}
4247
4348/// The important logic.
@@ -47,7 +52,7 @@ impl Ty {
4752 match ( ctor, * self ) {
4853 ( Struct , Ty :: Tuple ( tys) ) => tys. iter ( ) . copied ( ) . collect ( ) ,
4954 ( Struct , Ty :: BigStruct { arity, ty } ) => ( 0 ..arity) . map ( |_| * ty) . collect ( ) ,
50- ( Variant ( i) , Ty :: Enum ( tys) ) => vec ! [ tys[ * i] ] ,
55+ ( Variant ( i) , Ty :: Enum ( tys) | Ty :: NonExhaustiveEnum ( tys ) ) => vec ! [ tys[ * i] ] ,
5156 ( Variant ( _) , Ty :: BigEnum { ty, .. } ) => vec ! [ * ty] ,
5257 ( Bool ( ..) | IntRange ( ..) | NonExhaustive | Missing | Wildcard , _) => vec ! [ ] ,
5358 _ => panic ! ( "Unexpected ctor {ctor:?} for type {self:?}" ) ,
@@ -61,6 +66,7 @@ impl Ty {
6166 Ty :: Enum ( tys) => tys. iter ( ) . all ( |ty| ty. is_empty ( ) ) ,
6267 Ty :: BigStruct { arity, ty } => arity != 0 && ty. is_empty ( ) ,
6368 Ty :: BigEnum { arity, ty } => arity == 0 || ty. is_empty ( ) ,
69+ Ty :: NonExhaustiveEnum ( ..) => false ,
6470 }
6571 }
6672
@@ -90,6 +96,19 @@ impl Ty {
9096 . collect ( ) ,
9197 non_exhaustive : false ,
9298 } ,
99+ Ty :: NonExhaustiveEnum ( tys) => ConstructorSet :: Variants {
100+ variants : tys
101+ . iter ( )
102+ . map ( |ty| {
103+ if ty. is_empty ( ) {
104+ VariantVisibility :: Empty
105+ } else {
106+ VariantVisibility :: Visible
107+ }
108+ } )
109+ . collect ( ) ,
110+ non_exhaustive : true ,
111+ } ,
93112 Ty :: BigEnum { arity : 0 , .. } => ConstructorSet :: NoConstructors ,
94113 Ty :: BigEnum { arity, ty } => {
95114 let vis = if ty. is_empty ( ) {
@@ -113,7 +132,9 @@ impl Ty {
113132 match ( * self , ctor) {
114133 ( Ty :: Tuple ( ..) , _) => Ok ( ( ) ) ,
115134 ( Ty :: BigStruct { .. } , _) => write ! ( f, "BigStruct" ) ,
116- ( Ty :: Enum ( ..) , Constructor :: Variant ( i) ) => write ! ( f, "Enum::Variant{i}" ) ,
135+ ( Ty :: Enum ( ..) | Ty :: NonExhaustiveEnum ( ..) , Constructor :: Variant ( i) ) => {
136+ write ! ( f, "Enum::Variant{i}" )
137+ }
117138 ( Ty :: BigEnum { .. } , Constructor :: Variant ( i) ) => write ! ( f, "BigEnum::Variant{i}" ) ,
118139 _ => write ! ( f, "{:?}::{:?}" , self , ctor) ,
119140 }
@@ -126,10 +147,11 @@ pub(super) fn compute_match_usefulness<'p>(
126147 ty : Ty ,
127148 scrut_validity : PlaceValidity ,
128149 complexity_limit : usize ,
150+ exhaustive_witnesses : bool ,
129151) -> Result < UsefulnessReport < ' p , Cx > , ( ) > {
130152 init_tracing ( ) ;
131153 rustc_pattern_analysis:: usefulness:: compute_match_usefulness (
132- & Cx ,
154+ & Cx { exhaustive_witnesses } ,
133155 arms,
134156 ty,
135157 scrut_validity,
@@ -138,7 +160,9 @@ pub(super) fn compute_match_usefulness<'p>(
138160}
139161
140162#[ derive( Debug ) ]
141- pub ( super ) struct Cx ;
163+ pub ( super ) struct Cx {
164+ exhaustive_witnesses : bool ,
165+ }
142166
143167/// The context for pattern analysis. Forwards anything interesting to `Ty` methods.
144168impl PatCx for Cx {
@@ -153,6 +177,10 @@ impl PatCx for Cx {
153177 false
154178 }
155179
180+ fn exhaustive_witnesses ( & self ) -> bool {
181+ self . exhaustive_witnesses
182+ }
183+
156184 fn ctor_arity ( & self , ctor : & Constructor < Self > , ty : & Self :: Ty ) -> usize {
157185 ty. sub_tys ( ctor) . len ( )
158186 }
@@ -219,16 +247,18 @@ macro_rules! pats {
219247 // Entrypoint
220248 // Parse `type; ..`
221249 ( $ty: expr; $( $rest: tt) * ) => { {
222- #[ allow( unused_imports ) ]
250+ #[ allow( unused ) ]
223251 use rustc_pattern_analysis:: {
224252 constructor:: { Constructor , IntRange , MaybeInfiniteInt , RangeEnd } ,
225- pat:: DeconstructedPat ,
253+ pat:: { DeconstructedPat , IndexedPat } ,
226254 } ;
227255 let ty = $ty;
228256 // The heart of the macro is designed to push `IndexedPat`s into a `Vec`, so we work around
229257 // that.
258+ #[ allow( unused) ]
230259 let sub_tys = :: std:: iter:: repeat( & ty) ;
231- let mut vec = Vec :: new( ) ;
260+ #[ allow( unused) ]
261+ let mut vec: Vec <IndexedPat <_>> = Vec :: new( ) ;
232262 pats!( @ctor( vec: vec, sub_tys: sub_tys, idx: 0 ) $( $rest) * ) ;
233263 vec. into_iter( ) . map( |ipat| ipat. pat) . collect:: <Vec <_>>( )
234264 } } ;
@@ -263,6 +293,8 @@ macro_rules! pats {
263293 let ctor = Constructor :: Wildcard ;
264294 pats!( @pat( $( $args) * , ctor: ctor) $( $rest) * )
265295 } } ;
296+ // Nothing
297+ ( @ctor( $( $args: tt) * ) ) => { } ;
266298
267299 // Integers and int ranges
268300 ( @ctor( $( $args: tt) * ) $( $start: literal) ?..$end: literal $( $rest: tt) * ) => { {
0 commit comments