@@ -4,14 +4,7 @@ use std::{
44} ;
55
66use crate :: {
7- ast:: ItemVisibility ,
8- hir_def:: {
9- expr:: { HirBlockExpression , HirExpression } ,
10- stmt:: HirStatement ,
11- traits:: ResolvedTraitBound ,
12- } ,
13- node_interner:: DefinitionId ,
14- StructField , StructType , TypeBindings ,
7+ ast:: ItemVisibility , hir_def:: traits:: ResolvedTraitBound , StructField , StructType , TypeBindings ,
158} ;
169use crate :: {
1710 ast:: {
@@ -479,12 +472,16 @@ impl<'context> Elaborator<'context> {
479472
480473 // Check that the body can return without calling the function.
481474 if let FunctionKind :: Normal | FunctionKind :: Recursive = kind {
482- self . check_for_unbounded_recursion (
483- id,
484- self . interner . definition_name ( func_meta. name . id ) . to_string ( ) ,
485- func_meta. name . location . span ,
486- hir_func. as_expr ( ) ,
487- ) ;
475+ self . run_lint ( |elaborator| {
476+ lints:: unbounded_recursion (
477+ elaborator. interner ,
478+ id,
479+ || elaborator. interner . definition_name ( func_meta. name . id ) ,
480+ func_meta. name . location . span ,
481+ hir_func. as_expr ( ) ,
482+ )
483+ . map ( Into :: into)
484+ } ) ;
488485 }
489486
490487 let meta = self
@@ -1709,79 +1706,4 @@ impl<'context> Elaborator<'context> {
17091706 _ => true ,
17101707 } )
17111708 }
1712-
1713- /// Check that a recursive function *can* return without endlessly calling itself.
1714- fn check_for_unbounded_recursion (
1715- & mut self ,
1716- func_id : FuncId ,
1717- func_name : String ,
1718- func_span : Span ,
1719- body_id : ExprId ,
1720- ) {
1721- if !self . can_return_without_recursing ( func_id, body_id) {
1722- self . push_err ( CompilationError :: ResolverError ( ResolverError :: UnconditionalRecursion {
1723- name : func_name,
1724- span : func_span,
1725- } ) ) ;
1726- }
1727- }
1728-
1729- /// Check if an expression will end up calling a specific function.
1730- fn can_return_without_recursing ( & self , func_id : FuncId , expr_id : ExprId ) -> bool {
1731- let check = |e| self . can_return_without_recursing ( func_id, e) ;
1732-
1733- let check_block = |block : HirBlockExpression | {
1734- block. statements . iter ( ) . all ( |stmt_id| match self . interner . statement ( stmt_id) {
1735- HirStatement :: Let ( s) => check ( s. expression ) ,
1736- HirStatement :: Assign ( s) => check ( s. expression ) ,
1737- HirStatement :: Expression ( e) => check ( e) ,
1738- HirStatement :: Semi ( e) => check ( e) ,
1739- // Rust doesn't seem to check the for loop body (it's bounds might mean it's never called).
1740- HirStatement :: For ( e) => check ( e. start_range ) && check ( e. end_range ) ,
1741- HirStatement :: Constrain ( _)
1742- | HirStatement :: Comptime ( _)
1743- | HirStatement :: Break
1744- | HirStatement :: Continue
1745- | HirStatement :: Error => true ,
1746- } )
1747- } ;
1748-
1749- match self . interner . expression ( & expr_id) {
1750- HirExpression :: Ident ( ident, _) => {
1751- if ident. id == DefinitionId :: dummy_id ( ) {
1752- return true ;
1753- }
1754- let definition = self . interner . definition ( ident. id ) ;
1755- if let DefinitionKind :: Function ( id) = definition. kind {
1756- func_id != id
1757- } else {
1758- true
1759- }
1760- }
1761- HirExpression :: Block ( b) => check_block ( b) ,
1762- HirExpression :: Prefix ( e) => check ( e. rhs ) ,
1763- HirExpression :: Infix ( e) => check ( e. lhs ) && check ( e. rhs ) ,
1764- HirExpression :: Index ( e) => check ( e. collection ) && check ( e. index ) ,
1765- HirExpression :: MemberAccess ( e) => check ( e. lhs ) ,
1766- HirExpression :: Call ( e) => check ( e. func ) && e. arguments . iter ( ) . cloned ( ) . all ( check) ,
1767- HirExpression :: MethodCall ( e) => {
1768- check ( e. object ) && e. arguments . iter ( ) . cloned ( ) . all ( check)
1769- }
1770- HirExpression :: Cast ( e) => check ( e. lhs ) ,
1771- HirExpression :: If ( e) => {
1772- check ( e. condition )
1773- && ( check ( e. consequence ) || e. alternative . map ( check) . unwrap_or ( true ) )
1774- }
1775- HirExpression :: Tuple ( e) => e. iter ( ) . cloned ( ) . all ( check) ,
1776- HirExpression :: Unsafe ( b) => check_block ( b) ,
1777- // Rust doesn't check the lambda body (it might not be called).
1778- HirExpression :: Lambda ( _)
1779- | HirExpression :: Literal ( _)
1780- | HirExpression :: Constructor ( _)
1781- | HirExpression :: Quote ( _)
1782- | HirExpression :: Unquote ( _)
1783- | HirExpression :: Comptime ( _)
1784- | HirExpression :: Error => true ,
1785- }
1786- }
17871709}
0 commit comments