@@ -39,6 +39,9 @@ use crate::lower::context::LoweringContext;
3939type BuildNodeCallback < ' db , ' a > =
4040 & ' a dyn Fn ( & mut FlowControlGraphBuilder < ' db > , FilteredPatterns ) -> NodeId ;
4141
42+ /// A thin wrapper around [semantic::Pattern], where `None` represents the `_` pattern.
43+ pub type Pattern < ' a , ' db > = Option < & ' a semantic:: Pattern < ' db > > ;
44+
4245/// Given a list of patterns and the nodes to go to if the pattern matches,
4346/// returns a new graph node to handle the patterns.
4447///
@@ -50,17 +53,14 @@ pub fn create_node_for_patterns<'db>(
5053 ctx : & LoweringContext < ' db , ' _ > ,
5154 graph : & mut FlowControlGraphBuilder < ' db > ,
5255 input_var : FlowControlVar ,
53- patterns : & [ & semantic :: Pattern < ' db > ] ,
56+ patterns : & [ Pattern < ' _ , ' db > ] ,
5457 build_node_callback : BuildNodeCallback < ' db , ' _ > ,
5558 location : LocationId < ' db > ,
5659) -> NodeId {
5760 // If all the patterns are catch-all, we do not need to look into `input_var`.
5861 if patterns. iter ( ) . all ( |pattern| pattern_is_any ( pattern) ) {
5962 // Call the callback with all patterns accepted.
60- return build_node_callback (
61- graph,
62- FilteredPatterns :: all ( patterns. len ( ) )
63- ) ;
63+ return build_node_callback ( graph, FilteredPatterns :: all ( patterns. len ( ) ) ) ;
6464 }
6565
6666 let ( n_snapshots, long_ty) = peel_snapshots ( ctx. db , graph. var_ty ( input_var) ) ;
@@ -87,7 +87,7 @@ fn create_node_for_enum<'db>(
8787 input_var : FlowControlVar ,
8888 concrete_enum_id : ConcreteEnumId < ' db > ,
8989 n_snapshots : usize ,
90- patterns : & [ & semantic :: Pattern < ' db > ] ,
90+ patterns : & [ Pattern < ' _ , ' db > ] ,
9191 build_node_callback : BuildNodeCallback < ' db , ' _ > ,
9292 location : LocationId < ' db > ,
9393) -> NodeId {
@@ -100,18 +100,28 @@ fn create_node_for_enum<'db>(
100100 // Maps variant index to the list of the inner patterns.
101101 // For example, a pattern `A(B(x))` will add the (inner) pattern `B(x)` to the vector at the
102102 // index of the variant `A`.
103- let mut variant_to_inner_patterns: Vec < Vec < & semantic :: Pattern > > = vec ! [ vec![ ] ; concrete_variants. len( ) ] ;
103+ let mut variant_to_inner_patterns: Vec < Vec < Pattern > > = vec ! [ vec![ ] ; concrete_variants. len( ) ] ;
104104
105105 for ( idx, pattern) in patterns. iter ( ) . enumerate ( ) {
106106 match pattern {
107- semantic:: Pattern :: EnumVariant ( PatternEnumVariant { variant, inner_pattern, .. } ) => {
107+ Some ( semantic:: Pattern :: EnumVariant ( PatternEnumVariant {
108+ variant,
109+ inner_pattern,
110+ ..
111+ } ) ) => {
108112 variant_to_pattern_indices[ variant. idx ] . add ( idx) ;
109- // TODO(lior): Fix the unwrap below.
110- variant_to_inner_patterns[ variant. idx ] . push (
111- inner_pattern
112- . map ( |inner_pattern| & ctx. function_body . arenas . patterns [ inner_pattern] )
113- . unwrap ( ) ,
114- ) ;
113+ variant_to_inner_patterns[ variant. idx ]
114+ . push ( inner_pattern. map ( |inner_pattern| get_pattern ( ctx, inner_pattern) ) ) ;
115+ }
116+ Some ( semantic:: Pattern :: Otherwise ( ..) ) | None => {
117+ // Add `idx` to all the variants.
118+ for pattern_indices in variant_to_pattern_indices. iter_mut ( ) {
119+ pattern_indices. add ( idx) ;
120+ }
121+ // Add the `_` pattern (represented by `None`) to all the variants.
122+ for inner_patterns in variant_to_inner_patterns. iter_mut ( ) {
123+ inner_patterns. push ( None ) ;
124+ }
115125 }
116126 _ => todo ! ( "Pattern {:?} is not supported yet." , pattern) ,
117127 }
@@ -146,16 +156,26 @@ fn create_node_for_enum<'db>(
146156}
147157
148158/// Returns `true` if the pattern accepts any value (`_` or a variable name).
149- fn pattern_is_any ( pattern : & semantic :: Pattern ) -> bool {
159+ fn pattern_is_any ( pattern : & Pattern ) -> bool {
150160 match pattern {
151- semantic:: Pattern :: Otherwise ( ..)
152- | semantic:: Pattern :: Variable ( ..) => true ,
153- semantic:: Pattern :: Literal ( ..) |
154- semantic:: Pattern :: StringLiteral ( ..) |
155- semantic:: Pattern :: Struct ( ..) |
156- semantic:: Pattern :: Tuple ( ..) |
157- semantic:: Pattern :: FixedSizeArray ( ..) |
158- semantic:: Pattern :: EnumVariant ( ..) |
159- semantic:: Pattern :: Missing ( ..) => false ,
161+ Some ( semantic_pattern) => match semantic_pattern {
162+ semantic:: Pattern :: Otherwise ( ..) | semantic:: Pattern :: Variable ( ..) => true ,
163+ semantic:: Pattern :: Literal ( ..)
164+ | semantic:: Pattern :: StringLiteral ( ..)
165+ | semantic:: Pattern :: Struct ( ..)
166+ | semantic:: Pattern :: Tuple ( ..)
167+ | semantic:: Pattern :: FixedSizeArray ( ..)
168+ | semantic:: Pattern :: EnumVariant ( ..)
169+ | semantic:: Pattern :: Missing ( ..) => false ,
170+ } ,
171+ None => true ,
160172 }
161173}
174+
175+ /// Returns a reference to a [semantic::Pattern] from a [semantic::PatternId].
176+ pub fn get_pattern < ' db , ' a > (
177+ ctx : & ' a LoweringContext < ' db , ' _ > ,
178+ semantic_pattern : semantic:: PatternId ,
179+ ) -> & ' a semantic:: Pattern < ' db > {
180+ & ctx. function_body . arenas . patterns [ semantic_pattern]
181+ }
0 commit comments