浏览代码

opened anonymous types.

Nicolas Cannasse 19 年之前
父节点
当前提交
81f56968c3
共有 7 个文件被更改,包括 109 次插入55 次删除
  1. 1 0
      doc/CHANGES.txt
  2. 1 1
      genxml.ml
  3. 1 1
      std/neko/NekoArray__.hx
  4. 3 3
      std/neko/NekoString__.hx
  5. 1 1
      std/neko/Socket.hx
  6. 62 21
      type.ml
  7. 40 28
      typer.ml

+ 1 - 0
doc/CHANGES.txt

@@ -12,6 +12,7 @@
 	fixed very tricky bug with constraint parameters used together with polymorphic methods
 	fixed very tricky bug with constraint parameters used together with polymorphic methods
 	added selective import (import x.y.Class.InnerType)
 	added selective import (import x.y.Class.InnerType)
 	added optional enum constructor parameters
 	added optional enum constructor parameters
+	added opened anonymous types (no more Unknown has no field...)
 	
 	
 2006-06-08: 1.02
 2006-06-08: 1.02
 	fixed stack overflow when recursive class <: recursive signature
 	fixed stack overflow when recursive class <: recursive signature

+ 1 - 1
genxml.ml

@@ -55,7 +55,7 @@ let rec gen_type t =
 	| TInst (c,params) -> node "c" [gen_path c.cl_path c.cl_private] (List.map gen_type params)
 	| TInst (c,params) -> node "c" [gen_path c.cl_path c.cl_private] (List.map gen_type params)
 	| TSign (s,params) -> node "s" [gen_path s.s_path s.s_private] (List.map gen_type params)
 	| TSign (s,params) -> node "s" [gen_path s.s_path s.s_private] (List.map gen_type params)
 	| TFun (args,r) -> node "f" ["a",String.concat ":" (List.map gen_arg_name args)] (List.map gen_type (List.map (fun (_,_,t) -> t) args @ [r]))
 	| TFun (args,r) -> node "f" ["a",String.concat ":" (List.map gen_arg_name args)] (List.map gen_type (List.map (fun (_,_,t) -> t) args @ [r]))
-	| TAnon fields -> node "a" [] (pmap (fun f -> node f.cf_name [] [gen_type f.cf_type]) fields)
+	| TAnon a -> node "a" [] (pmap (fun f -> node f.cf_name [] [gen_type f.cf_type]) a.a_fields)
 	| TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2])
 	| TDynamic t2 -> node "d" [] (if t == t2 then [] else [gen_type t2])
 	| TLazy f -> gen_type (!f())
 	| TLazy f -> gen_type (!f())
 
 

+ 1 - 1
std/neko/NekoArray__.hx

@@ -46,7 +46,7 @@ class NekoArray__<T> implements Array<T> {
 		}
 		}
 	}
 	}
 
 
-	public function concat(arr) {
+	public function concat(arr : Array<T>) : Array<T> {
 		untyped {
 		untyped {
 			var a1 = this.__a;
 			var a1 = this.__a;
 			var a2 = arr.__a;
 			var a2 = arr.__a;

+ 3 - 3
std/neko/NekoString__.hx

@@ -57,7 +57,7 @@ class NekoString__ implements String {
 		}
 		}
 	}
 	}
 
 
-	public function indexOf( str, ?pos ) {
+	public function indexOf( str : String, ?pos ) {
 		untyped {
 		untyped {
 			var p = try __dollar__sfind(this.__s,if( pos == null ) 0 else pos,str.__s) catch( e : Dynamic ) null;
 			var p = try __dollar__sfind(this.__s,if( pos == null ) 0 else pos,str.__s) catch( e : Dynamic ) null;
 			if( p == null )
 			if( p == null )
@@ -66,7 +66,7 @@ class NekoString__ implements String {
 		}
 		}
 	}
 	}
 
 
-	public function lastIndexOf( str, pos ) {
+	public function lastIndexOf( str : String, pos ) {
 		untyped {
 		untyped {
 			var last = -1;
 			var last = -1;
 			if( pos == null )
 			if( pos == null )
@@ -81,7 +81,7 @@ class NekoString__ implements String {
 		}
 		}
 	}
 	}
 
 
-	public function split( delim ) {
+	public function split( delim : String ) {
 		untyped {
 		untyped {
 			var l = __split(this.__s,delim.__s);
 			var l = __split(this.__s,delim.__s);
 			var a = new Array<String>();
 			var a = new Array<String>();

+ 1 - 1
std/neko/Socket.hx

@@ -126,7 +126,7 @@ class Socket {
 	// STATICS
 	// STATICS
 	public static function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, timeout : Float) : {read: Array<Socket>,write: Array<Socket>,others: Array<Socket>} {
 	public static function select(read : Array<Socket>, write : Array<Socket>, others : Array<Socket>, timeout : Float) : {read: Array<Socket>,write: Array<Socket>,others: Array<Socket>} {
 		var c = untyped __dollar__hnew( 1 );
 		var c = untyped __dollar__hnew( 1 );
-		var f = function( a ){
+		var f = function( a : Array<Socket> ){
 			if( a == null ) return null;
 			if( a == null ) return null;
 			untyped {
 			untyped {
 				var r = __dollar__amake(a.length);
 				var r = __dollar__amake(a.length);

+ 62 - 21
type.ml

@@ -30,7 +30,7 @@ type t =
 	| TInst of tclass * t list
 	| TInst of tclass * t list
 	| TSign of tsignature * t list
 	| TSign of tsignature * t list
 	| TFun of (string * bool * t) list * t
 	| TFun of (string * bool * t) list * t
-	| TAnon of (string, tclass_field) PMap.t
+	| TAnon of tanon
 	| TDynamic of t
 	| TDynamic of t
 	| TLazy of (unit -> t) ref
 	| TLazy of (unit -> t) ref
 
 
@@ -49,6 +49,11 @@ and tfunc = {
 	tf_expr : texpr;
 	tf_expr : texpr;
 }
 }
 
 
+and tanon = {
+	mutable a_fields : (string, tclass_field) PMap.t;
+	a_open : bool ref;
+}
+
 and texpr_expr =
 and texpr_expr =
 	| TConst of tconstant
 	| TConst of tconstant
 	| TLocal of string
 	| TLocal of string
@@ -151,6 +156,21 @@ type module_def = {
 
 
 let mk e t p = { eexpr = e; etype = t; epos = p }
 let mk e t p = { eexpr = e; etype = t; epos = p }
 
 
+let not_opened = ref false
+
+let mk_anon fl = TAnon { a_fields = fl; a_open = not_opened; }
+
+let mk_field name t = {
+	cf_name = name;
+	cf_type = t;
+	cf_doc = None;
+	cf_public = true;
+	cf_get = NormalAccess;
+	cf_set = NormalAccess;
+	cf_expr = None;
+	cf_params = [];
+}
+
 let mk_mono() = TMono (ref None)
 let mk_mono() = TMono (ref None)
 
 
 let rec t_dynamic = TDynamic t_dynamic
 let rec t_dynamic = TDynamic t_dynamic
@@ -208,9 +228,9 @@ let rec s_type ctx t =
 		String.concat " -> " (List.map (fun (s,b,t) ->
 		String.concat " -> " (List.map (fun (s,b,t) ->
 			(if b then "?" else "") ^ (if s = "" then "" else s ^ " : ") ^ s_fun ctx t true
 			(if b then "?" else "") ^ (if s = "" then "" else s ^ " : ") ^ s_fun ctx t true
 		) l) ^ " -> " ^ s_fun ctx t false
 		) l) ^ " -> " ^ s_fun ctx t false
-	| TAnon fl ->
-		let fl = PMap.fold (fun f acc -> (" " ^ f.cf_name ^ " : " ^ s_type ctx f.cf_type) :: acc) fl [] in
-		"{" ^ String.concat "," fl ^ " }"
+	| TAnon a ->
+		let fl = PMap.fold (fun f acc -> (" " ^ f.cf_name ^ " : " ^ s_type ctx f.cf_type) :: acc) a.a_fields [] in
+		"{" ^ (if !(a.a_open) then "+" else "") ^  String.concat "," fl ^ " }"
 	| TDynamic t2 ->
 	| TDynamic t2 ->
 		"Dynamic" ^ s_type_params ctx (if t == t2 then [] else [t2])
 		"Dynamic" ^ s_type_params ctx (if t == t2 then [] else [t2])
 	| TLazy f ->
 	| TLazy f ->
@@ -248,9 +268,9 @@ let rec link e a b =
 				loop t2
 				loop t2
 		| TLazy f ->
 		| TLazy f ->
 			loop (!f())
 			loop (!f())
-		| TAnon fl ->
+		| TAnon a ->
 			try
 			try
-				PMap.iter (fun _ f -> if loop f.cf_type then raise Exit) fl;
+				PMap.iter (fun _ f -> if loop f.cf_type then raise Exit) a.a_fields;
 				false
 				false
 			with
 			with
 				Exit -> true
 				Exit -> true
@@ -308,8 +328,11 @@ let apply_params cparams params t =
 				TInst (c,List.map loop tl))
 				TInst (c,List.map loop tl))
 		| TFun (tl,r) ->
 		| TFun (tl,r) ->
 			TFun (List.map (fun (s,o,t) -> s, o, loop t) tl,loop r)
 			TFun (List.map (fun (s,o,t) -> s, o, loop t) tl,loop r)
-		| TAnon fl ->
-			TAnon (PMap.map (fun f -> { f with cf_type = loop f.cf_type }) fl)
+		| TAnon a ->
+			TAnon {
+				a_fields = PMap.map (fun f -> { f with cf_type = loop f.cf_type }) a.a_fields;
+				a_open = a.a_open;
+			}
 		| TLazy f ->
 		| TLazy f ->
 			let ft = !f() in
 			let ft = !f() in
 			let ft2 = loop ft in
 			let ft2 = loop ft in
@@ -367,17 +390,27 @@ let rec type_eq param a b =
 		type_eq param r1 r2 && List.for_all2 (fun (_,o1,t1) (_,o2,t2) -> o1 = o2 && type_eq param t1 t2) l1 l2
 		type_eq param r1 r2 && List.for_all2 (fun (_,o1,t1) (_,o2,t2) -> o1 = o2 && type_eq param t1 t2) l1 l2
 	| TDynamic a , TDynamic b ->
 	| TDynamic a , TDynamic b ->
 		type_eq param a b
 		type_eq param a b
-	| TAnon fl1, TAnon fl2 ->
-		let keys1 = PMap.fold (fun f acc -> f :: acc) fl1 [] in
-		let keys2 = PMap.fold (fun f acc -> f :: acc) fl2 [] in
+	| TAnon a1, TAnon a2 ->
 		(try
 		(try
-			List.iter2 (fun f1 f2 ->
-				if f1.cf_name <> f2.cf_name || not (type_eq param f1.cf_type f2.cf_type) then raise Not_found;
-				if f1.cf_get <> f2.cf_get || f1.cf_set <> f2.cf_set then raise Not_found;
-			) keys1 keys2;
+			PMap.iter (fun _ f1 ->
+				try
+					let f2 = PMap.find f1.cf_name a2.a_fields in
+					if not (type_eq param f1.cf_type f2.cf_type) then raise Exit;
+					if f1.cf_get <> f2.cf_get || f1.cf_set <> f2.cf_set then raise Exit;	
+				with
+					Not_found ->
+						if not !(a2.a_open) then raise Exit;
+						a2.a_fields <- PMap.add f1.cf_name f1 a2.a_fields
+			) a1.a_fields;
+			PMap.iter (fun _ f2 ->
+				if not (PMap.mem f2.cf_name a1.a_fields) then begin
+					if not !(a1.a_open) then raise Exit;
+					a1.a_fields <- PMap.add f2.cf_name f2 a1.a_fields
+				end;
+			) a2.a_fields;
 			true
 			true
 		with
 		with
-			_ -> false)
+			Exit -> false)
 	| _ , _ ->
 	| _ , _ ->
 		false
 		false
 
 
@@ -469,7 +502,7 @@ let rec unify a b =
 			) l2 l1 (* contravariance *)
 			) l2 l1 (* contravariance *)
 		with
 		with
 			Unify_error l -> error (cannot_unify a b :: l))
 			Unify_error l -> error (cannot_unify a b :: l))
-	| TInst (c,tl) , TAnon fl ->
+	| TInst (c,tl) , TAnon an ->
 		(try
 		(try
 			PMap.iter (fun n f2 ->
 			PMap.iter (fun n f2 ->
 				let f1 = (try PMap.find n c.cl_fields with Not_found -> error [has_no_field a n]) in
 				let f1 = (try PMap.find n c.cl_fields with Not_found -> error [has_no_field a n]) in
@@ -480,13 +513,15 @@ let rec unify a b =
 					unify (apply_params c.cl_types tl f1.cf_type) f2.cf_type
 					unify (apply_params c.cl_types tl f1.cf_type) f2.cf_type
 				with
 				with
 					Unify_error l -> error (invalid_field n :: l)
 					Unify_error l -> error (invalid_field n :: l)
-			) fl
+			) an.a_fields;
+			an.a_open := false;
 		with
 		with
 			Unify_error l -> error (cannot_unify a b :: l))
 			Unify_error l -> error (cannot_unify a b :: l))
-	| TAnon fl1, TAnon fl2 ->
+	| TAnon a1, TAnon a2 ->
 		(try
 		(try
 			PMap.iter (fun n f2 ->
 			PMap.iter (fun n f2 ->
-				let f1 = (try PMap.find n fl1 with Not_found -> error [has_no_field a n]) in
+			try
+				let f1 = PMap.find n a1.a_fields in
 				if not (unify_access f1.cf_get f2.cf_get) then error [invalid_access n true];
 				if not (unify_access f1.cf_get f2.cf_get) then error [invalid_access n true];
 				if not (unify_access f1.cf_set f2.cf_set) then error [invalid_access n false];
 				if not (unify_access f1.cf_set f2.cf_set) then error [invalid_access n false];
 				if f2.cf_public && not f1.cf_public then error [invalid_visibility n];
 				if f2.cf_public && not f1.cf_public then error [invalid_visibility n];
@@ -494,7 +529,13 @@ let rec unify a b =
 					unify f1.cf_type f2.cf_type;
 					unify f1.cf_type f2.cf_type;
 				with
 				with
 					Unify_error l -> error (invalid_field n :: l)
 					Unify_error l -> error (invalid_field n :: l)
-			) fl2;
+			with
+				Not_found ->
+					if not !(a1.a_open) then error [has_no_field a n];
+					a1.a_fields <- PMap.add n f2 a1.a_fields
+			) a2.a_fields;
+			a1.a_open := false;
+			a2.a_open := false;
 		with
 		with
 			Unify_error l -> error (cannot_unify a b :: l))
 			Unify_error l -> error (cannot_unify a b :: l))
 	| TDynamic t , _ ->
 	| TDynamic t , _ ->

+ 40 - 28
typer.ml

@@ -54,6 +54,7 @@ type context = {
 	mutable locals : (string, t) PMap.t;
 	mutable locals : (string, t) PMap.t;
 	mutable locals_map : (string, string) PMap.t;
 	mutable locals_map : (string, string) PMap.t;
 	mutable locals_map_inv : (string, string) PMap.t;
 	mutable locals_map_inv : (string, string) PMap.t;
+	mutable opened : bool ref list;
 }
 }
 
 
 (* ---------------------------------------------------------------------- *)
 (* ---------------------------------------------------------------------- *)
@@ -136,6 +137,7 @@ let context err warn =
 		tthis = mk_mono();
 		tthis = mk_mono();
 		current = empty;
 		current = empty;
 		std = empty;
 		std = empty;
+		opened = [];
 	} in
 	} in
 	ctx.std <- (try
 	ctx.std <- (try
 		load ctx ([],"StdTypes") null_pos
 		load ctx ([],"StdTypes") null_pos
@@ -336,7 +338,7 @@ and load_type ctx p t =
 	| TPNormal t -> load_normal_type ctx t p false
 	| TPNormal t -> load_normal_type ctx t p false
 	| TPExtend (t,l) ->
 	| TPExtend (t,l) ->
 		(match load_type ctx p (TPAnonymous l) with
 		(match load_type ctx p (TPAnonymous l) with
-		| TAnon l ->
+		| TAnon a ->
 			let rec loop t =
 			let rec loop t =
 				match follow t with
 				match follow t with
 				| TInst (c,tl) ->
 				| TInst (c,tl) ->
@@ -347,17 +349,17 @@ and load_type ctx p t =
 							error ("Cannot redefine field " ^ f) p
 							error ("Cannot redefine field " ^ f) p
 						with
 						with
 							Not_found -> ()
 							Not_found -> ()
-					) l;
+					) a.a_fields;
 					c2.cl_super <- Some (c,tl);
 					c2.cl_super <- Some (c,tl);
-					c2.cl_fields <- l;
+					c2.cl_fields <- a.a_fields;
 					TInst (c2,[])
 					TInst (c2,[])
 				| TMono _ ->
 				| TMono _ ->
 					error "Please ensure correct initialization of cascading signatures" p
 					error "Please ensure correct initialization of cascading signatures" p
-				| TAnon fields ->
+				| TAnon a2 ->
 					PMap.iter (fun f _ ->
 					PMap.iter (fun f _ ->
-						if PMap.mem f fields then error ("Cannot redefine field " ^ f) p
-					) l;
-					TAnon (PMap.foldi PMap.add l fields)
+						if PMap.mem f a2.a_fields then error ("Cannot redefine field " ^ f) p
+					) a.a_fields;
+					mk_anon (PMap.foldi PMap.add a.a_fields a2.a_fields)
 				| _ -> error "Cannot only extend classes and anonymous" p
 				| _ -> error "Cannot only extend classes and anonymous" p
 			in
 			in
 			loop (load_normal_type ctx t p false)
 			loop (load_normal_type ctx t p false)
@@ -393,7 +395,7 @@ and load_type ctx p t =
 				cf_doc = None;
 				cf_doc = None;
 			} acc
 			} acc
 		in
 		in
-		TAnon (List.fold_left loop PMap.empty l)
+		mk_anon (List.fold_left loop PMap.empty l)
 	| TPFunction (args,r) ->
 	| TPFunction (args,r) ->
 		match args with
 		match args with
 		| [TPNormal { tpackage = []; tparams = []; tname = "Void" }] ->
 		| [TPNormal { tpackage = []; tparams = []; tname = "Void" }] ->
@@ -416,10 +418,10 @@ let rec reverse_type t =
 		TPNormal { tpackage = fst s.s_path; tname = snd s.s_path; tparams = List.map reverse_type params }
 		TPNormal { tpackage = fst s.s_path; tname = snd s.s_path; tparams = List.map reverse_type params }
 	| TFun (params,ret) ->
 	| TFun (params,ret) ->
 		TPFunction (List.map (fun (_,_,t) -> reverse_type t) params,reverse_type ret)
 		TPFunction (List.map (fun (_,_,t) -> reverse_type t) params,reverse_type ret)
-	| TAnon fields ->
+	| TAnon a ->
 		TPAnonymous (PMap.fold (fun f acc ->
 		TPAnonymous (PMap.fold (fun f acc ->
 			(f.cf_name , AFVar (reverse_type f.cf_type), null_pos) :: acc
 			(f.cf_name , AFVar (reverse_type f.cf_type), null_pos) :: acc
-		) fields [])
+		) a.a_fields [])
 	| TDynamic t2 ->
 	| TDynamic t2 ->
 		TPNormal { tpackage = []; tname = "Dynamic"; tparams = if t == t2 then [] else [reverse_type t2] }
 		TPNormal { tpackage = []; tname = "Dynamic"; tparams = if t == t2 then [] else [reverse_type t2] }
 	| _ ->
 	| _ ->
@@ -848,7 +850,7 @@ let type_type ctx tpath p =
 			s_path = fst c.cl_path, "#" ^ snd c.cl_path;
 			s_path = fst c.cl_path, "#" ^ snd c.cl_path;
 			s_doc = None;
 			s_doc = None;
 			s_pos = c.cl_pos;
 			s_pos = c.cl_pos;
-			s_type = TAnon (if pub then PMap.map (fun f -> { f with cf_public = true }) c.cl_statics else c.cl_statics);
+			s_type = mk_anon (if pub then PMap.map (fun f -> { f with cf_public = true }) c.cl_statics else c.cl_statics);
 			s_private = true;
 			s_private = true;
 			s_static = Some c;
 			s_static = Some c;
 			s_types = c.cl_types;
 			s_types = c.cl_types;
@@ -872,7 +874,7 @@ let type_type ctx tpath p =
 			s_path = fst e.e_path, "#" ^ snd e.e_path;
 			s_path = fst e.e_path, "#" ^ snd e.e_path;
 			s_doc = None;
 			s_doc = None;
 			s_pos = e.e_pos;
 			s_pos = e.e_pos;
-			s_type = TAnon fl;
+			s_type = mk_anon fl;
 			s_private = true;
 			s_private = true;
 			s_static = None;
 			s_static = None;
 			s_types = e.e_types;
 			s_types = e.e_types;
@@ -980,12 +982,26 @@ let type_field ctx e i p get =
 			no_field())
 			no_field())
 	| TDynamic t ->
 	| TDynamic t ->
 		AccExpr (mk (TField (e,i)) t p)
 		AccExpr (mk (TField (e,i)) t p)
-	| TAnon fl ->
+	| TAnon a ->
 		(try
 		(try
-			let f = PMap.find i fl in
+			let f = PMap.find i a.a_fields in
 			if not f.cf_public && not ctx.untyped then display_error ctx ("Cannot access to private field " ^ i) p;
 			if not f.cf_public && not ctx.untyped then display_error ctx ("Cannot access to private field " ^ i) p;
 			field_access ctx get f (field_type f) e p
 			field_access ctx get f (field_type f) e p
-		with Not_found -> no_field())
+		with Not_found ->
+			if not !(a.a_open) then
+				no_field()
+			else
+			let f = mk_field i (mk_mono()) in
+			a.a_fields <- PMap.add i f a.a_fields;
+			field_access ctx get f (field_type f) e p
+		)
+	| TMono r ->
+		let f = mk_field i (mk_mono()) in
+		let x = ref true in
+		let t = TAnon { a_fields = PMap.add i f PMap.empty; a_open = x } in
+		ctx.opened <- x :: ctx.opened;
+		r := Some t;
+		field_access ctx get f (field_type f) e p
 	| t ->
 	| t ->
 		no_field()
 		no_field()
 
 
@@ -1381,20 +1397,11 @@ and type_expr ctx ?(need_val=true) (e,p) =
 		let rec loop (l,acc) (f,e) =
 		let rec loop (l,acc) (f,e) =
 			if PMap.mem f acc then error ("Duplicate field in object declaration : " ^ f) p;
 			if PMap.mem f acc then error ("Duplicate field in object declaration : " ^ f) p;
 			let e = type_expr ctx e in
 			let e = type_expr ctx e in
-			let cf = {
-				cf_name = f;
-				cf_type = e.etype;
-				cf_public = true;
-				cf_get = NormalAccess;
-				cf_set = NormalAccess;
-				cf_expr = None;
-				cf_doc = None;
-				cf_params = [];
-			} in
+			let cf = mk_field f e.etype in
 			((f,e) :: l, PMap.add f cf acc)
 			((f,e) :: l, PMap.add f cf acc)
 		in
 		in
 		let fields , types = List.fold_left loop ([],PMap.empty) fl in
 		let fields , types = List.fold_left loop ([],PMap.empty) fl in
-		mk (TObjectDecl fields) (TAnon types) p
+		mk (TObjectDecl fields) (mk_anon types) p
 	| EArrayDecl el ->
 	| EArrayDecl el ->
 		let t , pt = t_array ctx in
 		let t , pt = t_array ctx in
 		let dyn = ref ctx.untyped in
 		let dyn = ref ctx.untyped in
@@ -1682,7 +1689,7 @@ and type_expr ctx ?(need_val=true) (e,p) =
 			]),p)
 			]),p)
 
 
 and type_function ctx t static constr f p =
 and type_function ctx t static constr f p =
-	let locals = save_locals ctx in
+	let locals = save_locals ctx in	
 	let fargs , r = (match t with
 	let fargs , r = (match t with
 		| TFun (args,r) -> List.map (fun (n,opt,t) -> add_local ctx n t, opt, t) args, r
 		| TFun (args,r) -> List.map (fun (n,opt,t) -> add_local ctx n t, opt, t) args, r
 		| _ -> assert false
 		| _ -> assert false
@@ -1690,9 +1697,11 @@ and type_function ctx t static constr f p =
 	let old_ret = ctx.ret in
 	let old_ret = ctx.ret in
 	let old_static = ctx.in_static in
 	let old_static = ctx.in_static in
 	let old_constr = ctx.in_constructor in
 	let old_constr = ctx.in_constructor in
+	let old_opened = ctx.opened in
 	ctx.in_static <- static;
 	ctx.in_static <- static;
 	ctx.in_constructor <- constr;
 	ctx.in_constructor <- constr;
 	ctx.ret <- r;
 	ctx.ret <- r;
+	ctx.opened <- [];
 	let e = type_expr ~need_val:false ctx f.f_expr in
 	let e = type_expr ~need_val:false ctx f.f_expr in
 	let rec loop e =
 	let rec loop e =
 		match e.eexpr with
 		match e.eexpr with
@@ -1718,9 +1727,11 @@ and type_function ctx t static constr f p =
 		with
 		with
 			Exit -> ());
 			Exit -> ());
 	locals();
 	locals();
+	List.iter (fun r -> r := false) ctx.opened;
 	ctx.ret <- old_ret;
 	ctx.ret <- old_ret;
 	ctx.in_static <- old_static;
 	ctx.in_static <- old_static;
 	ctx.in_constructor <- old_constr;
 	ctx.in_constructor <- old_constr;
+	ctx.opened <- old_opened;
 	e , fargs
 	e , fargs
 
 
 let type_static_var ctx t e p =
 let type_static_var ctx t e p =
@@ -1750,7 +1761,7 @@ let check_overloading ctx c p () =
 let rec check_interface ctx c p intf params =
 let rec check_interface ctx c p intf params =
 	PMap.iter (fun i f ->
 	PMap.iter (fun i f ->
 		try
 		try
-			let t , f2 = class_field c i in
+			let t , f2 = class_field c i in			
 			if f.cf_public && not f2.cf_public then
 			if f.cf_public && not f2.cf_public then
 				display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p
 				display_error ctx ("Field " ^ i ^ " should be public as requested by " ^ s_type_path intf.cl_path) p
 			else if not(unify_access f2.cf_get f.cf_get) then
 			else if not(unify_access f2.cf_get f.cf_get) then
@@ -2049,6 +2060,7 @@ let type_module ctx m tdecls loadp =
 		in_static = false;
 		in_static = false;
 		in_loop = false;
 		in_loop = false;
 		untyped = false;
 		untyped = false;
+		opened = [];
 	} in
 	} in
 	let delays = ref [] in
 	let delays = ref [] in
 	let get_class name =
 	let get_class name =