Browse Source

forbid return outside functions (closes #9659) (#9665)

Dan Korostelev 5 years ago
parent
commit
2562cc3b70

+ 1 - 0
src/context/typecore.ml

@@ -122,6 +122,7 @@ and typer = {
 	(* per-function *)
 	mutable curfield : tclass_field;
 	mutable untyped : bool;
+	mutable in_function : bool;
 	mutable in_loop : bool;
 	mutable in_display : bool;
 	mutable in_macro : bool;

+ 3 - 0
src/typing/typeloadFunction.ml

@@ -46,6 +46,7 @@ let save_field_state ctx =
 	let old_fun = ctx.curfun in
 	let old_opened = ctx.opened in
 	let old_monos = ctx.monomorphs.perfunction in
+	let old_in_function = ctx.in_function in
 	let locals = ctx.locals in
 	(fun () ->
 		ctx.locals <- locals;
@@ -53,6 +54,7 @@ let save_field_state ctx =
 		ctx.curfun <- old_fun;
 		ctx.opened <- old_opened;
 		ctx.monomorphs.perfunction <- old_monos;
+		ctx.in_function <- old_in_function;
 	)
 
 let type_var_field ctx t e stat do_display p =
@@ -107,6 +109,7 @@ let type_function ctx args ret fmode f do_display p =
 		if n = "this" then v.v_meta <- (Meta.This,[],null_pos) :: v.v_meta;
 		v,c
 	) args f.f_args in
+	ctx.in_function <- true;
 	ctx.curfun <- fmode;
 	ctx.ret <- ret;
 	ctx.opened <- [];

+ 1 - 0
src/typing/typeloadModule.ml

@@ -968,6 +968,7 @@ let type_types_into_module ctx m tdecls p =
 		untyped = false;
 		in_macro = ctx.in_macro;
 		in_display = false;
+		in_function = false;
 		in_loop = false;
 		opened = [];
 		in_call_args = false;

+ 13 - 1
src/typing/typer.ml

@@ -2590,7 +2590,18 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
 		let e = Matcher.Match.match_expr ctx e1 cases def with_type false p in
 		wrap e
 	| EReturn e ->
-		type_return ctx e with_type p
+		if not ctx.in_function then begin
+			display_error ctx "Return outside function" p;
+			match e with
+			| None ->
+				Texpr.Builder.make_null t_dynamic p
+			| Some e ->
+				(* type the return expression to see if there are more errors
+				   as well as use its type as if there was no `return`, since
+				   that is most likely what was meant *)
+				type_expr ctx e WithType.value
+		end else
+			type_return ctx e with_type p
 	| EBreak ->
 		if not ctx.in_loop then display_error ctx "Break outside loop" p;
 		mk TBreak t_dynamic p
@@ -2694,6 +2705,7 @@ let rec create com =
 		macro_depth = 0;
 		untyped = false;
 		curfun = FunStatic;
+		in_function = false;
 		in_loop = false;
 		in_display = false;
 		get_build_infos = (fun() -> None);

+ 5 - 0
tests/misc/projects/Issue9659/Main.hx

@@ -0,0 +1,5 @@
+var field = return 3;
+
+function main() {
+	var x:String = field;
+}

+ 1 - 0
tests/misc/projects/Issue9659/compile-fail.hxml

@@ -0,0 +1 @@
+--main Main

+ 2 - 0
tests/misc/projects/Issue9659/compile-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Main.hx:1: characters 13-21 : Return outside function
+Main.hx:4: characters 2-23 : Int should be String