@@ -1320,6 +1320,10 @@ impl Lowerer {
13201320 // Pop the scope where the def lives.
13211321 self . symbols . pop_scope ( ) ;
13221322
1323+ if let Some ( return_ty) = & stmt. return_type {
1324+ self . check_that_def_returns_in_all_code_paths ( & body, return_ty. span ) ;
1325+ }
1326+
13231327 semantic:: StmtKind :: Def ( semantic:: DefStmt {
13241328 span : stmt. span ,
13251329 symbol_id,
@@ -1330,6 +1334,53 @@ impl Lowerer {
13301334 } )
13311335 }
13321336
1337+ fn check_that_def_returns_in_all_code_paths ( & mut self , body : & semantic:: Block , span : Span ) {
1338+ if !Self :: block_always_returns ( & body. stmts ) {
1339+ self . push_semantic_error ( SemanticErrorKind :: NonVoidDefShouldAlwaysReturn ( span) ) ;
1340+ }
1341+ }
1342+
1343+ fn block_always_returns < ' a > ( stmts : impl IntoIterator < Item = & ' a Box < semantic:: Stmt > > ) -> bool {
1344+ for stmt in stmts {
1345+ if Self :: stmt_always_returns ( stmt) {
1346+ return true ;
1347+ }
1348+ }
1349+ false
1350+ }
1351+
1352+ fn stmt_always_returns ( stmt : & semantic:: Stmt ) -> bool {
1353+ match & * stmt. kind {
1354+ semantic:: StmtKind :: Block ( block) => Self :: block_always_returns ( & block. stmts ) ,
1355+ semantic:: StmtKind :: Box ( stmt) => Self :: block_always_returns ( & stmt. body ) ,
1356+ semantic:: StmtKind :: If ( stmt) => {
1357+ if let Some ( else_body) = & stmt. else_body {
1358+ Self :: stmt_always_returns ( & stmt. if_body ) && Self :: stmt_always_returns ( else_body)
1359+ } else {
1360+ false
1361+ }
1362+ }
1363+ // We don't know if the user's switch is exhaustive.
1364+ // We take a best effort approach and check if all the branches always return.
1365+ semantic:: StmtKind :: Switch ( stmt) => {
1366+ let mut all_cases_return = true ;
1367+ for case in & stmt. cases {
1368+ all_cases_return &= Self :: block_always_returns ( & case. block . stmts ) ;
1369+ }
1370+ if let Some ( default_case) = & stmt. default {
1371+ all_cases_return &= Self :: block_always_returns ( & default_case. stmts ) ;
1372+ }
1373+ all_cases_return
1374+ }
1375+ // We don't know if the iterable of the loop is empty at compiletime.
1376+ // We take a best effort approach and check if the body always returns.
1377+ semantic:: StmtKind :: For ( stmt) => Self :: stmt_always_returns ( & stmt. body ) ,
1378+ semantic:: StmtKind :: WhileLoop ( stmt) => Self :: stmt_always_returns ( & stmt. body ) ,
1379+ semantic:: StmtKind :: Return ( ..) | semantic:: StmtKind :: End ( ..) => true ,
1380+ _ => false ,
1381+ }
1382+ }
1383+
13331384 fn lower_typed_parameter ( & mut self , typed_param : & syntax:: TypedParameter ) -> Symbol {
13341385 match typed_param {
13351386 syntax:: TypedParameter :: ArrayReference ( param) => {
@@ -2233,7 +2284,6 @@ impl Lowerer {
22332284 self . push_semantic_error (
22342285 SemanticErrorKind :: MissingTargetExpressionInReturnStmt ( stmt. span ) ,
22352286 ) ;
2236- return semantic:: StmtKind :: Err ;
22372287 }
22382288 }
22392289 ( Some ( expr) , Some ( ty) ) => {
0 commit comments