Number: 1201 Title: ltUnbound in curried functor with where structure Keywords: modules, functors, where structure Submitter: Dave MacQueen Date: 5/16/97 Version: 109.27+ (with SML 97 sharing, where structure, etc.) System: - Severity: major Problem: A "where structure" clause modifying the second parameter signature refers to a substructure of the first parameter. The result is a message "**** hmmm, I didn't find the variable 52" and an uncaught ltUnbound exception. Code: signature SA = sig type t end; signature SX = sig structure A : SA end; signature SY = sig structure A : SA end; functor F (structure X : SX) (structure Y : SY where structure A = X.A) = struct end; Transcript: - use "bug1201.sml"; [opening bug1201.sml] signature SA = sig type t end signature SX = sig structure A : sig type t end end signature SY = sig structure A : sig type t end end **** hmmm, I didn't find the variable 52 uncaught exception ltUnbound raised at: basics/ltyenv.sml:244.32-244.41 util/stats.sml:164.40 util/stats.sml:164.40 util/stats.sml:164.40 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 Comments: An extended variant of this remains open. See bug 1205. [fixed in 109.31] Fix: In ElabSig, where a STRdef is created by elabWhere, in the case that the STRdef in a CONSTstrDef variant, we replace the access and info fields by null values (NO_ACCESS and INL_NO respectively), since these fields are not relevant. Alternatively we could have CONSTstrDef have a record with only the sign and rlzn fields from the structure. Test: bug1201.sml Owner: dbm, zhong Status: fixed in 109.28 [dbm, 5/19/97] ---------------------------------------------------------------------- Number: 1202 Title: Unbound in functor with where structure clause on parameter sig Keywords: modules, functors, where structure Submitter: Dave MacQueen Date: 5/16/97 Version: 109.27+ (with SML 97 sharing, where structure, etc) System: - Severity: major Problem: where structure clause in parameter signature causes uncaught exception Unbound Code: signature SA = sig type t end; signature SX = sig structure A : SA end; signature SY = sig structure A : SA end; functor F (structure X : SX structure Y : SY where structure A = X.A) = struct end; Transcript: - use "bug1202.sml"; [opening bug1202.sml] signature SA = sig type t end signature SX = sig structure A : sig type t end end signature SY = sig structure A : sig type t end end uncaught exception Unbound raised at: elaborate/elabmod.sml:1144.39-1144.49 util/stats.sml:164.40 build/evalloop.sml:120.38 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 Comments: Note that in bug1202.3, the explicit definition of the parameter signature SZ works, but the functor declaration still fails with uncaught Unbound. This is probably the same bug as 1200. Fix: Test: bug1202.1.sml, bug1202.2.sml, bug1202.3.sml Owner: dbm Status: fixed in 109.28 [dbm,5/20/97] ---------------------------------------------------------------------- Number: 1203 Title: structure def spec doesn't work Keywords: modules, signatures, functors, structure definition spec Submitter: Dave MacQueen Date: 5/16/97 Version: 109.27+ (with SML 97 sharing, where structure, etc) System: - Severity: major Problem: A structure def spec in a functor parameter signature doesn't have the expected effect. Code: signature S = sig type t end; structure A : S = struct type t = int end; functor F1(X: sig type t = A.t end) = struct val x : X.t = 3 end; functor F2(X: sig structure B: S = A end) = struct val x : X.B.t = 3 end; Transcript: - use "bug1203.sml"; [opening bug1203.sml] signature S = sig type t end structure A : S functor F1 : GC #0.0.0.0.1.2: (0 ms) bug1203.sml:18.3-18.20 Error: pattern and expression in val dec don't agree [literal] pattern: ?.t expression: int in declaration: x : ?.t = (3 : int) uncaught exception Error raised at: build/evalloop.sml:103.44-103.52 build/evalloop.sml:120.38 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 Comments: Fix: Test: bug1203.sml Owner: dbm Status: fixed in 109.28 [dbm] ---------------------------------------------------------------------- Number: 1204 Title: invalid paths in lhs of where clauses Keywords: modules, signatures, where clauses Submitter: Dave MacQueen Date: 5/16/97 Version: 109.27+ (SML 97 sharing, where structure, etc.) System: - Severity: major Problem: An invalid path in the the lhs of a where clause is not detected when a signature is elaborated, and causes uncaught Unbound when the signature is instantiated as a functor parameter. Code: This causes no complaint: (* bug1204.1.sml *) signature S = sig type t end; signature S1 = S where type A.t = int; while this causes uncaught exception Unbound: (* bug1204.2.sml *) signature S = sig type t end; functor F(X: S where type A.t = int) = struct end; Comments: Fix: added checkWhereDefs in ElabSig to check that lhs paths are valid. Test: bug1204.1.sml, bug1204.2.sml Owner: dbm Status: fixed in 109.28 [dbm, 5/17/98] ---------------------------------------------------------------------- Number: 1205 Title: problem with "where structure" and curried functors (cf. 1201) Keywords: modules, functors, curried functors, where structure Submitter: Dave MacQueen Date: 5/21/97 Version: 109.27+ (109.28) System: - Severity: major Problem: Defining the result of a curried functor by partial application of another curried functor, a "where structure" spec is not matched. Code: (* bug1205.sml *) signature SA = sig type t end; signature SX = sig structure A : SA end; signature SY = sig structure A : SA end; functor F (structure X : SX) (structure Y : SY where structure A = X.A) = struct fun f(x: X.A.t, y: Y.A.t list) = x::y end; functor G(structure A : SA) : sig functor G1(structure Y: SY where structure A = A) : sig end end = struct functor G1 = F(structure X = struct structure A = A end) end; Transcript: [opening test/bugs/bug1205.sml] signature SA = sig type t end signature SX = sig structure A : sig type t end end signature SY = sig structure A : sig type t end end GC #0.0.0.0.1.5: (0 ms) functor F : test/bugs/bug1205.sml:26.9-32.4 Error: where structure spec not matched: A uncaught exception Error raised at: build/evalloop.sml:103.44-103.52 build/evalloop.sml:120.38 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 Comments: This bug represents a problem with MLRISC/mlrisc/ra.sml and MLRISC/hppa/hppaRegAlloc.sml and MLRISC/alpha32/alpha32RegAlloc.sml. Fix: In processing structure def specs or where structure defs, lookStrDef has to relativize structures that are local to a functor (such as the functor parameter), turning CONSTstrDefs into VARstrDefs for such local structures. A local version of lookStrDef was defined within ElabSig (which is the only module using Lookup.lookStrDef) that does this relativization. Test: bug1205.sml Owner: dbm, Zhong Status: fixed in 109.31 [dbm, 8/14/97] ---------------------------------------------------------------------- Number: 1206 Title: Compiler bug: TransTypes: unexpected FORMAL kind in tycTyc-h Keywords: modules, functors, TransTypes Submitter: George Russell Date: 5/7/97 Version: 109.28- System: - Severity: major Problem: Compiling the code below (which requires smlnj-lib) causes Compiler bug: TransTypes: unexpected FORMAL kind in tycTyc-h Code: functor Dictionary (HK:HASH_KEY): sig type 'b dictionary val create: int->'b dictionary end= struct structure Hash=HashTableFn(HK) exception NF type 'b dictionary='b Hash.hash_table fun create i=Hash.mkTable(i,NF) end functor T(S:HASH_KEY)= struct structure U=Dictionary(S) datatype v=v of int U.dictionary fun cre n=v(U.create n) end; structure OP=T(struct type hash_key=Word.word fun hashVal k=k val sameKey=op= end) [Zhong, 5/7/97] I have narrowed your code further down the following (it does not rely on the SML Library any more): functor Dict (type t) : sig type dict end = struct datatype dict = HT of t | NIL type dict = dict (* removing this line, the bug goes away *) end functor T(type t) = struct structure U = Dict(type t = t) datatype s = EE of U.dict | FF val x = FF end; structure A = T(type t = int) Transcript: - use "/usr/local/sml/bugs/tests/bug1206.sml"; [opening /usr/local/sml/bugs/tests/bug1206.sml] functor Dictionary : functor T : Error: Compiler bug: TransTypes: unexpected FORMAL kind in tycTyc-h uncaught exception Error raised at: util/errormsg.sml:51.14-51.19 util/stats.sml:164.40 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 Comments: [Zhong, 6/24/97] (* The following is a narrowed-down version of the code. The code raises the following exception: - [opening ztodo/z3.sml] functor T : Error: Compiler bug: TransTypes: unexpected FORMAL kind in tycTyc-h I managed to track it down and understand that the bug is caused by the incorrect management of "epContext". The scenerio is like this: datatype u is shadowed by another DEFtyc u inside U, so it is not exported by structure U; when we enter structure U, we create a new level of epContext, but when finish processing structure U, this level of epContext is popped off; we do try to recover the epContext binding all the components exported by structure U, but not the shadowed datatype "u". Therefore, when we process datatype s, the type U.u is not properly relativized because the shadowed version of u is not in the epContext. Possible fixes: we have to adjust the "enterClosed" or the "mapEPC" functions to take account these shadowed type bindings. *) functor T(type t) = struct structure U = struct datatype u = HT of t type u = u (* removing this line, the bug goes away *) end datatype s = EE of U.u val x = fn (_: s) => 0 end; structure A = T(type t = int) Fix: Added enterOpenNew and mergeHidden functions to modules/epcontext.sml and called them within function elabStrbs in elaborate/elabmod.sml. The effect is the preserve mappings for local hidden types that won't be found by the call to mapPaths, like the internal datatype u in the above code. Test: bug1206.sml (requires smlnj-lib), bug1206.2.sml Owner: Zhong, dbm Status: fixed in 109.32 (dbm, 7/21/97) ---------------------------------------------------------------------- Number: 1207 Title: unimplemented include syntax Keywords: syntax, parsing, include, signatures Submitter: John Reppy Date: 5/22/97 Version: 109.29 System: - Severity: medium Problem: The syntax for the basic "include" spec is include sigexp (page 14, DSMLR). Only sidids are accepted as arguments now. Comments: The derived form include sigid1 ... sigidn is implemented properly. The derived form does not allow for sigexps. Code: (from Andrew Kennedy) signature SIG = sig datatype d = c include sig type t end where type t = d end; Transcript: Error: Compiler bug: Include: elabInclude Fix: Test: bug1207.sml Owner: dbm Status: fixed in 110 [dbm, 10/25/97] ---------------------------------------------------------------------- Number: 1208 Title: unimplemented strexp syntax Keywords: syntax, parsing, structures Submitter: Dave MacQueen Date: 6/19/97 Version: 109.29 System: - Severity: major Problem: Syntax for structure expressions includes strexp : sigexp (DSMLR, p.13). This isn't implemented. Comments: Fix: Test: Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1209 Title: casting polymorphic functions and abstract types Keywords: cast, polymorphism, abstract types Submitter: Chris Paris Date: 5/28/97 Version: 109.28 System: ? Severity: minor Problem: casting a polymorphic function causes a Compiler bug. A better error message should be generated. Transcript: - fun subst (f : 'a -> unit) = System.Unsafe.cast f (); Error: Compiler bug: Contract: UsageMap on 158 Comments: [Paris] I reworked some of my code, and I believe I have it working in 109.28 now. In response to a comp.lang.ml post I made a while ago, Zhong Shao suggested that the introduction of the FLINT code would change the behavior of the cast function, so that I get to write one evil thing instead of another. The "nicer" approach seems to work in 109.28, though I don't know why my earlier code broke between 27 and 28, since I thought that FLINT has been around for a while now. [Zhong] While FLINT has been around for a few months, it is changing almost every week :-) There are some major differences between 27 and 28, one is the default calling conventions for polymorphic functions --- the result is that it is no longer safe to directly cast a polymorphic function from "'a -> unit" into "unit -> unit". Future compilers will report such "unsafe" uses of cast. For the time being, the compiler does not bother, the CPS optimizer takes the code and complains about "Contract: UsageMap on 158". I'll try to get a fix into 109.29. [jhr] The example where I get this bug involves converting the type (char -> char) -> string -> string to (Word8.word -> Word8.word) -> Word8Vector.vector -> Word8Vector.vector No polymorphism is involved, and the representations of the two types should be the same. [Zhong] There is a bug in 109.28 on representation analysis of values with "abstract types". In this case, Word8Vector.vector is an abstract type created by :> in boot/built-in.sml. I'll try to fix this in 109.29. In general, care must be taken when creating new types using :>. For example, structure V :> sig eqtype vector val create : int -> vector end = struct type vector = string val create = Assembly.A.create_s end representation analysis would think V.vector has type TC_ABS (string) and process it in the same way as other abstract types (with same shapes but different type stamps). A better way to add built-in types such as word8vector is to directly add it into the initial Prim environment. There are no guarantees that values of type T and ABS(T) would have same representations (right now, T and ABS(T) would have same representations if T is "boxed" in a canonical way) Fix: same as fix for 1323? Test: bug1209.sml Owner: Zhong Status: fixed in 110.0.1 [Zhong, 1/7/98] ---------------------------------------------------------------------- Number: 1210 Title: weak pointers to strings cause SML to crash Keywords: weak pointers Submitter: Edo Biagioni, esb@cs.cmu.edu Date: 05/30/1997 Version: 109.27 System: DEC alpha Osf1 V3.2 Severity: minor Transcript: % /afs/cs.cm.edu/project/fox/port/109.27/bin/sml Standard ML of New Jersey, Version 109.27, April 20, 1997 [CM&CMB] val it = () : unit - val a = "foo"; val a = "foo" : string - val b = SMLofNJ.Weak.weak a; val b = - : string ?.weak - SMLofNJ.Internals.GC.doGC 0; GC #1.1.1.1.1.2: /afs/cs.cmu.edu/project/fox/port/109.27/bin/.run/run.alpha32x-osf1: Fatal error -- weak big object Comments: [jhr] Actually, this bug is weak pointers to big objects (aka, code). Heap allocated strings should work okay. This will be fixed when we go to the new array/vector representations. Fix: Test: Owner: jhr Status: open ---------------------------------------------------------------------- Number: 1211 Title: signature problems not reported until signature instantiation Keywords: modules, signatures, instantiation Submitter: Norman Ramsey Date: 5/30/97 Version: 109.28 System: - Severity: major Problem: I'm having trouble migrating my code to the new rules for sharing. The error message I get is: control.nw:94.9-94.44 Error: rigid type spec in sharing: item The source code prompting this message is: functor CodeBogus(Code : CODE) = struct end It would be more helpful if - the error message were issued when the CODE signature was compiled - the source locations referred to in the message contained the offending sharing constraint - the README file for 109.28 indicated what error message to expect when the new illegal constructs are used. This way I could correlate the error message with the potential problem. Comments: Fix: Need to instantiate signatures where they are declared to detect these errors at the appropriate point. This could be controlled by a flag that could turn off instantiation when recompiling debugged code. Test: Owner: dbm, Zhong Status: fixed in 109.30 [dbm] ---------------------------------------------------------------------- Number: 1212 Title: where structure when signatures differ Keywords: modules, where structure, SML97 Submitter: Norman Ramsey Date: 5/30/97 Version: 109.28 System: - Severity: major Problem: I am informed: elabexp.nw:32.9...53.4 Error: Inconsistent defining constraints : type item = item I introduced this error by replacing functor ElabExpFun (structure Denotable : DENOTABLE structure DoublePattern : DOUBLE_PATTERN sharing DoublePattern.Normal = Denotable.Pattern val simplify : Denotable.Constructor.Pattern.Exp.exp -> Denotable.Constructor.Pattern.Exp.exp ) : ELAB_EXP = struct ... end with functor ElabExpFun (structure Denotable : DENOTABLE structure DoublePattern : DOUBLE_PATTERN where structure Normal = Denotable.Pattern val simplify : Denotable.Constructor.Pattern.Exp.exp -> Denotable.Constructor.Pattern.Exp.exp ) : ELAB_EXP = struct ... end The replacement was necessary because the two structures have difference signatures and both signatures are full of 'rigid' type definitions (I've forgotten the proper term for these). I have no idea how to track down and diagnose this error. Some more source locations in the error message might help. Comments: Same as bug 1232. Fix: Test: Owner: dbm Status: fixed in 109.30 ---------------------------------------------------------------------- Number: 1213 Title: CM dependency analysis Keywords: CM, dependency Submitter: Andrew Kennedy Date: 6/3/97 Version: 109.28 System: - Severity: major Problem: I don't have sample code for this one; I'm hoping that my vague description will suffice. The situation is that a structure imports another structure but only by way of rebinding e.g. structure STR1 = struct structure STR2 = STR3 .... STR2.x ... end so that STR3 is never used in a qualified identifier. This seems to trick the compilation manager into thinking that STR3 is not referenced in STR1, leading to compilation errors such as "no such structure STR3". However, if one of the qualified identifiers (such as STR2.x above) is replaced by its synonym (STR3.x) then this fixes things. What's more, I can then change it back to STR2.x and the compilation manager seems to `remember' that STR1 referred to STR3. Comments: Fix: Test: Owner: Matthias Status: not reproducible [blume, 8/3/97] ---------------------------------------------------------------------- Number: 1214 Title: Increased make time Keywords: CM, memory usage Submitter: Emden R. Gansner, erg@research.att.com Date: Wed Jun 4 17:35:01 EDT 1997 Version: 109.28 System: Only tested on irix-mips Severity: minor Problem: There seems to be a dramatic increase in make time from 109.27 to 109.28 Code: Transcript: In 109.27, the entire process takes 20 secs and I get something like the following: [dependency analysis completed] GC #3.23.28.47.230.7259: (34 ms) GC #3.23.28.47.231.7305: (29 ms) GC #3.23.28.47.232.7343: (18 ms) GC #3.24.29.48.233.7406: (127 ms) GC #3.24.29.48.234.7455: (9 ms) GC #3.24.29.48.235.7523: (18 ms) GC #3.24.29.48.236.7581: (23 ms) GC #3.24.29.48.237.7657: (19 ms) GC #3.24.29.48.238.7735: (29 ms) [compiling bezier.sml -> CM/mipseb-unix/bezier.sml.bin] In 109.28, the entire process takes 60 secs and I get something like the following: [dependency analysis completed] GC #2.15.16.21.104.6631: (35 ms) GC #2.15.16.21.105.6741: (19 ms) GC #2.15.16.21.106.6841: (10 ms) GC #2.15.16.21.107.6955: (13 ms) GC #2.15.16.21.108.7097: (7 ms) GC #2.15.16.21.109.7242: (5 ms) GC #2.15.16.21.110.7341: (48 ms) GC #2.16.17.22.111.7408: (97 ms) GC #2.16.17.22.112.7417: (1 ms) GC #2.16.17.22.113.7453: (34 ms) GC #2.16.17.22.114.7520: (8 ms) GC #2.16.17.22.115.7586: (42 ms) GC #2.17.18.23.116.7728: (159 ms) GC #3.18.19.24.117.7774: (736 ms) GC #3.18.19.24.118.7816: (37 ms) GC #3.18.19.25.119.7887: (33 ms) GC #3.18.19.25.120.7968: (43 ms) GC #3.18.19.25.121.8107: (31 ms) GC #3.18.19.25.122.8258: (17 ms) GC #3.18.19.25.123.8389: (17 ms) [compiling bezier.sml -> CM/mipseb-unix/bezier.sml.bin] Comments: This was caused by supplying a context entityEnv when building a realization for a closed signature in modules/instantiate.sml. Fix: Test: Owner: dbm Status: fixed in 109.30 ---------------------------------------------------------------------- Number: 1215 Title: Unaligned access messages Keywords: reals, real arrays, alignment Submitter: George Russell Date: 4/3/97 Version: 109.26 System: alpha, OSF4.0 (& probably OSF3.2) Severity: major Problem: Following code produces lots and lots of "Unaligned access . . ." messages. Code: Array.tabulate(500,fn i=>RealArray.array(500,0.0)); Transcript: Comments: [Lal] This bug appears to be garbage collection related. Executing: Array.tabulate(100, fn i=>RealArray.array(500,0.0)); results in a large number of unaligned accesses. However, executing this under: sml @SMLalloc=10M works fine. [jhr, 7/31/97] This is the same as bug 1227, which is fixed in 109.30. Fix: Test: bug1215.sml Owner: Lal, jhr Status: fixed in 109.30 [jhr] ---------------------------------------------------------------------- Number: 1216 Title: curried higher-order functors not accepted Keywords: modules, functors, higher-order functors Submitter: Zhong Shao (shao@cs.yale.edu) Date: April 4, 1997 Version: 109.29 System: all platform Severity: minor Problem: curried higher-order functors not accepted Code: signature SIG = sig end functor F (A : SIG) (B : SIG) = struct end structure V = struct end structure X = F (struct end) (struct end) structure Y = F (structure A = V) (structure B = V); structure Z = F V V ; (* this one is problematic *) Transcript: - signature SIG = sig end functor F : structure V : sig end structure X : sig end structure Y : sig end - stdIn:94.23 Error: syntax error found at ID Comments: Probably this is not a bug. But I was never clear about the currying syntax for higher-order functors. Is the functor application "(F V V)" allowed ? [dbm] Not a bug. Parantheses are required around all functor arguments. Fix: Test: bug1216.sml Owner: dbm Status: not a bug ---------------------------------------------------------------------- Number: 1217 Title: Compiler generates exception [FPRegEA]. Keywords: code generation Submitter: ? Date: 5/1/97 Version: 109.27 System: x86-linux Severity: major Problem: Compiler generates exception [FPRegEA]. Code: val foo = fn x : 'a * 'b => [x] val bar = fn y => foo(y,13) Transcript: Standard ML of New Jersey, Version 109.27, April 20, 1997 [CM; autoload enabled] - val foo = fn x : 'a * 'b => [x] val bar = fn y => foo(y,13) ; uncaught exception in compiler: FPRegEA raised at: cps/generic.sml:98.67-98.74 util/stats.sml:164.40 util/stats.sml:164.40 build/evalloop.sml:191.58 Comments: For the polymorphic function 'foo', because 'x' is put in a list, representation analysis generates special code (governed by a runtime test) that coerces 'x' to its boxed representation if 'x' is a pair of floats. In the cps optimizer, because the call to 'foo' in 'bar' is known, it is inlined. Because the type of 'y' is unknown, the runtime test in 'foo' remains, and the special case code for floating points is not dead. However, the record '(y,13)' is known and the coercion code for floating point attempts to coerce this record to its boxed representation, which causes it to think that '13' can be put in a floating point register. The bug occurs if you attempt to batch compile ml-yacc (i.e. if you cat all the source files and compile as one declaration). Fix: This is speculative, but the representation analysis uses the following idiom, which is not type correct: Lambda alpha. lambda z:alpha. typecase alpha of float => _ => The idiom could be replaced by the following, which is type correct: Lambda alpha. typecase alpha of float => lambda z:float. _ => lambda z:alpha. Comment: [Lorenz, 5/1/97] For what it's worth, this bug appeared in the transition from 109.23 to 109.24, appears (at least) on x86-linux and sparc-solaris, but not on mipseb-unix. [Zhong, 5/1/97] Thanks for the bug report (and also suggestion the fix). This was really bug 1175 in the masterbug list. I have fixed it and will incorporate the fix into 109.28. Test: bug1217.sml Owner: Zhong Status: fixed in 109.28 [Zhong] ---------------------------------------------------------------------- Number: 1218 Title: increase in size of exportFn image Keywords: exportFn, image size Submitter: Nikolaj Bjorner Date: 5/1/97 Version: 109.27 System: ? Severity: major Problem: The size of the image that is exported with 109.27 is significantly higher than with for instance version 108. I made the following tests: Transcript: [108:] structure Test = struct fun dummy(_,[name]) = (print ("Hi I am "^name^"\n")) fun export() = exportFn("/step/sml-108/bin/.heap/hi",dummy) end [109.27:] structure Test = struct fun dummy(name,_) = (TextIO.print ("Hi I am "^name^"\n"); OS.Process.success) fun export() = SMLofNJ.exportFn("/step/sml/bin/.heap/hi",dummy) end The sizes of the exported images were: 108: -rw-rw---- 1 nikolaj 196292 May 1 22:42 hi 109.27 -rw-rw---- 1 nikolaj 500824 May 1 22:38 hi.sparc-solaris For larger executables the situation gets even worse. I reported an image size of more than 35 MB in 109.27 compared to approx 13 MB in 108. Comments: [Zhong, 5/2/97] This difference seems to be caused from changes in the runtime system, as even the image for a null function is about this big. fun export1() = SMLofNJ.exportFn("xxx1", dummy); fun export2() = SMLofNJ.exportFn("xxx2", fn _ => 0); -rw-r--r-- 1 shao systems 449616 May 2 09:38 xxx1.sparc-solaris -rw-r--r-- 1 shao systems 433232 May 2 10:55 xxx2.sparc-solaris I also checked the runtime closures for both the dummy function and the "fn _ => 0" function, they all contain minimum amount of free variables. |> For larger executables the situation gets even worse. I |> reported an image size of more than 35 MB in 109.27 compared |> to approx 13 MB in 108. |> |> Is there any way to improve on this situation? This could be caused by completely different reasons from the previous. Sorry for keeping asking this, but if you can ship us the entire source code, we can probably take a look and narrow the problem down for you. [Nikolaj, 5/20/97] A. -- I was asked if I could provide a more realistic example where the size of the exported image problem showed up in the 109 version. The example directory in eXene (the bricks example) appears to be excellent. With 108: -rw-rw---- 1 nikolaj 1490428 May 20 14:17 /step/sml-108/bin/.heap/bricks With 109.27: -rw-rw---- 1 nikolaj 12978676 May 20 14:21 /step/sml/bin/.heap/bricks.sparc-solaris As we can see, the size of the image is almost 10 times larger for this small eXene example. The size problem seems however not to be an artifact of eXene. I have exported images that are purely ML (that do not use CML) that are much larger than they should be. The fact that I am using an eXene demo is that it was the first and best example that I could find. B. -- I have previously reported problems with CM. I still think there is something fishy about CM. Some of the problems appear to arise when the same files are loaded using different .cm files. If person A has one cm file and person B has a different one that loads different files, and A and B both use SCCS they may see different versions of files that other files depend on. It is typically possible to hack around this so I have not been eager to clarify the source of the problems precisely. C. -- eXene/CML may have some problems running under Linux and over the network. We have just started to port our system to a laptop (IBM thinkpad 760 E). Here the Inbuf appears to die as well as IO exceptions are raised at will. Over the network (phone line) in Inbuf dies. Other applications (emacs,...) do not have these problems. ----------------------------------------------- Below follows the modifications I did to export the images (so you can reproduce it): 109: examples/bricks/sources.cm: Group is cml.cm cml-lib.cm ../../sources.cm util.sml brickview.sml brick.sml wall.sml badbricks.sml export.sml examples/bricks/export.sml: structure Export = struct val tq = Time.fromMilliseconds 20 fun main(name,display::args) = (RunCML.doit(fn ()=>BadBricks.badBricks display,SOME tq); OS.Process.success) fun export() = SMLofNJ.exportFn("/step/sml/bin/.heap/bricks",main) end ----------------------------------------------- 108: examples/bricks/sources.cm: (* sources file for triangle demo *) Group is /step/sml-108/lib/smlnj-lib.cm /step/sml-108/lib/cml.cm /step/sml-108/lib/cml-lib.cm ../../sources.cm util.sml brickview.sml brick.sml wall.sml badbricks.sml export.sml examples/bricks/export.sml: structure Export = struct fun main(env,display::args) = BadBricks.badBricks display fun export() = RunCML.exportFn("/step/sml-108/bin/.heap/bricks",main,SOME 20) end examples/bricks/brickview.sml: This does not compile under 108, so I corrected it with parts from 109. Replaced: fun showText (backc, framec) txt _ = ( Label.setBackground label backc; Label.setLabel label (Label.Text txt); Frame.setColor frame framec; framec) val showView = showText (#concrete palette, SOME(#lightLines palette)) val endView = showText (#brick palette, SOME(#lightLines palette)) val markView = showText (#mark palette, SOME(#darkLines palette)) "ok" val normView = showText (#brick palette, SOME(#darkLines palette)) "" examples/bricks/wall.sml: This does not compile under 108, so I corrected it with parts from 109. Replaced: fun setMsg txt = Label.setLabel msgArea (Label.Text txt) [Zhong, 5/21/97] Hi, Nikolaj, Thanks very much for narrowing down the problem for us. I can reproduce the image size using the following export.sml: structure Export = struct fun export() = SMLofNJ.exportFn("bricks", fn _ => (RunCML.doit (fn () => (), NONE); 0)) end There are definitely wierd thing going on with exportFn. As if I use the following sources.cm file: Group is cml.cm cml-lib.cm ../../sources.cm util.sml brickview.sml brick.sml wall.sml badbricks.sml export.sml I get 12Mbytes image, while if I use this sources.cm file: Group is cml.cm cml-lib.cm export.sml I get only 8.2Mbytes. Even though export.sml does not refer to anything in eXene or brick code at all. Clearly, the closure for RunCML.doit function contains a pointer to all the toplevel environments. Even worse, I am afraid that it contains a pointer to the top-level environment (where code for bricks and eXene stays). This bug occurs also in version 109.16 (with probably 1.2 Mbytes smaller image size, which is the image size difference between sml-cm-109.16 and sml-cm-109.27). John, what are the main differences between 108's RunCML.doit and 109.16's RunCML.doit ? Would the new code possibly hold more free variables ? |> The size problem seems however not to be an artifact of eXene. |> I have exported images that are purely ML (that do not use CML) |> that are much larger than they should be. The fact that I am using |> an eXene demo is that it was the first and best example that I could find. It is possible that the image-size problems for these purely-ML code are caused by different reasons (from the brick example above). We'll continue diagnosing the problem, at the same time, we would very appreciate you send us new (purely-ML) examples if you happen to run into any of them in the future. [Bjorner, 8/7/97] The recent bugfixes in version 109.30 offered some hopes that the heap size bug has been fixed. This appears not to be the case: -rw-rw---- 1 root 14293696 Aug 7 08:38 bricks.sparc-solaris is the 109.30 size of the bricks exported image. Compared with previous sizes this is a clear worsening. [Bjorner, 8/7/97] I have previously communicated with various members of the SML/NJ team on the memory problems in versions 109.**. Desparately trying to track the problem down further in 109.30 (it is really a serious problem for us and others who wish to use SML/NJ images on reasonable hardware) I ran into the following simple scenario that can recreate some weird memory behaviour. I am still a bit frustrated that I am don't have an overview of the source code of SML/NJ which could allow me to track the problem in a more systematic way. What are the documents describing the design of the present compiler? Regards Nikolaj --------------------------------------------- sources.cm: Group is (** (* C *) cml.cm cml-lib.cm **) export.sml -------------------- structure Export = struct val tq = Time.fromMilliseconds 20 fun main(name,display::args) = (** (* A *) (TextIO.print "dummy"; OS.Process.success) **) (** (* B *) (RunCML.doit(fn ()=>(),SOME tq); OS.Process.success) **) fun export() = SMLofNJ.exportFn("dummy",main) end -------------------- 1. To obtain an image of with 318 big objects (9 MB!) uncomment C and B. 2. Then comment B, and uncomment A. This still gives the same image size. 3. Then comment C. This gives 38 big objects, about 0.5 MB (nice and "small"). 4. Then uncomment C. This still gives only 38 big objects, different than point 2 although the CM.sa files look exactly the same! It has been listed below. To narrow the source of the problems down further it should also be possible to recreate the situation with the reference to cml-lib.cm deleted from the sources.cm. This already seems to follow from the CM.sa generate file below. Even when replacing C by: /sml-109.30/src/cml/src/Unix/sources.cm in step 2 I get the 9 MB large image size. In comparison when compiling the following under version 108 I only get 22 big objects ( 0.3 MB). This is the 108 equivalent of step 1 above. sources.cm ---------- Group is /sml-108/lib/cml.cm export.sml export.sml ---------- structure Export = struct val tq = Time.fromMilliseconds 20 fun main(name,display::args) = (RunCML.doit(fn ()=>(),SOME 20);()) fun export() = exportFn("dummy",main) end ------------------------------------------------------ CM.sa for step 1,2,3,4: local open Compiler.CMSA val pervenv = pervenv () val o1 = run ("/step/sml-109.30/src/cml/src/core-cml/rep-types.sml", pervenv) val d0 = layer [o1, pervenv] val o2 = run ("/step/sml-109.30/src/cml/src/core-cml/queue.sml", d0) val o3 = run ("/step/sml-109.30/src/cml/src/core-cml/debug.sml", pervenv) val d1 = layer [o1, o2, o3, pervenv] val o4 = run ("/step/sml-109.30/src/cml/src/core-cml/scheduler.sml", d1) val o5 = run ("/step/sml-109.30/src/cml/src/core-cml/event-sig.sml", pervenv) val d2 = layer [o1, o4, o5, pervenv] val o6 = run ("/step/sml-109.30/src/cml/src/core-cml/event.sml", d2) val d3 = layer [o6, pervenv] val o21 = run ("/step/sml-109.30/src/cml/src/OS/os-io-sig.sml", d3) val o22 = run ("/step/sml-109.30/src/cml/src/OS/os-process-sig.sml", d3) val d4 = layer [o21, o22, pervenv] val o23 = run ("/step/sml-109.30/src/cml/src/OS/os-sig.sml", d4) val d5 = layer [o21, o22, o23, pervenv] val o24 = run ("/step/sml-109.30/src/cml/src/OS/os-signatures.sml", d5) val f0 = filter [SIG "OS", SIG "OS_IO", SIG "OS_PROCESS"] val d6 = f0 o24 val d7 = layer [o1, o4, o6, pervenv] val o13 = run ("/step/sml-109.30/src/cml/src/core-cml/io-manager.sml", d7) val o0 = run ("/step/sml-109.30/src/cml/src/core-cml/version.sml", pervenv) val o7 = run ("/step/sml-109.30/src/cml/src/core-cml/thread-sig.sml", pervenv) val d8 = layer [o1, o4, o6, o7, pervenv] val o8 = run ("/step/sml-109.30/src/cml/src/core-cml/thread.sml", d8) val o9 = run ("/step/sml-109.30/src/cml/src/core-cml/channel-sig.sml", pervenv) val d9 = layer [o1, o2, o4, o6, o8, o9, pervenv] val o10 = run ("/step/sml-109.30/src/cml/src/core-cml/channel.sml", d9) val o11 = run ("/step/sml-109.30/src/cml/src/core-cml/timeout-sig.sml", pervenv) val d10 = layer [o1, o4, o6, o11, pervenv] val o12 = run ("/step/sml-109.30/src/cml/src/core-cml/timeout.sml", d10) val d11 = layer [o5, o7, o9, o11, pervenv] val o14 = run ("/step/sml-109.30/src/cml/src/core-cml/cml-sig.sml", d11) val d12 = layer [o0, o6, o8, o10, o12, o14, pervenv] val o15 = run ("/step/sml-109.30/src/cml/src/core-cml/cml.sml", d12) val d13 = layer [o13, o15, d6, pervenv] val o25 = run ("/step/sml-109.30/src/cml/src/Unix/os-io.sml", d13) val f1 = filter [SIG "OS", STR "OS_Process", SIG "OS_IO", STR "OS_IO", SIG "OS_PROCESS", STR "ProcManager"] val d14 = f1 o25 val d15 = layer [o15, pervenv] val o16 = run ("/step/sml-109.30/src/cml/src/core-cml/sync-var-sig.sml", d15) val d16 = layer [o1, o2, o4, o16, pervenv] val o17 = run ("/step/sml-109.30/src/cml/src/core-cml/sync-var.sml", d16) val d17 = layer [o15, o17, pervenv] val o20 = run ("/step/sml-109.30/src/cml/src/util/result.sml", d17) val d18 = layer [o4, o6, o20, pervenv] val o26 = run ("/step/sml-109.30/src/cml/src/Unix/proc-manager.sml", d18) val d19 = layer [o26, o4, o6, d6, pervenv] val o27 = run ("/step/sml-109.30/src/cml/src/Unix/os-process.sml", d19) val d20 = f1 o27 val d21 = layer [d6, d14, d20, pervenv] val o45 = run ("/step/sml-109.30/src/cml/src/Unix/os.sml", d21) val f2 = filter [STR "OS", SIG "UNIX", STR "Unix", STR "TextPrimIO", STR "BinPrimIO", SIG "OS_IO", STR "BinIO", STR "RunCML", SIG "OS_PROCESS", STR "TextIO"] val d22 = f2 o45 val o32 = run ("/step/sml-109.30/src/cml/src/IO/prim-io-sig.sml", d15) val d23 = layer [o32, o15, pervenv] val o36 = run ("/step/sml-109.30/src/cml/src/IO/prim-io-fn.sml", d23) val d24 = layer [o36, pervenv] val o39 = run ("/step/sml-109.30/src/cml/src/IO/text-prim-io.sml", d24) val o34 = run ("/step/sml-109.30/src/cml/src/IO/cml-text-stream-io-sig.sml", d15) val d25 = layer [o34, o39, o15, pervenv] val o40 = run ("/step/sml-109.30/src/cml/src/IO/cml-text-io-sig.sml", d25) val d26 = layer [o32, pervenv] val o41 = run ("/step/sml-109.30/src/cml/src/IO/os-prim-io-sig.sml", d26) val o18 = run ("/step/sml-109.30/src/cml/src/core-cml/mailbox-sig.sml", d3) val d27 = layer [o1, o4, o18, pervenv] val o19 = run ("/step/sml-109.30/src/cml/src/core-cml/mailbox.sml", d27) val d28 = layer [o32, o15, o17, o19, pervenv] val o43 = run ("/step/sml-109.30/src/cml/src/IO/chan-io-fn.sml", d28) val d29 = layer [o39, o40, o41, o43, o15, o17, pervenv] val o44 = run ("/step/sml-109.30/src/cml/src/IO/text-io-fn.sml", d29) val o37 = run ("/step/sml-109.30/src/cml/src/IO/bin-prim-io.sml", d24) val d30 = layer [o45, o4, pervenv] val o46 = run ("/step/sml-109.30/src/cml/src/Unix/syscall.sml", d30) val d31 = layer [o45, o46, o13, o15, o17, o37, o41, pervenv] val o47 = run ("/step/sml-109.30/src/cml/src/Unix/posix-bin-prim-io.sml", d31) val d32 = layer [o47, o15, o17, o39, o41, pervenv] val o49 = run ("/step/sml-109.30/src/cml/src/Unix/posix-text-prim-io.sml", d32) val d33 = layer [o49, o44, pervenv] val o50 = run ("/step/sml-109.30/src/cml/src/Unix/posix-text-io.sml", d33) val d34 = f2 o50 val d35 = layer [d22, d34, pervenv] val o153 = run ("export.sml", d35) in val _ = register o153 end Fix: Optimization to lift structure references out of closures restored (it had been dropped in 109.24). Isolate function fixed. CML version of exportFn cleaned up. Test: Owner: Zhong, jhr Status: fixed in 109.31 [jhr, Zhong, 9/15/97] ---------------------------------------------------------------------- Number: 1219 Title: sml crashes while trying to print Keywords: printing, representations Submitter: Chris Paris Date: 5/5/97 Version: 109.27 System: sparc/solaris 5.5, mipseb Severity: major Problem: Printing datatype values involving ints and words causes segmentation faults. Transcript: Standard ML of New Jersey, Version 109.27, April 20, 1997 [CM; autoload enabled] - datatype id = ID of Int32.int; datatype id = ID of int32 - ID (Int32.fromInt 0); Segmentation fault Standard ML of New Jersey, Version 109.27, April 20, 1997 [CM; autoload enabled] - datatype id = ID of int32; datatype id = ID of int32 - ID (0 : int32); Segmentation fault Standard ML of New Jersey, Version 109.27, April 20, 1997 [CM; autoload enabled] - datatype id = ID of Word32.word; datatype id = ID of word32 - ID (Word32.fromInt 0); Segmentation fault Comments: Fix: Test: bug1219.sml Owner: Zhong Status: fixed ---------------------------------------------------------------------- Number: 1220 Title: type definition masks datatype Keywords: modules, signature matching, datatypes Submitter: Zhong Shao Date: 5/7/97 Version: 109.29 System: - Severity: minor Problem: Is the following legal sml ? structure A : sig datatype t = HT end = struct datatype t = HT type t = t end Our compiler complains that z2.sml:1.1-4.6 Error: type t must be a datatype z2.sml:1.1-4.6 Error: unmatched type specification: t uncaught exception Error raised at: build/evalloop.sml:103.44-103.52 build/evalloop.sml:120.38 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 Changing it to the following works as expected: structure A : sig datatype t = HT end = struct datatype t = HT datatype t = datatype t end Code: Transcript: Comments: Check whether this is legal. Fix: Test: Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1221 Title: type inference of literals is quirky Keywords: type inference, literals Submitter: Perry Cheng; pscheng@cs.cmu.edu Date: 5/9/97 Version: 109.25, 109.29 System: alpha DEC UNIX 3.2 Severity: minor Problem: The type of word literals seems to fail when they occur in top-level bindings inside a structure. Transcript: - let val ten = 0w10 val y = Word32.div(ten,ten) in y end; val it = 0wx1 : Word32.word - structure X = struct val ten = 0w10 val y = Word32.div(ten,ten) end; stdIn:270.21-277.4 Error: operator and operand don't agree (tycon mismatch) operator domain: Word32.word * Word32.word operand: word * word in expression: Word32.div (ten,ten) Comments: This is not a bug because of the way literal overloading is resolved in let expressions vs within structures. The overloading is resolved at each structure element declaration, meaing that the type of ten in structure X will default to Word.word, not Word32.word. In the let expression the resolution of the type of ten is not done until after the body is typed. Fix: Test: bug1221.sml Owner: dbm Status: not a bug ---------------------------------------------------------------------- Number: 1222 Title: ref assignment not performed before overflow Keywords: Submitter: Lorenz Huelsbergen (lorenz@research.bell-labs.com) Date: 5/27/97 Version: 109.28 System: mipseb-irix5 (but not sparc-solaris) Severity: major Problem: ref assignment not performed before overflow Code: val x = ref 0; fun f n : unit = (x := !x + 1; f (n+1)); f (valOf Int.maxInt); x; (* should be 1 *) Transcript: - : canna.research.bell-labs.com 178; Standard ML of New Jersey, Version 109.28, May 23, 1997 [new runtime] - val x = ref 0; val x = ref 0 : int ref - fun f n : unit = (x := !x + 1; f (n+1)); = = val f = fn : int -> unit - ; - f (valOf Int.maxInt); uncaught exception Overflow [overflow] - x; (* should be 1 *) val it = ref 0 : int ref - Comments: Appears to be work properly on sparc. Fix: The problem is caused by the following CPS fragment generated by unrolling f a couple of times: f772(v785[I],v784[PV]) = !(v784) -> v698[PV] .. 1 +i31(v698,(I)1) -> v710[I] .. 2 unboxedupdate(v784,(I)0,v710) .. 3 +i31(v785,(I)1) -> v740[I] .. 4 !(v784) -> v758[PV] .. 5 +i31(v758,(I)1) -> v759[I] .. 6 unboxedupdate(v784,(I)0,v759) .. 7 +i31(v740,(I)1) -> v760[I] .. 8 (L)f772(v760,v784) .. 9 In mips/mipsdepend.sml the use/def information associated with trapping add is given by: fun arith_ud(rd,rs,ea) = (exnptr::(reg rs @ arithOpndUse ea), reg rd) The problem with this, is that there is no dependence of any kind with memory. Thus there is nothing preventing (trapping) instruction 4 from being scheduled before 3. [I cannot believe that we haven't tripped this bug earlier.] It doesn't matter what kind of dependency is introduced so I think I prefer to create a regular data dependency and define arith_ud as: fun arith_ud(rd,rs,ea) = (mem::exnptr::(reg rs @ arithOpndUse ea), reg rd) This essentially says that the trapping instruction will use memory on a trap. A similar consideration should be made with arith3_ud and mult_ud. -- Lal Test: Owner: Status: fixed in 109.31 [Lal, 8/18/97] ---------------------------------------------------------------------- Number: 1223 Title: Compiler bug: ModuleUtil: strId after unbound structure in functor Keywords: modules, unbound identifier, secondary error Submitter: Chris Paris (cap@cs.cmu.edu) Date: 6/15/97 Version: 109.29 System: - Severity: minor Problem: Unbound structure identifier in a functor body leads to "Compiler bug: ModuleUtil: strId". Code: functor A () = struct structure B = B end; Transcript: Standard ML of New Jersey, Version 109.29, June 13, 1997 [CM; autoload enabled] - functor A () = struct structure B = B end; stdIn:17.37 Error: unbound structure: B Error: Compiler bug: ModuleUtil: strId Comments: Fix: Test: bug1223.sml Owner: Zhong Status: fixed in 109.31 [Zhong, 8/14/97] ---------------------------------------------------------------------- Number: 1224 Title: representation foulup Keywords: data representation Submitter: Chris Paris Date: 6/15/97 Version: 109.28? System: ? Severity: major Problem: Execution gives wrong answers or core dumps. Code: structure T = struct datatype 'a pref = PREF of {obj : 'a} fun apply (PREF {obj}, arg) = obj arg fun f ((x, y), z) = y fun s () = apply (PREF {obj=f}, (("one", "two"), "three")) fun t () = apply (PREF {obj=f}, (("one", "two"), ())) end; T.s(); T.t(); Transcript: - T.s(); val it = "three" : string (* should be "two" *) - T.t(); Bus error (* tries to print a unit as a string? *) Comments: [Paris] Something interesting happens if I change the definition of f to fun f ((x, y), z) = x Then we get - T.s(); val it = "\238\160\145\224\238\160\145\208\238\1335X\238\^Q\218\244\238\147 0\000\000\^A\219\000\000\000\^A\238\029\231\^H\000\000\000\^E\238\029\231\^P\238\029\231\^X\238\029\231 \000\000\000\^E\238\029\231(\000\000\000\^E\238\029\2310\238\178\250\192\000\000#" : string And if f is fun f ((x, y), z) = z, then the file doesn't compile: - use "test.sml"; [opening test.sml] uncaught exception Lookup raised at: cps/nclosure.sml:384.49-384.62 util/stats.sml:164.40 util/stats.sml:164.40 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 Fix: Test: bug1224.sml Owner: Zhong Status: fixed in 109.30 [Zhong] ---------------------------------------------------------------------- Number: 1225 Title: SMLofNJ.Internals.GC.doGC doesn't work Keywords: garbage collection, runtime Submitter: Christoph Kern Date: 06/18/97 Version: Version 109.28, May 23, 1997 System: sparc-solaris (probably any) Severity: minor Problem: SMLofNJ.Internals.GC.doGC x doesn't cause a collection, regardless of the value of x. Fix: --- src/runtime/c-libs/smlnj-runtime/gc-ctl.c.orig Wed Jun 18 14:11:03 1997 +++ src/runtime/c-libs/smlnj-runtime/gc-ctl.c Wed Jun 18 14:12:51 1997 @@ -86,7 +86,7 @@ PVT void DoGC (ml_state_t *msp, ml_val_t arg) { heap_t *heap = msp->ml_heap; - int level = INT_MLtoC(arg); + int level = INT_MLtoC(DEREF(arg)); if (level < 0) level = 0; Comment [jhr] I think you are right. What is happening is that the ref cell's address is a negative number on the sparc, but is a (large) positive number on the SGI. When you call doGC, it only does a minor collection, whereas, when I call it, it always collects all generations. I've applied your patch, and it will be in 109.30. Thanks. Test: * Owner: jhr Status: fixed in 109.30 ---------------------------------------------------------------------- Number: 1226 Title: Ctrl-C no longer works on Alpha Keywords: signals, interrupt Submitter: Andrew.Kennedy@persimmon.co.uk Date: 6/17/97 Version: 109.29 System: Alpha Severity: critical Problem: Ctrl-C does not interrupt compilation or execution Comments: [George Russell , 6/23/97] This is more about a problem reported by Andrew Kennedy, that SML109.29 on Digital Unix 4 does not respond to /C. I can now report that it also does not respond to kill -2 [process id] (IE sending SIGINT to it). However SML109.29 on Digital Unix 3.2, and SML109.28 on Digital Unix 4, both do respond to kill -2. [jhr, 6/23/97] We have not been able to reproduce these problems on our Unix 4.0 Alpha, so we will need your help in tracking this down. Please try the following experiment: cd src/runtime/objs make -f mk.alpha32-dunix BASE_DEFS="-DSIGNAL_DEBUG" run.alpha32-dunix @SMLload=../../../bin/.heap/sml (* and then try your ^C at the SML prompt *) Another thing to try (you might do this first) is typing Signals.inqHandler Signals.sigINT; at the prompt. This should return val it = HANDLER fn : sig_action Let me know what you find out. [jhr, 6/23/97] In message <33AE614D.41C6@persimmon.co.uk>, George Russell writes: > > Test #1 - Ctrl/C does nothing. I'll keep this SML session going in > case there's anything else you want me to try. > > Test #2 yields > val it = IGNORE : sig_action > !! > But for 109.28 and 109.29 on 3.2 it does what you say it should do. Then the explanation is quite simple. When SML starts up, it checks the status of signals that it inherits from its parent process; if the status is SIGING, then it doesn't install a handler. This behavior is necessary to get sml to work properly as a background process (or under nohup). Why you see different behavior between 109.28 and 109.29, I have no idea, but I think that the problem is in your shell environment. [jhr, 7/14/97] not a bug --- sml was built in a non interactive shell. Owner: jhr, Lal Status: not a bug ---------------------------------------------------------------------- Number: 1227 Title: Unaligned access generated from floating-point arrays Keywords: arrays, reals Submitter: Perry Cheng (pscheng@cs.cmu.edu) Date: 6/26/97 Version: 109.28 System: Alpha OSF/1 3.2 Severity: major Problem: Floating point array manipulations cause unaligned accesses. Code: The following program computes FFTs at sizes 16, 32, ..., 65536. The code comes from a CAML-Lite distribution. local val sin = Real.Math.sin val cos = Real.Math.cos open Array fun abs_real(x:real) = if x < 0.0 then ~x else x fun print_real (x:real) = print(Real.toString x) (* $Id: bugs.1201-1400 1314 2003-03-20 23:09:51Z macqueen $ *) val pi = 3.14159265358979323846 val tpi = 2.0 * pi fun for(start,stop,f) = let fun loop i = if i > stop then () else (f i; loop (i+1)) in loop start end val print_string : string -> unit = print val print_int : int -> unit = print_string o Int.toString val print_newline : unit -> unit = fn _ => print_string "\n" fun dump pxr pxi = for(0,15,fn i => (print_int i; print " "; print_real (sub(pxr,i+1)); print " "; print_real (sub(pxi,i+1)); print_newline())) fun fft px py np = let val i = ref 2 val m = ref 1 val _ = while (!i < np) do (i := !i + !i; m := !m + 1) val n = !i in if n <> np then ( for (np+1,n,fn i=> (update(px,i,0.0); update(py,i,0.0))); print_string "Use "; print_int n; print_string " point fft"; print_newline() ) else (); let val n2 = ref(n+n) in for(1,!m-1,fn k => let val _ = n2 := !n2 div 2 val n4 = !n2 div 4 val e = tpi / (real (!n2 )) in for(1,n4,fn j => let val a = e * real(j - 1) val a3 = 3.0 * a val cc1 = cos(a) val ss1 = sin(a) val cc3 = cos(a3) val ss3 = sin(a3) val is = ref j val id = ref(2 * !n2) in while !is < n do let val i0r = ref (!is) in while !i0r < n do let val i0 = !i0r val i1 = i0 + n4 val i2 = i1 + n4 val i3 = i2 + n4 val r1 = sub(px,i0) - sub(px,i2) val _ = update(px,i0,sub(px,i0) + sub(px,i2)) val r2 = sub(px,i1) - sub(px,i3) val _ = update(px,i1,sub(px,i1) + sub(px,i3)) val s1 = sub(py,i0) - sub(py,i2) val _ = update(py,i0,sub(py,i0) + sub(py,i2)) val s2 = sub(py,i1) - sub(py,i3) val _ = update(py,i1,sub(py,i1) + sub(py,i3)) val s3 = r1 - s2 val r1 = r1 + s2 val s2 = r2 - s1 val r2 = r2 + s1 in update(px,i2,r1*cc1 - s2*ss1); update(py,i2,~s2*cc1 - r1*ss1); update(px,i3,s3*cc3 + r2*ss3); update(py,i3,r2*cc3 - s3*ss3); i0r := i0 + !id end; is := 2 * !id - !n2 + j; id := 4 * !id (* ; dump px py *) end end) end) end; (************************************) (* Last stage, length=2 butterfly *) (************************************) let val is = ref 1 val id = ref 4 in while !is < n do let val i0r = ref (!is) in while !i0r <= n do let val i0 = !i0r val i1 = i0 + 1 val r1 = sub(px,i0) val _ = update(px,i0,r1 + sub(px,i1)) val _ = update(px,i1,r1 - sub(px,i1)) val r1 = sub(py,i0) in update(py,i0,r1 + sub(py,i1)); update(py,i1,r1 - sub(py,i1)); i0r := i0 + !id end; is := 2 * !id - 1; id := 4 * !id end end; (* print "\nbutterfly\n"; dump px py; *) (*************************) (* Bit reverse counter *) (*************************) let val j = ref 1 in for (1,n-1,fn i => (if i < !j then ( let val xt1 = sub(px,!j) val xt2 = sub(px,i) val _ = update(px,!j,xt2) val _ = update(px,i,xt1) val yt1 = sub(py,!j) val yt2 = sub(py,i) in update(py,!j,yt2); update(py,i,yt1) end) else (); let val k = ref(n div 2) in while !k < !j do (j := !j - !k; k := !k div 2); j := !j + !k end)); (* print "\nbit reverse\n"; dump px py; *) n end end; fun test np = (print_int np; print_string "... "; let val enp = real np val npm = np div 2 - 1 val pxr = array ((np+2), 0.0) val pxi = array ((np+2), 0.0) val t = pi / enp val _ = update(pxr,1,(enp - 1.0) * 0.5) val _ = update(pxi,1,0.0) val n2 = np div 2 val _ = update(pxr,n2+1,~0.5) val _ = update(pxi,n2+1,0.0) in for (1,npm,fn i => let val j = np - i val _ = update(pxr,i+1,~0.5) val _ = update(pxr,j+1,~0.5) val z = t * (real i) val y = ~0.5 * (cos(z)/sin(z)) in update(pxi,i+1,y); update(pxi,j+1,~y) end); (* print "\n"; print "before fft: \n"; dump pxr pxi; *) fft pxr pxi np; (* print "\n"; print "after fft: \n"; dump pxr pxi; *) let val zr = ref 0.0 val zi = ref 0.0 val kr = ref 0 val ki = ref 0 in for (0,np-1,fn i => let val a = abs_real(sub(pxr,i+1) - (real i)) in if !zr < a then (zr := a; kr := i) else (); let val a = abs_real(sub(pxi,i+1)) in if !zi < a then (zi := a; ki := i) else () end end); let val zm = if abs_real (!zr) < abs_real (!zi) then !zi else !zr in print_real zm; print_newline() end end end) fun doit() = let val np = ref 16 in for(1,13,fn i => (test (!np); np := (!np)*2)) end in val _ = doit() end Transcript: Standard ML of New Jersey, Version 109.28, May 23, 1997 [CM&CMB] val it = () : unit - use "/afs/cs/user/pscheng/bug.sml"; [opening /afs/cs/user/pscheng/bug.sml] GC #0.0.0.0.1.6: (10 ms) GC #0.0.0.0.2.24: (14 ms) GC #0.0.0.1.3.40: (23 ms) GC #0.0.0.1.4.51: (16 ms) GC #0.0.1.2.5.60: (55 ms) GC #0.0.1.3.6.96: (12 ms) GC #0.0.1.3.7.120: (23 ms) 16... 8.881784197e~16 32... 3.5527136788e~15 64... 1.06581410364e~14 128... 2.84217094304e~14 256... 5.68434188608e~14 512... 1.16795462191e~13 1024... GC #0.0.1.4.8.130: (1 ms) Unaligned access pid=1001 va=31c205c pc=2b439f4 ra=2b43994 type=stt Unaligned access pid=1001 va=31c2064 pc=2b43a28 ra=ffffffffffffffff type=stt Unaligned access pid=1001 va=31c206c pc=2b439f4 ra=ffffffffffffffff type=stt Unaligned access pid=1001 va=31c2074 pc=2b43a28 ra=ffffffffffffffff type=stt Unaligned access pid=1001 va=31c207c pc=2b439f4 ra=ffffffffffffffff type=stt Unaligned access pid=1001 va=31c2084 pc=2b43a28 ra=ffffffffffffffff type=stt Unaligned access pid=1001 va=31c208c pc=2b439f4 ra=ffffffffffffffff type=stt Comments: This works correctly in 109.25. [Zhong, 6/26/97] This seems to be an Alpha-specific bug, as the above code work fine on my SPARC. Do we align all floating-point numbers on Alpha ? [jhr, 6/26/97] I suspect that it must be a bug in the code generator. The run-time system and garbage collector aligns all real and real array objects on 64-bit boundries on all machines. BTW, I hope this code is not being used for benchmarking. It uses int refs to do iteration, instead of the more natural (and more efficient) tail recursive form. [Lal, 6/29/97] The bug is in the runtime system, in the routine runtime/gc/ml-object.c:ML_AllocRealdarray. If garbage collection is invoked there is no guarantee that the next word in the STRING arena is properly aligned. ------ ml_val_t ML_AllocRealdarray (ml_state_t *msp, int len) { int nwords = DOUBLES_TO_WORDS(len); if (nwords > SMALL_OBJ_SZW) { arena_t *ap = msp->ml_heap->gen[0]->arena[STRING_INDX]; BEGIN_CRITICAL_SECT(MP_GCGenLock) #ifdef ALIGN_REALDS /* Force REALD_SZB alignment (descriptor is off by one word) */ ap->nextw = (ml_val_t *)((Addr_t)(ap->nextw) | WORD_SZB); #endif IFGC (ap, (WORD_SZB*(nwords + 1))+msp->ml_heap->allocSzB) { /* we need to do a GC */ ap->reqSizeB += WORD_SZB*(nwords + 1); RELEASE_LOCK(MP_GCGenLock); InvokeGC (msp, 1); ACQUIRE_LOCK(MP_GCGenLock); } *(ap->nextw++) = desc; <<<<<< not aligned. res = PTR_CtoML(ap->nextw); ap->nextw += nwords; ---- A crude fix to get you going is to replicate the #ifdef ALIGN_REALDS ... #endif just before the line containing: *(ap->nextw++) = desc; <<<<<< not aligned. p.s. This bug manifested on the HPPA, and this fix solved the problem. I have not tested this on the alpha, so please let me know if it works on the alpha as well. Thanks. Fix: Test: Owner: Lal, jhr Status: fixed in 109.30 ---------------------------------------------------------------------- Number: 1228 Title: various Real functions on Alpha Keywords: Floating point, Real Submitter: Andrew.Kennedy@persimmon.co.uk, George Russell Date: 7/7/97 Version: 109.29 System: Alpha, OSF 4.0 Severity: Minor Problem: 1. Real.ceil and Real.floor cause segmentation fault on reals whose integer equivalent is out of range 2. Real.signBit (~0.0); returns false on both Alpha/OSF 4.0 and Linux/i386. 3. Real.fromManExp{exp=0,man=1.5}; causes SML/NJ 109.29 to hang forever (well, 8 GCs so far and counting) on Alpha/Digital Unix 4 and i686/Linux 4. Real.toManExp(1.0); returns {exp=0,man=1.0} for both Alpha/Digital Unix 4.0 and Linux/i686. However by my version of the standard this is wrong because we should have 0.5<=man<1.0. The correct answer is {exp=1,man=0.5}. The local version of frexp gets this right, incidentally. 5. Real.isNormal 0.0 ought to return false. Code: Real.floor 1073741824.0 Transcript: Comments: [Kennedy] NB Real.ceil 1073741823.1 correctly raises Overflow [jhr, 7/7/97] > Real.signBit (~0.0); > returns false on both Alpha/OSF 4.0 and Linux/i386. Actually, this is a feature of the IEEE 754-1985 specification. The negation of zero is negative zero, only when the rounding mode is set to TO_NEGINF. I don't know if the SML specification says anything about how the literal ~0.0 should be interpreted (is it the same as Real.~(0.0) in default rounding mode)? [appel, 9/17/97] No, this is not true. The IEEE specification calls for the negation of 0.0 to be ~0.0 regardless of rounding mode. [jhr, 7/7/97] I've tried the various FP bugs on canna, and here is some more info: 1) The Real.floor and Real.ceil of 1073741824.0 work correctly. This is probably a bug in the assembly code for floor. 2) Real.signBit(~0.0) returns false, but Real.signBit(0.0/ ~1.0) returns true. This is probably not a bug, but a feature of the IEEE specification. 3) Real.fromManExp{exp=0,man=1.5} goes to lunch on the MIPS too. I suspect this is a bug in the Real.fromManExp function (written by Andrew, I think). Fix: [for which part?] [Lal, 7/7/97] Thanks for the bug report. In the file src/runtime/mach-dep/ALPHA32-prim.asm there are two labels called floor_overflow that require a trapb instruction at the end. The first floor_overflow label should look like: floor_overflow: ldl ATMP1, ovfl_MAXINT addlv ATMP1, ATMP1, ATMP1 trapb and the second should look like: floor_overflow: addq $30, 16, $30 ldl ATMP1, ovfl_MAXINT addlv ATMP1, ATMP1, ATMP1 trapb The stack deallocation must be added to the second label as well. Making this change and recompiling the runtime system fixes this problem. Test: * Owner: jhr, Lal Status: fixed in 109.31 [Lal, Andrew] ---------------------------------------------------------------------- Number: 1229 Title: Bugs in unionWith, unionWithi of smlnj-lib Keywords: smlnj-lib, binary-set-map Submitter: Yasuhiko Minamide, nan@kurims.kyoto-u.ac.jp Date: 7/11/1997 Version: 109.29 System: any Severity: minor Problem: The behaviour of unionWith and unionWithi of smlnj-lib seems wrong. Code: let open IntBinaryMap val x = insert (insert (empty, 1,1), 2, 2) val y = insert (empty, 1, 0) val z = unionWith (fn (x,y) => x) (x, y) in listItemsi z end Transcript: The code above returns val it = [(1,0),(2,2)] : (int * int) list I think that this should be val it = [(1,1),(2,2)] : (int * int) list Test: * Owner: jhr Status: fixed in 109.30 [jhr, 7/14/97] ---------------------------------------------------------------------- Number: 1230 Title: bus-error due to representation problem Keywords: bus-error Submitter: manuel@cs.berkeley.edu Date: July 12 Version: 109.26 and 109.29 System: Solaris Ultrasparc and Linux i686 Severity: severe Problem: Small test program crashes sml process Code: signature CONS = sig type 'a sign type 'a constructor val new : {name : string, signa : 'a sign} -> 'a constructor end structure Cons : CONS = struct datatype sort = SUB | CSUB datatype datacon = DCON of {name : string, arity : int, sign : sort list, sort : sort, strict : bool} type 'a constructor = datacon type 'a sign = {sign : sort list, sort : sort, strict : bool} fun new {name,signa={sign,sort,strict}} = DCON {name=name, arity=List.length sign, sign=sign, sort=sort, strict=strict } end Transcript: [Solaris,UltraSparc] Standard ML of New Jersey, Version 109.26, March 25, 1997 [CM; autoload enabled] - [opening /tmp/mla002oZ] signature CONS = sig type 'a sign type 'a constructor val new : {name:string, signa:'a sign} -> 'a constructor end structure Cons : CONS? val it = () : unit - Cons.new; Process sml bus error [Linux i686] Standard ML of New Jersey, Version 109.26, March 25, 1997 [CM; autoload enabled] use "/tmp/mla32088";^M - [opening /tmp/mla32088] signature CONS = sig type 'a sign type 'a constructor val new : {name:string, signa:'a sign} -> 'a constructor end structure Cons : CONS? val it = () : unit - Cons.new; /disks/orodruin/aa/home/manuel/Projects/sml-109.26/bin/.run/run.x86-linux: Fatal error --\ unexpected fault, signal = 11, code = 0x4081346b Process sml exited abnormally with code 1 Comments: I tried to make the example as short as possible. It seems important that the datatype DCON have at least 5 fields in the record, and that new takes 2 arguments. Fix: Test: bug1230.sml Owner: Zhong Status: fixed in 109.30 [Zhong] ---------------------------------------------------------------------- Number: 1231 Title: Error: Compiler bug: ModuleUtil: unexpected binding in extractInfo Keywords: secondary error, error recovery Submitter: manuel@cs.berkeley.edu Date: July 12 Version: 109.29 System: Solaris Ultrasparc Severity: severe Problem: Error: Compiler bug: ModuleUtil: unexpected binding in extractInfo Code: signature CONS = sig type 'a sign type 'a constructor val new : {name : string, signa : 'a sign} -> 'a constructor end structure Cons : CONS = struct datatype sort = SUB | CSUB datatype datacon = DCON of {name : string, arity : int, sign : sort list, sort : sort, strict : bool} type 'a constructor = datacon datatype 'a sign = Sign of {sign : sort list, sort : sort, strict : bool} fun new {name,signa=Sign{sign,sort,strict}} = DCON {name=name, arity=List.length sign, sign=sign, sort=sort, strict=strict } end signature B = sig structure Cons : Cons end structure B :> B = struct structure Cons = Cons end Transcript: Standard ML of New Jersey, Version 109.29, June 13, 1997 [CM; autoload enabled] - [opening /tmp/mla002oZ] /tmp/mla002oZ:39.2-40.5 Error: unbound signature: Cons Error: Compiler bug: ModuleUtil: unexpected binding in extractInfo uncaught exception Error raised at: util/errormsg.sml:51.14-51.19 modules/sigmatch.sml:807.24 elaborate/elabmod.sml:1039.8 util/stats.sml:164.40 build/evalloop.sml:120.38 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 - Comments: Fix: Test: bug1231.sml Owner: Zhong Status: fixed in 109.30 ---------------------------------------------------------------------- Number: 1232 Title: consistent definitional specs seen as inconsistent Keywords: modules, signatures, definitional specs, where definitions Submitter: Norman Ramsey Date: 6/19/97 Version: 109.29 System: - Severity: major Problem: Definitional specs are rejected as inconsistent when they are not. Code: signature SIG1 = sig type t = int end signature SIG2 = sig structure N : SIG1 end functor Bad(structure X : SIG1 structure Y : SIG2 where N = X) = struct end; Transcript: - use "foo.sml"; [opening foo.sml] foo.sml:11.9-13.11 Error: Inconsistent defining constraints : type t = t uncaught exception Error raised at: build/evalloop.sml:103.44-103.52 build/evalloop.sml:120.38 build/evalloop.sml:193.58 build/evalloop.sml:285.46-285.49 Comments: Confusing error message too. Fix: Remove consistency checking for multiple definitions in Instantiate.builtTycClass.constrain when one or both definitions are not instantiated (NOTINST tyc). Test: bug1232.sml Owner: dbm Status: fixed in 109.30 [dbm, 7/16/97] ---------------------------------------------------------------------- Number: 1233 Title: funny printing of multiple bindings in a declaration Keywords: printing, duplicate binding Submitter: Walid Taha Date: 7/16/97 Version: 109.29 System: - Severity: minor Problem: The top level prints an odd message when a value variable is bound twice in a declaration. Transcript: - val c = 1 val c = 2; val c = : int val c = 2 : int Comments: It would be preferable to just print val c = 2 : int as the result of the declaration. Fix: Test: bug1233.sml Owner: Zhong? Status: open ---------------------------------------------------------------------- Number: 1234 Title: EntityEnv.Unbound raised in functor application Keywords: modules, translation, hidden types Submitter: Dave MacQueen Date: 7/21/97 Version: 109.30 (+ bug 1206 fix) System: - Severity: major Problem: EntityEnv.Unbound exception raised in function specLty when compiling legal functor application. Code: functor F(type t val x : t) = struct structure U : sig type u val y : u end = struct datatype u = K of t type u = u list val y = [K x] end val z = hd U.y end; structure A = T(type t = int val x = 3); Transcript: - use "bug1234.sml"; [opening bug1234.sml] functor F : uncaught exception Unbound raised at: translate/transmodules.sml:79.33-79.43 util/stats.sml:164.40 build/evalloop.sml:193.58 build/evalloop.sml:285.46-285.49 Comments: [dbm] This is after incorporating the fix for bug 1206. If the signature on U is removed, the code works. Looking at the functor representation and the bad entityEnv with debugging on, it looks like signature matching is introducing an extra level of structure nesting. The path to the hidden datatype u should be of length 2, but in the entityEnv, the datatype is nested inside an extra intermediate structure, so the length two path doesn't reach it. I presume that sigmatch is creating the extra intermediate structure level. Fix: Test: bug1234.sml Owner: dbm, Zhong Status: Fixed in 109.31 [Zhong] ---------------------------------------------------------------------- Number: 1235 Title: Argument type constraint changes behavior of a function Keywords: types Submitter: Sam Kamin, s-kamin@uiuc.edu Date: 7/21/97 Version: Version 109.29, June 13, 1997 [CM&CMB] System: sparc-solaris, don't know what version offhand Severity: major Problem: Function defined as fun f x = ... type-checks, but then crashes. When defined as fun f (x:T) = ..., it works fine. Code: I'm not going to send enough to reproduce the error, because it's too much. If this turns out to be an interesting problem, I can send it. Anyway, the specific problem is demonstrated in this function: fun mkseqlist seqop [] = empty | mkseqlist seqop [p:Picture] = p | mkseqlist seqop (p::ps) = seqop (p, mkseqlist seqop ps); If the ":Picture" in the second clause is omitted, the function type-checks but crashes when used. Transcript: In this transcript, "seq" is an infix operator. As I said, I haven't come up with a simpler example, and I don't think you want all the code (especially not if this turns out to be something simple). - fun mkseqlist seqop [] = empty | mkseqlist seqop [p] = p | mkseqlist seqop (p::ps) = seqop (p, mkseqlist seqop ps); = = val mkseqlist = fn : ((('a -> string) * Environment) * (('a -> string) * Environment) -> ('a -> string) * Environment) -> (('a -> string) * Environment) list -> ('a -> string) * Environment - val seqlist = mkseqlist (op seq); val seqlist = fn : ((GraphicsContext -> string) * Environment) list -> (GraphicsContext -> string) * Environment - draw (seqlist [text "a"]) "test"; ~2.34725596609e228, ~2.34705354077e228 uncaught exception Overflow [overflow] - fun mkseqlist seqop [] = empty | mkseqlist seqop [p:Picture] = p | mkseqlist seqop (p::ps) = seqop (p, mkseqlist seqop ps); = = val mkseqlist = fn : (Picture * ((GraphicsContext -> string) * Environment) -> (GraphicsContext -> string) * Environment) -> Picture list -> (GraphicsContext -> string) * Environment - val seqlist = mkseqlist (op seq); val seqlist = fn : Picture list -> (GraphicsContext -> string) * Environment - draw (seqlist [text "a"]) "test"; 1.0, 0.0(1.0, 1.0)(0.0, 0.0)val it = () : unit - Comments: I'm not sure if this is really a bug, but it seems to me that adding type declarations is not supposed to matter. And it's a heck of a difficult error to track down. Fix: Test: ? Owner: Zhong Status: fixed in 109.30 ---------------------------------------------------------------------- Number: 1236 Title: TextIO.outputSubstr doesn't work on substrings containing \n Keywords: IO, TextIO, outputSubstr Submitter: Konrad.Slind@cl.cam.ac.uk Date: 7/23/97 Version: 109.30 System: sparc/solaris 2.5.5 Severity: major Problem: TextIO.outputSubstr doesn't seem to handle substrings with "\n" in them. For example: - TextIO.outputSubstr(TextIO.stdOut, Substring.all("hello\n")); val it = () : unit This behaviour contradicts the description in the basis documentation. Code: TextIO.outputSubstr(TextIO.stdOut, Substring.all("hello\n")); Comments: Fix: Test: bug1236.sml Owner: jhr, erg Status: fixed in 109.32 [jhr, 7/24/97] ---------------------------------------------------------------------- Number: 1237 Title: ml-yacc doesn't handle constructors with long names Keywords: ml-yacc, constructor names Submitter: Konrad.Slind@cl.cam.ac.uk Date: 7/23/97 Version: 109.30 System: - Severity: major Problem: ml-yacc emits bogus string literals from constructors with long names. The following input will generate a file where, on about line 104, a mangled string literal is produced. Code: %% %term I_am_a_great_long_lexeme_comma_of_a_sort_not_normally_found_in_the_wild | EOLEX | EOF %nonterm START of unit %start START %eop EOF EOLEX %pos int %header (functor ELrValsFun (structure Token : TOKEN)) %name E %noshift EOF %pure %% START : I_am_a_great_long_lexeme_comma_of_a_sort_not_normally_found_in_the_wild() Transcript: Comments: Fix: Test: Owner: appel Status: fixed in 109.32 ---------------------------------------------------------------------- Number: 1238 Title: Elaboration error involving where structure Keywords: where structure Submitter: Perry Cheng (pscheng@cs.cmu.edu) Date: 7/23/97 Version: 109.30 System: Digital Unix 4.0 Severity: major Problem: Where structure construct causes strange error message. Code: signature MA = sig type t end; signature MU = sig structure M : MA end; signature DA = sig type t end; (* ------------ this one works ---------------------- *) functor Good(structure D : DA structure Mu : MU where type M.t = D.t) = struct end; (* ------------ this one fails ---------------------- *) functor Bad(structure D : DA structure Mu : MU where M = D) = struct end; Transcript: - use "bug1238.sml"; [opening bug1238.sml] signature MA = sig type t end signature MU = sig structure M : sig type t end end signature DA = sig type t end functor Good : uncaught exception Unbound raised at: elaborate/elabmod.sml:1164.39-1164.49 util/stats.sml:164.40 build/evalloop.sml:120.38 build/evalloop.sml:193.58 build/evalloop.sml:285.46-285.49 Comments: Minor modification to the code will make the bug go away. This bug is related to bug 1232. On a related note, sometime a functor definition that involves "where structure" generates a functor which, when instantiated, gives the same error message even though the code is correct. [dbm, 7/23/97] If DA is replaced by MA in Bad, the code compiles ok. So the problem is caused by the difference in signatures (DA vs MA). Fix: Modified entityInfo datatype in Instantiate so that GENERATE_ENT carries a boolean value indicating whether there was a VARstrDef with signature that does not agree with the spec. Test: bug1238.sml Owner: dbm Status: fixed in 109.31 [dbm, 8/13/97] ---------------------------------------------------------------------- Number: 1239 Title: Subscript-out-of-bounds error when opening a structure Keywords: pretty printing, compiler Submitter: Jon Riecke, riecke@bell-labs.com Date: 07/25/97 Version: 109.30 System: Linux and Irix Severity: major Problem: When opening the CML structure, a "subscript out of bounds" exn is raised. Code: CML standard library Transcript: - open CML; GC #0.0.0.1.3.57: (43 ms) open CML val version = {date="June 11, 1997",system="Concurrent ML",version_id=[1,0,7]} : {date:string, system:string, version_id:int list} val banner = "Concurrent ML, Version 1.0.7, June 11, 1997" : string val getTid = fn : unit -> thread_id val sameTid = fn : thread_id * thread_id -> bool val compareTid = fn : thread_id * thread_id -> order val hashTid = fn : thread_id -> word val tidToString = fn : thread_id -> string val spawnc = fn : ('a -> unit) -> 'a -> thread_id val spawn = fn : (unit -> unit) -> thread_id val exit = fn : unit -> 'a val joinEvt = fn : thread_id -> unit event val yield = fn : unit -> unit val channel = fn : unit -> 'a chan val sameChannel = fn : 'a chan * 'a chan -> bool val send = fn : 'a chan * 'a -> unit val recv = fn : 'a chan -> 'a val sendEvt = fn : 'a chan * 'a -> unit event val recvEvt = fn : 'a chan -> 'a event val sendPoll = fn : 'a chan * 'a -> bool val recvPoll = fn : 'a chan -> 'a option uncaught exception in compiler: subscript out of bounds raised at: print/ppobj.sml:89.24-89.29 print/ppobj.sml:349.20 print/ppobj.sml:349.20 print/ppobj.sml:349.20 util/pp.sml:545.6 build/evalloop.sml:193.58 Comments: [jhr, 7/30/97] Appears to be the same as bug 1241, which is fixed in 109.31. Fix: Test: * Owner: Zhong Status: fixed in 109.31 [Zhong, 7/29/97] ---------------------------------------------------------------------- Number: 1240 Title: Can't form pairs of reals Keywords: reals Submitter: Sam Kamin, kamin@cs.uiuc.edu Date: 7/25/97 Version: 109.30 System: sparc-solaris Severity: Critical Problem: Attempt to create tuples containing only real numbers results in "uncaught exception in compiler: Representation" Code: (0.0,0.0) Transcript: Here are a couple of more examples: - (0.0, 0.0); uncaught exception in compiler: Representation raised at: boot/Unsafe/object.sml:58.19-58.33 print/ppobj.sml:349.20 print/ppobj.sml:349.20 util/pp.sml:545.6 build/evalloop.sml:193.58 - (real 0, real 0); uncaught exception in compiler: Representation raised at: boot/Unsafe/object.sml:58.19-58.33 print/ppobj.sml:349.20 print/ppobj.sml:349.20 util/pp.sml:545.6 build/evalloop.sml:193.58 - ((fn x => (x,x)) 0.0); uncaught exception in compiler: Representation raised at: boot/Unsafe/object.sml:58.19-58.33 print/ppobj.sml:349.20 print/ppobj.sml:349.20 util/pp.sml:545.6 build/evalloop.sml:193.58 - (0.0, 0); val it = (0.0,0) : real * int - (0.0, "abc"); val it = (0.0,"abc") : real * string Comments: Fix: Test: bug1240.sml Owner: jhr, Zhong Status: fixed in 109.31 [jhr, 7/28/97] ---------------------------------------------------------------------- Number: 1241 Title: confused datatype constructors Keywords: datatype Submitter: Elsa L. Gunter, elsa@research.bell-labs.com Date: July 25, 1997 Version: 109.30 System: x86 - linux 2.0 Severity: critical Problem: In a datatype with two constructors, the constructors get swapped Code: datatype 'a t1 = A1 | B1 of ('a list) val i1 = A1; datatype 'a t2 = A2 of int | B2 of ('a list) val i2 = A2 0; norfolk% sml Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] - datatype 'a t1 = A1 | B1 of ('a list) val i1 = A1; datatype 'a t1 = A1 | B1 of 'a list val i1 = B1 [] : 'a t1 - datatype 'a t2 = A2 of int | B2 of ('a list) val i2 = A2 0; datatype 'a t2 = A2 of int | B2 of 'a list uncaught exception in compiler: subscript out of bounds raised at: print/ppobj.sml:89.24-89.29 print/ppobj.sml:349.20 print/ppobj.sml:349.20 util/pp.sml:545.6 build/evalloop.sml:193.58 - Comments: Notice that in the first datatype declaration, I assign, i1 to be A1, but it gives me back that it is B1 []. In the second case, it raises an exception (I think because it is trying to apply B2 [] to 0.). Fix: change to ppobj.sml Test: bug1241.sml Owner: Zhong Status: fixed in 109.31 [Zhong] ---------------------------------------------------------------------- Number: 1242 Title: error recovery in open could be better Keywords: open error recovery Submitter: manuel@cs.berkeley.edu Date: July 29/97 Version: 109.29 System: all Severity: low Problem: If one structure is undefined in an open declarations with multiple structures, the non-constant constructors made visible from opening preceding structures are not bound. Results in weird spurious error messages. Code: structure A = struct datatype at = A | B | C of int end local open A Foo in fun toString A = "A" | toString B = "B" | toString (C i) = "C " ^ Int.toString i end Transcript: - [opening /tmp/mla003Cy] /tmp/mla003Cy:7.5-7.15 Error: unbound structure: Foo /tmp/mla003Cy:9.9-11.47 Error: non-constructor applied to argument in pattern: C uncaught exception Error raised at: build/evalloop.sml:103.44-103.52 build/evalloop.sml:120.38 build/evalloop.sml:192.58 build/evalloop.sml:284.46-284.49 - Comments: The C constructor isn't visible, even though A and B are. Removing the Foo structure from the open declaration makes the second error disappear. [dbm, 7/29/97] The reason there is no error message complaining about A and B in the first two clauses of toString is that since these are not bound as constructors they are interpreted as variables. It should be possible to have the open take effect on the structures that are defined, which would cut down on secondary errors like this one. [manuel, 7/29/97] Yes, you are right about the constant constructors. I didn't think of that. But what is strange is that only constructors seem to be missing from the environment. Value bindings are visible in the same context. Fix: Test: bug1242.sml Owner: dbm Status: open ---------------------------------------------------------------------- Number: 1243 Title: Application of functor to different representations Keywords: functor application, polymorphism, representation analysis Submitter: Stephen Weeks Date: 7/28/97 Version: 109.30 System: x86-linux Severity: major Problem: compiler bug tickled by application of functor to two different polymorphic representations Code: local functor Foo(type 'a t val destruct : 'a t -> ('a * 'a t) option) = struct fun first s = case destruct s of SOME(x,_) => x end structure Foo1 = Foo(type 'a t = 'a list fun destruct _ = let exception E in raise E end) structure Foo2 = Foo(datatype 'a t = T of ('a * 'a t) option fun destruct _ = let exception E in raise E end) in val _ = 13 end Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] stdIn:36.6-37.23 Warning: match nonexhaustive SOME (x,_) => ... for the type: I Error: Compiler bug: LambdaType: unexpected case in tcd_arw - Comments: Fix: change to translate/specialize.sml Test: bug1243.sml Owner: Zhong Status: fixed in 109.31 [Zhong, 7/29/97] ---------------------------------------------------------------------- Number: 1244 Title: Explicitly scoped type variable with 'val ... and' declaration Keywords: translate, lambda types Submitter: Stephen Weeks Date: 8/1/97 Version: 109.30, 109.30+ System: x86-linux Severity: minor Problem: Compiler bug caused by use of an explicitly scoped type variable in multiple val declarations. Code: val 'a f = fn x : 'a => x and g = fn y : 'a => y Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] - val 'a f = fn x : 'a => x and g = fn y : 'a => y = = ; Error: Compiler bug: Translate: unexpected tyvar INSTANTIATED in mkPE - Comments: Fix: Test: bug1244.sml Owner: Zhong, dbm Status: fixed in 109.31 ---------------------------------------------------------------------- Number: 1245 Title: Pretty printer bug Keywords: Submitter: Stephen Weeks Date: 8/4/97 Version: 109.30 System: x86-linux Severity: minor Problem: Error raised when attempting to print the binding of a pair of empty lists in the REPL. Code: val (x,y) = ([],[]) Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM&CMB] val it = () : unit - val (x,y) = ([],[]); uncaught exception in compiler: subscript out of bounds raised at: print/ppobj.sml:422.28-422.33 print/ppobj.sml:349.20 print/ppobj.sml:349.20 util/pp.sml:545.6 build/evalloop.sml:193.58 - Comments: Fix: Test: bug1245.sml Owner: Zhong Status: fixed in 109.31 ---------------------------------------------------------------------- Number: 1246 Title: Explicit scoping of type variables does not obey the standard. Keywords: explicity scoped type variable Submitter: Stephen Weeks Date: 8/4/97 Version: 109.30 System: x86-linux Severity: minor Problem: The following definition does not typecheck. fun f() = (let val 'a id :'a -> 'a = fn z => z in id id end, fn z => z:'a) The following definition does typecheck. fun f() = (let val 'a id :'a -> 'a = fn z => z in id id end, fn z => z:'b) I believe that, according to the standard, they both should typecheck. It appears that the first example is failing because the typechecker is changing the scope of the explicitly scoped 'a, whereas the standard only specifies how to determine the scope of implicitly scoped type variables -- the scope of explicitly scoped type variables should not change. As the second example demonstrates, the problem appears to occur because a bound type variable happens to have the same name as a free type variable. Code: fun f() = (let val 'a id :'a -> 'a = fn z => z in id id end, fn z => z:'a) fun f() = (let val 'a id :'a -> 'a = fn z => z in id id end, fn z => z:'b) Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM&CMB] val it = () : unit - fun f() = (let val 'a id :'a -> 'a = fn z => z in id id end, fn z => z:'a); = stdIn:13.12-13.60 Error: operator and operand don't agree [UBOUND match] operator domain: 'a operand: 'a -> 'a in expression: id id - fun f() = (let val 'a id :'a -> 'a = fn z => z in id id end, fn z => z:'b); = val f = fn : unit -> ('a -> 'a) * ('b -> 'b) - Another example from Andrew Tolmach [8/18/97] - val 'a f = fn (x:'a) => let val 'a g = fn (y:'a) => (y,y) in g (x,x) end; stdIn:15.25-15.73 Error: operator and operand don't agree [UBOUND match] operator domain: 'a operand: 'a * 'a in expression: g (x,x) Comments: [Andrew Kennedy, 3/20/98] I have a small query concerning explicit type variables: the final syntactic restriction listed in Section 2.9 (page 9) of the Definition seems unnecessary and isn't enforced by SML/NJ. Was it a mistake? In particular, the Tolmach example cited on your bug list val 'a f = fn (x:'a) => let val 'a g = fn (y:'a) => (y,y) in g (x,x) end would appear (to me) not to obey this restriction, and yet is perfectly sensible if val 'a is essentially `big lambda'. Surely a desirable property of the SML is that a declaration such as val 'a id = fn x : 'a => x can be plugged into an arbitrary program context without breaking any restrictions. Fix: in elabcore.sml, revised calculations of updt in the presence of etvs (explicitly bound type variables) to avoid inappropriate instantiations of explicit variables. Test: bug1246.sml, bug1246.1.sml Owner: dbm Status: fixed in 109.31 [dbm, 9/4/97] ---------------------------------------------------------------------- Number: 1247 Title: IntSet library module is wrong Keywords: smlnj-lib, IntSet, ListSet Submitter: Andrew Kennedy Date: 8/4/97 Version: 109.30 System: - Severity: major Problem: A while back I reported some bugs in the ListSet functor. They were fixed but unfortunately the fix doesn't appear to have been applied to the IntSet specialised version. (Just compare the source files: they're are some missing primes on variable names in some functions). Comments: Fix: Test: ? Owner: jhr, Emden Status: Fixed in 109.31 ---------------------------------------------------------------------- Number: 1248 Title: blastWrite failures Keywords: blastRead, blastWrite Submitter: Chris Paris Date: 8/5/97 Version: 109.30 System: ? Severity: major Problem: blastwrite fails catastrophically Code: Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM&CMB] val it = () : unit - val blastWrite : 'a -> Word8Vector.vector = (fn x => Unsafe.CInterface.c_function "SMLNJ-RunT" "blastOut" x);val blastWrite = fn : 'a -> Word8Vector.vector - blastWrite (Word8Array.array (516000, 0w0)); GC #0.0.0.0.1.4: (0 ms) GC #0.0.0.0.2.6: (10 ms) val it = - : Word8Vector.vector - blastWrite (Word8Array.array (516001, 0w0)); GC #0.0.0.1.3.7: (0 ms) GC #0.0.0.1.4.8: (0 ms) ./sml: Fatal error -- blasting out of 516096 bytes not supported yet! Increase allocation arena size. But perhaps blasting one large atomic object presents a problem that blasting a collection of small objects wouldn't, so here's another example. Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM&CMB] val it = () : unit - val blastWrite : 'a -> Word8Vector.vector = (fn x => Unsafe.CInterface.c_function "SMLNJ-RunT" "blastOut" x); val blastWrite = fn : 'a -> Word8Vector.vector - fun iter 0 = [] = | iter n = n :: (iter (n-1)); val iter = fn : int -> int list - blastWrite (iter 10); val it = - : Word8Vector.vector - blastWrite (iter 100); val it = - : Word8Vector.vector - blastWrite (iter 1000); val it = - : Word8Vector.vector - blastWrite (iter 10000); GC #0.0.0.0.1.13: (20 ms) val it = - : Word8Vector.vector - blastWrite (iter 100000); GC #0.0.0.1.2.16: (110 ms) GC #0.0.0.2.3.17: (140 ms) Segmentation fault Comments: [Chris Paris, 8/5/97] In last night's message, I meant to make another comment about blastWrite but forgot. I find it limiting that the size of the object blastWrite can handle is limited by the allocation arena size. I'm already running with a doubled allocation arena size to accomodate our growing data, but I understand that I can't just keep increasing it indefinitely and expect to retain reasonable performance. The end of blast-out.c mentions allocating space in the big-object arena as an alternative implementation. I'm wondering if this would be an easy change to make that hasn't been done simply due to lack of demand, or whether there are difficult issues to overcome in order to remove the current limitation. Fix: Test: bug1248.1.sml, bug1248.2.sml Owner: jhr Status: fixed in 109.31 [jhr, 8/12/97] ---------------------------------------------------------------------- Number: 1249 Title: Time.time type too small Keywords: Time.time Submitter: Chris Paris Date: 8/5/97 Version: 109.30 System: - Severity: minor Problem: The project I'm working on uses the Time.time type for some things. Today we ran into some data that required 32 bits in the sec field. We had to write our own time type to handle this. I'm not saying the system Time type should definitely be changed, but I thought you'd like to know that someone needed more than 31 bits there. Comments: The SML Basis now specifies a LargeInt.int representation for the seconds field. -- jhr Fix: Test: Owner: jhr? Status: Fixed in 109.31 [jhr, 7/31/97] ---------------------------------------------------------------------- Number: 1250 Title: Bind exception delayed by polymorphic generalization Keywords: Bind exception Submitter: Stephen Weeks Date: 8/5/97 Version: 109.30 System: x86-linux Severity: minor Problem: A Bind exception is not raised in a value declaration when the variable being defined is polymorphically generalized. I suspect that the raise is getting wrapped in a _/\_ in the translation into the typed IL. The exception is raised later if the polymorphic value is applied. Code: datatype 'a foo = Foo1 of 'a | Foo2 of 'a val Foo1 f = Foo2(fn x => x); f 13; Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM&CMB] - datatype 'a foo = Foo1 of 'a | Foo2 of 'a val Foo1 f = Foo2(fn x => x); = stdIn: Warning: binding not exhaustive Foo1 f = ... datatype 'a foo = Foo1 of 'a | Foo2 of 'a val f = fn : 'a -> 'a - f 13; uncaught exception Bind [nonexhaustive binding failure] raised at: stdIn: Comments: [Zhong, 8/5/97] Thanks for the bug report. This bug is actually related to the pretty-printing. As you observed, binding f to _/\_ does not raise the exception; the exception should be raised when printing f in the top-level (however, the pretty-printing in 109.30 was broken, so the exception is not raised). Our fixes for the other pretty-printing bugs (which have been incorporated into 109.31) should correctly raise the exception, however, the exception name is not printed out correctly still. Fix: Test: bug1250.sml Owner: Zhong Status: Fixed in 109.31 [Zhong] ---------------------------------------------------------------------- Number: 1251 Title: where specs cause exception Unbound Keywords: where Unbound Submitter: Stephen Weeks Date: 8/6/97 Version: 109.30 System: x86-linux Severity: minor Problem: The use of a where spec can cause exception Unbound to be raised by the elaborator. Code: structure S : sig structure A : sig end structure B : sig structure C : sig end end where C = A end = struct structure A = struct end structure B = struct structure C = A end end Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] - structure S : sig structure A : sig end structure B : sig structure C : sig end end where C = A end = struct structure A = struct end structure B = struct structure C = A end end; uncaught exception in compiler: Unbound raised at: elaborate/elabmod.sml:1050.15-1050.25 util/stats.sml:164.40 build/evalloop.sml:120.38 build/evalloop.sml:193.58 Comments: [Zhong, 8/6/97] Thanks for the bug report. I encountered this same bug while trying to fix bug 1205. It happens only if the righthand side of the where clause is a "flexible" structure (i.e., locally defined structure). Dave and I will try to get a fix into 109.31. Fix: change strEntEnv to entEnv around line 545 of sigmatch.sml Test: bug1251.sml Owner: Zhong, dbm Status: fixed in 109.31 [Zhong, dbm] ---------------------------------------------------------------------- Number: 1252 Title: Unbound exception on functor application Keywords: modules, functors Submitter: Stephen Weeks Date: 8/6/97 Version: 109.30 System: x86-linux Severity: minor Problem: A compiler bug is raised on the following code. Code: functor F(type t) = let structure S : sig type v val x : v end = struct datatype 'a u = U of (t * 'a) list type v = t u val x = U[] end in struct datatype t = T of S.v val x = T S.x end end; structure S = F(type t = int); Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] - functor F(type t) = let structure S : sig type v val x : v end = struct datatype 'a u = U of (t * 'a) list type v = t u val x = U[] end in struct datatype t = T of S.v val x = T S.x end end; - structure S = F(type t = int); functor F : Error: Compiler bug: TransTypes: unexpected FORMAL kind in tycTyc-h [dbm: In 109.31-, the behavior is different. Unbound (EE.Unbound?) is raised instead: ] - use "test/bugs/bug1252.sml"; [opening test/bugs/bug1252.sml] functor F : uncaught exception Unbound raised at: elaborate/elabmod.sml:1060.15-1060.25 util/stats.sml:164.40 build/evalloop.sml:123.38 build/evalloop.sml:196.58 build/evalloop.sml:289.46-289.49 Comments: [Zhong] This seems to be the same as bug 1234. Fix: Test: bug1252.sml, bug1252.1.sml Owner: Zhong, dbm Status: Fixed in 109.31 [Zhong] ---------------------------------------------------------------------- Number: 1253 Title: pretty printing nested polymorphic records Keywords: pretty printing, representations Submitter: Chris Page Date: 8/6/97 Version: 109.30 System: - Severity: major Problem: The code in the printer that tries to avoid printing polymorphic records doesn't work when the record is wrapped in another (non-record) type. Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM&CMB] val it = () : unit - (NONE, ()); val it = : 'a option * unit - SOME (NONE, ()); uncaught exception in compiler: Representation Comments: [Zhong, 4/4/98] By the way, in 110.4, I have fixed the pretty printing of poly record. So typing things such as: val x = (nil, nil) or val x = (nil, 3) will print the expected values rather than . Fix: Test: bug1253.sml Owner: Zhong Status: fixed in 109.31 ---------------------------------------------------------------------- Number: 1254 Title: Disagreements between SML/NJ and Defn: datatype replication Keywords: datatype replication Submitter: Stephen Weeks Date: 8/11/97 Version: 109.30 System: x86-linux Severity: minor Problem: (1) I believe that the Standard says that the following program is legal, and should make 's' an abbreviation for 'int'. However, SML/NJ responds with "Error: rhs of datatype replication not a datatype". type t = int datatype s = datatype t SML/NJ and the Standard both accept the following program, but I believe they do so for different reasons. (2) structure S : sig type t end = struct datatype t = T end datatype u = datatype S.t After the above program is entered, I believe that the Standard says that the following declaration is illegal, whereas SML/NJ accepts it. val x = T My reading of the Standard is that the signature constraint on 'S' should hide the constructors associated with type 't' and that the declaration of 'u' should declare 'u' as an abbreviation of 't', but not be able to access t's constructors, since they were hidden by the signature. Comments: [dbm, 8/14/97] Part (1) is considered an omission in the Definition. Part (2) is a bug because of rule (80), which says that the constructor environment component of t is stipped out by signature matching. This should really cause the subsequent datatype replication declaration datatype u = datatype S.t to fail, because there is no constructor environment for u to inherit from S.t, and a datatype without a constructor environment is not a proper datatype. Fix: Test: bug1254.sml Owner: dbm Status: open (2) ---------------------------------------------------------------------- Number: 1255 Title: Disagreements between SML/NJ and Defn: datatype replication, part II Keywords: datatype replication Submitter: Stephen Weeks Date: 8/11/97 Version: 109.30 System: x86-linux Severity: minor Problem: I believe that the following code is legal, according to the Standard. However, SML/NJ rejects it, responding with: Error: value type in structure doesn't match signature spec name: U spec: ?.t -> ?.Foo.u actual: ?.int -> ?.Foo.u Code: structure Foo : sig type t datatype u = U of t structure Goo : sig datatype v = datatype u end end = struct type t = int datatype u = U of t structure Goo = struct datatype v = datatype u end end Transcript: Comments: Fix: Modified PATHtyc case of expandTyc in elabDATArepl in elabsig.sml. Check if entPath is external, in which case nothing needs to be done. Otherwise, if PATHtyc is internal to current signature, adjust it by adding appending prefix. Test: bug1255.sml Owner: dbm Status: fixed in 109.31 [dbm, 7/15/97] ---------------------------------------------------------------------- Number: 1256 Title: Free type variables in local datatype declarations. Keywords: datatype type variable Submitter: Stephen Weeks Date: 8/11/97 Version: 109.30 System: x86-linux Severity: minor Problem: In a local datatype declarations, SML/NJ does not accept constructors whose types contain type variables that are not bound in the datatype declaration (even if they are bound in the enclosing program). For example, I believe that the Standard says that following program should be accepted. SML/NJ responds with "Error: unbound type variable in type declaration: 'a". Code: fun 'a f (x : 'a) = let datatype foo = Foo of 'a * int in 13 end Transcript: Comments: [dbm, 8/13/97] This may technically be accepted under the definition, but this is an oversight or error in the definition. For various reasons, if a polymorphically bound type variable could participate in type definitions as in your example, there would be serious implementation complications for very little gain in utility. I don't plan to "fix" this bug in SML/NJ. Fix: Test: * Owner: dbm Status: not a bug ---------------------------------------------------------------------- Number: 1257 Title: (spurious) dependency cycle in instantiate Keywords: modules, opaque signatures Submitter: manuel@cs.berkeleye.edu Date: 8/19/97 Version: SML-109.30 + blume patch System: x86-linux, sparc-solaris2.5 Severity: major Problem: Opaque signature matching fails when the structure contains a functor whose signature has where specifications. Produces uncaught exception Unbound and a message "dependency cycle in instantiate" Code: signature S = sig type genT type T val embed : T -> genT end structure S = struct type genT = int type T = int val embed = fn x => x end signature B = sig type genT functor mkS() : S where type genT = genT end structure B :> B = struct type genT = S.genT functor mkS() = S end Transcript: - use "bug_inst.sml"; [opening bug_inst.sml] bug_inst.sml:29.1-35.8 Error: dependency cycle in instantiate uncaught exception Unbound raised at: elaborate/elabmod.sml:1060.15-1060.25 util/stats.sml:164.40 build/evalloop.sml:123.38 build/evalloop.sml:196.58 build/evalloop.sml:289.46-289.49 - Comments: The idea behind this code is to create new structures using B.mkS(), each of which will share the type genT, but not the type T. The desired behavior can be obtained with the following code, which moves the opaque matching from B to the functor. The difference to the code above is in that genT is not opaque in B. signature S = sig type genT type T val embed : T -> genT val new : int -> T val show : genT -> unit end structure S = struct type genT = int type T = int val embed = fn x => x fun new x = x val show = fn x => print (Int.toString x ^"\n") end signature B = sig type genT functor mkS() : S where type genT = genT end structure B : B = struct type genT = S.genT functor mkS() :> S where type genT = genT = S end structure X = B.mkS; structure Y = B.mkS; val x = X.new 5; val y = Y.new 7; val xe = X.embed x; val ye = X.embed y; val _ = X.show ye; (* is accepted correctly *) val _ = Y.show xe; (* is accepted correctly *) val xf = Y.embed x; (* rejected correctly *) val yf = X.embed y; (* rejected correctly *) val _ = X.show 5; (* genT isn't opaque. *) Fix: Test: Owner: dbm Status: Fixed in 109.31 ---------------------------------------------------------------------- Number: 1258 Title: OS.Process.atExit does not agree with basis documentation Keywords: standard basis Submitter: Chris Stone, cstone+@cs.cmu.edu Perry Cheng, pscheng+@cs.cmu.edu Date: August 19, 1997 Version: 109.30 System: Alpha OSF/1 3.2 Severity: minor Problem: From the on-line standard basis documentation for OS.Process.atExit: Calls to exit do not return, but should cause the remainder of the functions registered with atExit to be executed. The code does not have this behavior. Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] - OS.Process.atExit (fn _ => print "1\n"); val it = () : unit - OS.Process.atExit (fn _ => print "2\n"); val it = () : unit - OS.Process.atExit (fn _ => print "3\n"); val it = () : unit - ^D3 2 1 Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] - OS.Process.atExit (fn _ => print "1\n"); val it = () : unit - OS.Process.atExit (fn _ => OS.Process.exit 1); val it = () : unit - OS.Process.atExit (fn _ => print "3\n"); val it = () : unit - ^D3 3 3 3 ...[infinite loop] Comments: A quick glance at the file NJ/cleanup.sml led us to initially expect that the call to exit would terminate the program immediately, skipping the third function registered with atExit. However, it turns out that since the "clean" function does not change the list "hooks" when called with the AtExit parameter, the call to exit starts re-invoking all of the functions registered with AtExit. Fix: Test: Owner: jhr Status: fixed in 109.31 ---------------------------------------------------------------------- Number: 1259 Title: Mistakenly inadmissable signature. Keywords: modules, signatures Submitter: Stephen Weeks Date: 8/19/97 Version: 109.30 System: x86-linux Severity: minor Problem: The following signature is not accepted by SML/NJ 109.30, even though it should be. SML/NJ 109.30 returns the message "Error: dependency cycle in instantiate". Earlier versions, such as 109.29, accepted this signature at the point it was declared, but reported the dependency cycle error when it was used as a functor parameter (i.e. when it was instantiated). Code: signature SIG = sig type b' datatype a = A1 | A2 of b' datatype b = B1 | B2 of a sharing type b = b' end The signature is accepted when it directly constrains a structure, as in the following code. structure S : sig type b' datatype a = A1 | A2 of b' datatype b = B1 | B2 of a sharing type b = b' end = struct datatype a = A1 | A2 of b and b = B1 | B2 of a type b' = b end Transcript: Comments: This might be the same as bug #1257. [Zhong, 8/21/97] Ok, in 109.30, we check the validity of every signature at its definition site (i.e., we try to instantiate it), thus the cycle is detected even at the declaration site. |> In any case, both versions are wrong to reject the signature, since it |> can be instantiated by the structure I provided. |> |> structure S : sig |> type b' |> datatype a = A1 | A2 of b' |> datatype b = B1 | B2 of a |> sharing type b = b' |> end = |> struct |> datatype a = A1 | A2 of b |> and b = B1 | B2 of a |> type b' = b |> end I'd not say our implementation is wrong :-) I'd argue that it is the Definition that is wrong --- in fact, the Definition is vague on how the above signature will be elaborated --- if you follow what's said in the Definition, you will get a structure of the form structure SIG-INST = struct type b' = b datatype a = A1 | A2 of b datatype b = B1 | B2 of a end [dbm: not quite. The definition (rule 78) elaborates the sharing spec by applying a substitution to an already elaborated environment structure representing the previous specs.] Notice I have no way to reorder the above into a valid ML structure. The best I can do is: structure SIG-INST = struct datatype a = A1 | A2 of b datatype b = B1 | B2 of a type b' = b end still type a and b are mutually recursive. To make it work, the signature elaboration has to make a and b mutually recursive: structure SIG-INST = struct datatype a = A1 | A2 of b and b = B1 | B2 of a type b' = b end This is non-trivial to generalize to cover other cases; for example, what if SIG is like the following: signature SIG' = sig type b' datatype a = A1 | A2 of b' structure S : sig datatype b = B1 | B2 of a end sharing type b' = S.b' end SIG' probably will not match any structure, but it is very hard to discover what is match-able and what is not. Because of all these, we decided to adopt a simpler algorithm in SML/NJ --- we'll only do reorganizations of all the specs, but we'll never merge two non-recursive datatype specs into mutually-recursive ones. [dbm, 8/5/97] I think that it would probably be possible to fix this "bug" superficially in the Instantiate module, but I am not sure what the consequences would be for FLINT's type representation analysis. In particular, with a signature declaration such as the following [1] signature SIG = sig type b' datatype a = A1 | A2 of b' datatype b = B1 | B2 of a sharing type b = b' end the datatypes a and b are made mutually recursive "after the fact" as a consequence of the type sharing spec. Will the FLINT representation analysis be able to come up with the same representations of a and b as for the following "equivalent" (see comment on equality properties below) signatures: [2] signature SIG = sig datatype a = A1 | A2 of b and b = B1 | B2 of a type b' sharing type b = b' end [3] signature SIG = sig datatype a = A1 | A2 of b and b = B1 | B2 of a type b' = b end and if you come up with different representations for the latter two signatures, does it matter? In other words, if you have two independent datatype specs, and then tie a knot between them by a subsequent sharing spec, can you recover the same representation as though the types had originally been specified as mutually recursive, or do you care? There is also the issue of assigning the equality properties to the specified types. In [1], b' does not admit equality, and therefore neither does a, and so neither does b. In [2] and [3], a and b, and therefore b', do admit equality. Does this inconsistency matter? Also, things can get much more convoluted; for instance signature SIG = sig structure A : sig type a end structure B : sig datatype b = B1 | B2 of A.a end structure C : sig datatype c = C1 | C2 of B.b end sharing type A.a = C.c end which could be matched by the structure structure S = struct datatype b = B1 | B2 of c and c = C1 | C2 of b structure A = struct type a = c end structure A = struct datatype b = datatype b end structure A = struct datatype c = datatype c end end I think it is clear that we don't want to force Instantiate to be this clever when attempting to create a realization. So how do we formulate a sharp condition that will disallow these kinds of recursion through sharing specs? Fix: Test: bug1259.1.sml, bug1259.2.sml, bug1259.3.sml Owner: dbm, Zhong Status: open ---------------------------------------------------------------------- Number: 1260 Title: Compiler bug (EntityEnv) when compiling ml-yacc Keywords: Submitter: John Reppy (jhr@research.bell-labs.com) Date: August 26, 1997 Version: 109.30+ System: all Severity: major Problem: I changed ml-yacc by replacing the three uses of "abstraction" with ":>". Now I get a compiler error on the file parser2.sml, which is one of the files I changed. I note that this file compiled okay in the context of the compiler, but not when trying to compile ml-yacc. Note, the changed file is accepted by 109.30, so this must have been introduced by one of the recent changes. Code: Transcript: [opening ../lib/parser2.sml] GC #0.0.0.1.3.62: (76 ms) lookEnt.1: expected STRent found entity: TYCent entpath: [#L.52,#L.1] Error: Compiler bug: EntityEnv: lookEnt.2 uncaught exception TopLevelException [Error] raised at: util/errormsg.sml:54.14-54.19 modules/instantiate.sml:1122.9 elaborate/elabmod.sml:1119.8 util/stats.sml:164.40 build/evalloop.sml:123.38 build/evalloop.sml:196.58 build/evalloop.sml:289.46-289.49 Comments: Zhong says: I found a fix for the bug. The bug was caused by Dave and Matthias's recent changes on turning off "pickling" in the top level (sigh ...). In fact, a more severe bug is the test case below. It turns out that the mkStamp function is making new stamp from 0 when compiling each compilation unit (hmmm, not quite accurate, look when evalLoop is called in interact.sml). So t and s share the same stamp (L0). If we do pickling, s and t's stamps will be globalized during the pickling, so they will not be indentified. For the ML-Yacc, it is the similar reason. Because the stamp is not unique, the entity variable created for each signature component is not unique, this confuses the elaborator thus causing the bug. Fix: I make sure that the compiler never resets the global stamp counter --- notice that if the interactive loop is long enough (e.g., even after exportML,...); it is possible to run out of the stamps (i.e., overflow) --- especially the same stamp counter is now used for multiple purposes (stamp, entvar, ...). With pickling, the counter is reset each time and the pickler always globalize all the stamps (even hidden ones) with an external pid ! Test: (* typing in each of the following at the top-level *) local datatype t = A in val x = A end; junk; (* this line is crucial; the purpose is to cause an error *) local datatype s = B in val y = B end; x = y; (* The compiler accepts the "x = y", and producing true. *) Owner: dbm, blume, zsh Status: fixed in 109.31 ---------------------------------------------------------------------- Number: 1261 Title: explicit type parameter with "val rec" not supported Keywords: syntax, explicit type parameters Submitter: Dave MacQueen Date: 9/4/97 Version: 109.30 System: - Severity: minor Problem: Syntax "val 'a rec ..." not implemented. Transcript: - val 'a rec f = fn x : 'a => x; stdIn:14.8-14.15 Error: syntax error: deleting REC ID EQUALOP stdIn:14.16-14.22 Error: syntax error: deleting FN ID COLON stdIn:14.23-14.28 Error: syntax error: deleting TYVAR DARROW Comments: Fix: Test: bug1261.sml Owner: dbm, Appel Status: open ---------------------------------------------------------------------- Number: 1262 Title: literal ~0.0 reads as 0.0 Keywords: floating point, literals Submitter: appel Date: August 19, 1997 Version: 109.30 System: any Severity: minor Problem: literal ~0.0 reads as 0.0 Code: Real.copysign(1.0,~0.0) Transcript: val it = 1.0 Comments: Fix: in first if-statement of ieeereal.sml Test: bug1262.sml Owner: Appel Status: open ---------------------------------------------------------------------- Number: 1263 Title: sqrt, ln incorrect on subnormal numbers Keywords: floating point, math Submitter: appel Date: August 19, 1997 Version: 109.30 System: any Severity: minor Problem: sqrt, ln incorrect on subnormal numbers Code: let val a = Math.sqrt(Real.minNormalPos * 0.1) in [Real.minNormalPos*0.1, a*a] end Transcript: val it = [2.22507385851e~309,1.22379062218e~308] : real list Comments: The scalb and logb functions in math64.sml called upon Assembly.A.scalb,logb, and were already augmented to handle a bigger range of cases than the assembly-lang primops, but I made them even fancier to handle subnormal inputs and outputs. Status: fixed in 109.31 ---------------------------------------------------------------------- Number: 1264 Title: (spurious) dependency cycle in instantiate Keywords: modules, opaque signatures Submitter: manuel@cs.berkeleye.edu Date: 8/19/97 Version: SML-109.27 + blume patch System: x86-linux, sparc-solaris2.5 Severity: major Problem: Opaque signature matching fails when the structure contains a functor whose signature has where specifications. Produces uncaught exception Unbound and a message "dependency cycle in instantiate" Code: signature S = sig type genT type T val embed : T -> genT end; structure S = struct type genT = int type T = int val embed = fn x => x end; signature B = sig type genT functor mkS() : S where type genT = genT end; structure B :> B = struct type genT = S.genT functor mkS() = S end; Transcript: - use "bug_inst.sml"; [opening bug_inst.sml] bug_inst.sml:29.1-35.8 Error: dependency cycle in instantiate uncaught exception Unbound raised at: elaborate/elabmod.sml:1060.15-1060.25 util/stats.sml:164.40 build/evalloop.sml:123.38 build/evalloop.sml:196.58 build/evalloop.sml:289.46-289.49 - Comments: The idea behind this code is to create new structures using B.mkS(), each of which will share the type genT, but not the type T. The desired behavior can be obtained with the following code, which moves the opaque matching from B to the functor. The difference to the code above is in that genT is not opaque in B. signature S = sig type genT type T val embed : T -> genT val new : int -> T val show : genT -> unit end structure S = struct type genT = int type T = int val embed = fn x => x fun new x = x val show = fn x => print (Int.toString x ^"\n") end signature B = sig type genT functor mkS() : S where type genT = genT end structure B : B = struct type genT = S.genT functor mkS() :> S where type genT = genT = S end structure X = B.mkS; structure Y = B.mkS; val x = X.new 5; val y = Y.new 7; val xe = X.embed x; val ye = X.embed y; val _ = X.show ye; (* is accepted correctly *) val _ = Y.show xe; (* is accepted correctly *) val xf = Y.embed x; (* rejected correctly *) val yf = X.embed y; (* rejected correctly *) val _ = X.show 5; (* genT isn't opaque. *) Fix: Test: bug1264.sml Owner: Zhong Status: fixed in 109.31 [Zhong, 8/21/97] ---------------------------------------------------------------------- Number: 1265 Title: uncaught Match exn in elabmod.sml:632.7 Keywords: module elaboration, signature matching Submitter: manuel@cs.berkeley.edu Date: 8/19/97 Version: 109.30 + Matthias Blume patch System: x86-linux, sparc-solaris2.5 Severity: major Problem: Signature matching causes Match exception in compiler Code: structure J : S = K : T; Transcript: - structure J : S = K : T; uncaught exception in compiler: nonexhaustive match failure raised at: elaborate/elabmod.sml:632.7 elaborate/elabmod.sml:1059.8 util/stats.sml:164.40 build/evalloop.sml:123.38 build/evalloop.sml:196.58 - Comments: Fix: Test: bug1265.sml Owner: Zhong, dbm Status: fixed in 109.31 ---------------------------------------------------------------------- Number: 1266 Title: OS.Process.atExit does not agree with basis documentation Keywords: standard basis Submitter: Chris Stone, cstone+@cs.cmu.edu Perry Cheng, pscheng+@cs.cmu.edu Date: August 19, 1997 Version: 109.30 System: Alpha OSF/1 3.2 Severity: minor Problem: From the on-line standard basis documentation for OS.Process.atExit: Calls to exit do not return, but should cause the remainder of the functions registered with atExit to be executed. The code does not have this behavior. Transcript: Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] - OS.Process.atExit (fn _ => print "1\n"); val it = () : unit - OS.Process.atExit (fn _ => print "2\n"); val it = () : unit - OS.Process.atExit (fn _ => print "3\n"); val it = () : unit - ^D3 2 1 Standard ML of New Jersey, Version 109.30, July 17, 1997 [CM; autoload enabled] - OS.Process.atExit (fn _ => print "1\n"); val it = () : unit - OS.Process.atExit (fn _ => OS.Process.exit 1); val it = () : unit - OS.Process.atExit (fn _ => print "3\n"); val it = () : unit - ^D3 3 3 3 ...[infinite loop] Comments: A quick glance at the file NJ/cleanup.sml led us to initially expect that the call to exit would terminate the program immediately, skipping the third function registered with atExit. However, it turns out that since the "clean" function does not change the list "hooks" when called with the AtExit parameter, the call to exit starts re-invoking all of the functions registered with AtExit. Fix: * Test: * Owner: jhr Status: fixed in 109.31 [jhr, 8/19/97] ---------------------------------------------------------------------- Number: 1267 (duplicate of bug 1259) Title: Mistakenly inadmissable signature. Keywords: modules, signatures, definition specs, datatype specs Submitter: Stephen Weeks Date: 8/19/97 Version: 109.30 System: x86-linux Severity: minor Problem: The following signature is not accepted by SML/NJ 109.30, even though it should be. SML/NJ 109.30 returns the message "Error: dependency cycle in instantiate". Earlier versions, such as 109.29, accepted this signature. signature SIG = sig type b' datatype a = A1 | A2 of b' datatype b = B1 | B2 of a sharing type b = b' end The signature is accepted when it directly constrains a structure, as in the following code. structure S : sig type b' datatype a = A1 | A2 of b' datatype b = B1 | B2 of a sharing type b = b' end = struct datatype a = A1 | A2 of b and b = B1 | B2 of a type b' = b end Code: Transcript: Comments: [Zhong, 8/21/97] |> In any case, both versions are wrong to reject the signature, since it |> can be instantiated by the structure I provided. |> |> structure S : sig |> type b' |> datatype a = A1 | A2 of b' |> datatype b = B1 | B2 of a |> sharing type b = b' |> end = |> struct |> datatype a = A1 | A2 of b |> and b = B1 | B2 of a |> type b' = b |> end I'd not say our implementation is wrong :-) I'd argue that it is the Definition that is wrong --- in fact, the Definition is vague on how the above signature will be elaborated --- if you follow what's said in the Definition, you will get a structure of the form structure SIG-INST = struct type b' = b datatype a = A1 | A2 of b datatype b = B1 | B2 of a end Notice I have no way to reorder the above into a valid ML structure. The best I can do is: structure SIG-INST = struct datatype a = A1 | A2 of b datatype b = B1 | B2 of a type b' = b end still type a and b are mutually recursive. To make it work, the signature elaboration has to make a and b mutually recursive: structure SIG-INST = struct datatype a = A1 | A2 of b and b = B1 | B2 of a type b' = b end This is non-trivial to generalize to cover other cases; for example, what if SIG is like the following: signature SIG' = sig type b' datatype a = A1 | A2 of b' structure S : sig datatype b = B1 | B2 of a end sharing type b' = S.b' end SIG' probably will not match any structure, but it is very hard to discover what is match-able and what is not. Because of all these, we decided to adopt a simpler algorithm in SML/NJ --- we'll only do reorgan