@@ -187,48 +187,62 @@ bool expr_match(pass_opt_t* opt, ast_t* ast)
187187 type = control_type_add_branch (opt , type , cases );
188188 }
189189
190- // analyze exhaustiveness
191- ast_t * exhaustive_at = is_match_exhaustive (opt , expr_type , cases );
192-
193- if (exhaustive_at == NULL )
190+ // If the method definition containing the match site had its body inherited
191+ // from a trait, we don't want to check exhaustiveness here -
192+ // it should only be checked in the context of the original trait.
193+ bool skip_exhaustive = false;
194+ ast_t * body_donor = (ast_t * )ast_data (opt -> check .frame -> method );
195+ if ((body_donor != NULL ) && (ast_id (body_donor ) == TK_TRAIT )
196+ && (ast_id (opt -> check .frame -> type ) != TK_TRAIT ))
194197 {
195- // match might not be exhaustive
196- if ((ast_id (else_clause ) == TK_NONE ))
197- {
198- // If we have no else clause, and the match is not found to be exhaustive,
199- // we must generate an implicit else clause that returns None as the value.
200- ast_scope (else_clause );
201- ast_setid (else_clause , TK_SEQ );
202-
203- BUILD (ref , else_clause ,
204- NODE (TK_TYPEREF ,
205- NONE
206- ID ("None" )
207- NONE ));
208- ast_add (else_clause , ref );
209-
210- if (!expr_typeref (opt , & ref ) || !expr_seq (opt , else_clause ))
211- return false;
212- }
198+ skip_exhaustive = true;
213199 }
214- else
200+
201+ if (!skip_exhaustive )
215202 {
216- // match is exhaustive
217- if (ast_sibling (exhaustive_at ) != NULL )
203+ // analyze exhaustiveness
204+ ast_t * exhaustive_at = is_match_exhaustive (opt , expr_type , cases );
205+
206+ if (exhaustive_at == NULL )
218207 {
219- // we have unreachable cases
220- ast_error (opt -> check .errors , ast , "match contains unreachable cases" );
221- ast_error_continue (opt -> check .errors , ast_sibling (exhaustive_at ),
222- "first unreachable case expression" );
223- return false;
208+ // match might not be exhaustive
209+ if ((ast_id (else_clause ) == TK_NONE ))
210+ {
211+ // If we have no else clause, and the match is not found to be exhaustive,
212+ // we must generate an implicit else clause that returns None as the value.
213+ ast_scope (else_clause );
214+ ast_setid (else_clause , TK_SEQ );
215+
216+ BUILD (ref , else_clause ,
217+ NODE (TK_TYPEREF ,
218+ NONE
219+ ID ("None" )
220+ NONE ));
221+ ast_add (else_clause , ref );
222+
223+ if (!expr_typeref (opt , & ref ) || !expr_seq (opt , else_clause ))
224+ return false;
225+ }
224226 }
225- else if (( ast_id ( else_clause ) != TK_NONE ))
227+ else
226228 {
227- ast_error (opt -> check .errors , ast ,
228- "match is exhaustive, the else clause is unreachable" );
229- ast_error_continue (opt -> check .errors , else_clause ,
230- "unreachable code" );
231- return false;
229+ // match is exhaustive
230+ if (ast_sibling (exhaustive_at ) != NULL )
231+ {
232+ // we have unreachable cases
233+ ast_error (opt -> check .errors , ast , "match contains unreachable cases" );
234+ ast_error_continue (opt -> check .errors , ast_sibling (exhaustive_at ),
235+ "first unreachable case expression" );
236+ return false;
237+ }
238+ else if ((ast_id (else_clause ) != TK_NONE ))
239+ {
240+ ast_error (opt -> check .errors , ast ,
241+ "match is exhaustive, the else clause is unreachable" );
242+ ast_error_continue (opt -> check .errors , else_clause ,
243+ "unreachable code" );
244+ return false;
245+ }
232246 }
233247 }
234248
@@ -504,81 +518,96 @@ bool expr_case(pass_opt_t* opt, ast_t* ast)
504518
505519 ast_settype (ast , pattern_type );
506520
521+ // If the method definition containing the match site had its body inherited
522+ // from a trait, we don't want to check it here -
523+ // it should only be checked in the context of the original trait.
524+ bool skip = false;
525+ ast_t * body_donor = (ast_t * )ast_data (opt -> check .frame -> method );
526+ if ((body_donor != NULL ) && (ast_id (body_donor ) == TK_TRAIT )
527+ && (ast_id (opt -> check .frame -> type ) != TK_TRAIT ))
528+ {
529+ skip = true;
530+ }
531+
507532 bool ok = true;
508- errorframe_t info = NULL ;
509533
510- switch ( is_matchtype_with_consumed_pattern ( match_type , pattern_type , & info , opt ) )
534+ if (! skip )
511535 {
512- case MATCHTYPE_ACCEPT :
513- break ;
536+ errorframe_t info = NULL ;
514537
515- case MATCHTYPE_REJECT :
538+ switch ( is_matchtype_with_consumed_pattern ( match_type , pattern_type , & info , opt ))
516539 {
517- errorframe_t frame = NULL ;
518- ast_error_frame (& frame , pattern , "this pattern can never match" );
519- ast_error_frame (& frame , match_type , "match type: %s" ,
520- ast_print_type (match_type ));
521- // TODO report unaliased type when body is consume !
522- ast_error_frame (& frame , pattern , "pattern type: %s" ,
523- ast_print_type (pattern_type ));
524- errorframe_append (& frame , & info );
525- errorframe_report (& frame , opt -> check .errors );
526-
527- ok = false;
528- break ;
529- }
540+ case MATCHTYPE_ACCEPT :
541+ break ;
530542
531- case MATCHTYPE_DENY_CAP :
532- {
533- errorframe_t frame = NULL ;
534- ast_error_frame (& frame , pattern ,
535- "this capture violates capabilities, because the match would "
536- "need to differentiate by capability at runtime instead of matching "
537- "on type alone" );
538- ast_error_frame (& frame , match_type , "the match type allows for more than "
539- "one possibility with the same type as pattern type, but different "
540- "capabilities. match type: %s" ,
541- ast_print_type (match_type ));
542- ast_error_frame (& frame , pattern , "pattern type: %s" ,
543- ast_print_type (pattern_type ));
544- errorframe_append (& frame , & info );
545- ast_error_frame (& frame , match_expr ,
546- "the match expression with the inadequate capability is here" );
547- errorframe_report (& frame , opt -> check .errors );
548-
549- ok = false;
550- break ;
551- }
543+ case MATCHTYPE_REJECT :
544+ {
545+ errorframe_t frame = NULL ;
546+ ast_error_frame (& frame , pattern , "this pattern can never match" );
547+ ast_error_frame (& frame , match_type , "match type: %s" ,
548+ ast_print_type (match_type ));
549+ // TODO report unaliased type when body is consume !
550+ ast_error_frame (& frame , pattern , "pattern type: %s" ,
551+ ast_print_type (pattern_type ));
552+ errorframe_append (& frame , & info );
553+ errorframe_report (& frame , opt -> check .errors );
554+
555+ ok = false;
556+ break ;
557+ }
552558
553- case MATCHTYPE_DENY_NODESC :
554- {
555- errorframe_t frame = NULL ;
556- ast_error_frame (& frame , pattern ,
557- "this capture cannot match, since the type %s "
558- "is a struct and lacks a type descriptor" ,
559- ast_print_type (pattern_type ));
560- ast_error_frame (& frame , match_type ,
561- "a struct cannot be part of a union type. match type: %s" ,
562- ast_print_type (match_type ));
563- ast_error_frame (& frame , pattern , "pattern type: %s" ,
564- ast_print_type (pattern_type ));
565- errorframe_append (& frame , & info );
566- errorframe_report (& frame , opt -> check .errors );
567- ok = false;
568- break ;
569- }
570- }
559+ case MATCHTYPE_DENY_CAP :
560+ {
561+ errorframe_t frame = NULL ;
562+ ast_error_frame (& frame , pattern ,
563+ "this capture violates capabilities, because the match would "
564+ "need to differentiate by capability at runtime instead of matching "
565+ "on type alone" );
566+ ast_error_frame (& frame , match_type , "the match type allows for more than "
567+ "one possibility with the same type as pattern type, but different "
568+ "capabilities. match type: %s" ,
569+ ast_print_type (match_type ));
570+ ast_error_frame (& frame , pattern , "pattern type: %s" ,
571+ ast_print_type (pattern_type ));
572+ errorframe_append (& frame , & info );
573+ ast_error_frame (& frame , match_expr ,
574+ "the match expression with the inadequate capability is here" );
575+ errorframe_report (& frame , opt -> check .errors );
576+
577+ ok = false;
578+ break ;
579+ }
571580
572- if (ast_id (guard ) != TK_NONE )
573- {
574- ast_t * guard_type = ast_type (guard );
581+ case MATCHTYPE_DENY_NODESC :
582+ {
583+ errorframe_t frame = NULL ;
584+ ast_error_frame (& frame , pattern ,
585+ "this capture cannot match, since the type %s "
586+ "is a struct and lacks a type descriptor" ,
587+ ast_print_type (pattern_type ));
588+ ast_error_frame (& frame , match_type ,
589+ "a struct cannot be part of a union type. match type: %s" ,
590+ ast_print_type (match_type ));
591+ ast_error_frame (& frame , pattern , "pattern type: %s" ,
592+ ast_print_type (pattern_type ));
593+ errorframe_append (& frame , & info );
594+ errorframe_report (& frame , opt -> check .errors );
595+ ok = false;
596+ break ;
597+ }
598+ }
575599
576- if (is_typecheck_error ( guard_type ) )
600+ if (ast_id ( guard ) != TK_NONE )
577601 {
578- ok = false;
579- } else if (!is_bool (guard_type )) {
580- ast_error (opt -> check .errors , guard ,
581- "guard must be a boolean expression" );
602+ ast_t * guard_type = ast_type (guard );
603+
604+ if (is_typecheck_error (guard_type ))
605+ {
606+ ok = false;
607+ } else if (!is_bool (guard_type )) {
608+ ast_error (opt -> check .errors , guard ,
609+ "guard must be a boolean expression" );
610+ }
582611 }
583612 }
584613 return ok ;
0 commit comments