diff --git a/src/semantize/typing.nit b/src/semantize/typing.nit index 2b78c9f127..0ca99d3d2d 100644 --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@ -629,6 +629,21 @@ private class TypeVisitor # Some loops had been visited during the visit var has_loop = false + # Visit `nbody`, the body of `npropdef` + fun visit_body(npropdef: APropdef, nbody: nullable AExpr) + do + if nbody != null then + loop + dirty = false + visit_stmt(nbody) + if not has_loop or not dirty then break + end + end + + var post_visitor = new PostTypingVisitor(self) + post_visitor.enter_visit(npropdef) + end + fun set_variable(node: AExpr, variable: Variable, mtype: nullable MType) do var flow = node.after_flow_context @@ -1014,14 +1029,7 @@ redef class AMethPropdef var nblock = self.n_block if nblock == null then return - loop - v.dirty = false - v.visit_stmt(nblock) - if not v.has_loop or not v.dirty then break - end - - var post_visitor = new PostTypingVisitor(v) - post_visitor.enter_visit(self) + v.visit_body(self, nblock) if not nblock.after_flow_context.is_unreachable and msignature.return_mtype != null then # We reach the end of the function without having a return, it is bad @@ -1069,12 +1077,11 @@ redef class AAttrPropdef v.visit_expr_subtype(nexpr, mtype) end var nblock = self.n_block - if nblock != null then - v.visit_stmt(nblock) - if not nblock.after_flow_context.is_unreachable then - # We reach the end of the init without having a return, it is bad - v.error(self, "Error: reached end of block; expected `return`.") - end + v.visit_body(self, nblock) + + if nblock != null and not nblock.after_flow_context.is_unreachable then + # We reach the end of the init without having a return, it is bad + v.error(self, "Error: reached end of block; expected `return`.") end end end @@ -1132,18 +1139,6 @@ redef class AExpr end return res end - - # Type the expression as if located in `visited_mpropdef` - # `TypeVisitor` and `PostTypingVisitor` will be used to do the typing, see them for more information. - # - # `visited_mpropdef`: Correspond to the evaluation context in which the expression is located. - fun do_typing(modelbuilder: ModelBuilder, visited_mpropdef: MPropDef) - do - var type_visitor = new TypeVisitor(modelbuilder, visited_mpropdef) - type_visitor.visit_stmt(self) - var post_visitor = new PostTypingVisitor(type_visitor) - post_visitor.enter_visit(self) - end end redef class ABlockExpr diff --git a/tests/base_adaptive_loop_attr.nit b/tests/base_adaptive_loop_attr.nit new file mode 100644 index 0000000000..cee35d299b --- /dev/null +++ b/tests/base_adaptive_loop_attr.nit @@ -0,0 +1,45 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import core::kernel +class A + fun m: nullable Object do + var b = null + loop + if b != null then return b + b = 1 + end + end + + var x: nullable Object do + var b = null + loop + if b != null then return b + b = 2 + end + end + + var y: nullable Object is lazy do + var b = null + loop + if b != null then return b + b = 3 + end + end +end + +var a = new A +a.m.as(not null).output +a.x.as(not null).output +a.y.as(not null).output diff --git a/tests/base_attr_useless_check.nit b/tests/base_attr_useless_check.nit new file mode 100644 index 0000000000..6ea6287b2b --- /dev/null +++ b/tests/base_attr_useless_check.nit @@ -0,0 +1,43 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import core::kernel + +class A + fun m: Int do + var i = 1 + if i == null then return 0 + return i.as(Int) + end + + var x: Int do + var i = 2 + if i == null then return 0 + return i.as(Int) + end + + var y: Int is lazy do + var i = 3 + if i isa Int then return i + return 0 + end + + var z: Int = 4.as(Int) +end + +var a = new A +a.m.output +a.x.output +a.y.output +a.z.output diff --git a/tests/sav/base_adaptive_loop_attr.res b/tests/sav/base_adaptive_loop_attr.res new file mode 100644 index 0000000000..01e79c32a8 --- /dev/null +++ b/tests/sav/base_adaptive_loop_attr.res @@ -0,0 +1,3 @@ +1 +2 +3 diff --git a/tests/sav/base_attr_useless_check.res b/tests/sav/base_attr_useless_check.res new file mode 100644 index 0000000000..9c427f5246 --- /dev/null +++ b/tests/sav/base_attr_useless_check.res @@ -0,0 +1,10 @@ +base_attr_useless_check.nit:20,6: Warning: expression is not null, since it is a `Int`. +base_attr_useless_check.nit:21,10--18: Warning: expression is already a `Int`. +base_attr_useless_check.nit:26,6: Warning: expression is not null, since it is a `Int`. +base_attr_useless_check.nit:27,10--18: Warning: expression is already a `Int`. +base_attr_useless_check.nit:32,6--14: Warning: expression is already a `Int`. +base_attr_useless_check.nit:36,15--23: Warning: expression is already a `Int`. +1 +2 +3 +4