• Aucun résultat trouvé

Common errors

Dans le document The Objective Caml system release 3.12 (Page 164-167)

Batch compilation (ocamlc)

8.4 Common errors

This section describes and explains the most frequently encountered error messages.

Cannot find file filename

The named file could not be found in the current directory, nor in the directories of the search path. The filename is either a compiled interface file (.cmi file), or a compiled bytecode file (.cmo file). If filename has the format mod.cmi, this means you are trying to compile a file that references identifiers from module mod, but you have not yet compiled an interface for module mod. Fix: compile mod.mli or mod.ml first, to create the compiled interface mod.cmi.

Iffilename has the format mod.cmo, this means you are trying to link a bytecode object file that does not exist yet. Fix: compilemod.mlfirst.

If your program spans several directories, this error can also appear because you haven’t specified the directories to look into. Fix: add the correct -Ioptions to the command line.

Corrupted compiled interface filename

The compiler produces this error when it tries to read a compiled interface file (.cmifile) that has the wrong structure. This means something went wrong when this.cmifile was written:

the disk was full, the compiler was interrupted in the middle of the file creation, and so on.

This error can also appear if a .cmi file is modified after its creation by the compiler. Fix:

remove the corrupted .cmifile, and rebuild it.

This expression has type t1, but is used with type t2

This is by far the most common type error in programs. Type t1 is the type inferred for the expression (the part of the program that is displayed in the error message), by looking at the expression itself. Typet2 is the type expected by the context of the expression; it is deduced by looking at how the value of this expression is used in the rest of the program. If the two typest1 and t2 are not compatible, then the error above is produced.

In some cases, it is hard to understand why the two types t1 and t2 are incompatible. For instance, the compiler can report that “expression of typefoocannot be used with typefoo”, and it really seems that the two types foo are compatible. This is not always true. Two type constructors can have the same name, but actually represent different types. This can happen if a type constructor is redefined. Example:

type foo = A | B

let f = function A -> 0 | B -> 1 type foo = C | D

f C

This result in the error message “expressionCof type foocannot be used with typefoo”.

The type of this expression, t, contains type variables that cannot be generalized Type variables (’a, ’b, . . . ) in a type t can be in either of two states: generalized (which means that the type t is valid for all possible instantiations of the variables) and not gener-alized (which means that the typet is valid only for one instantiation of the variables). In a letbindinglet name = expr, the type-checker normally generalizes as many type variables as possible in the type of expr. However, this leads to unsoundness (a well-typed program can crash) in conjunction with polymorphic mutable data structures. To avoid this, general-ization is performed atletbindings only if the bound expression exprbelongs to the class of

“syntactic values”, which includes constants, identifiers, functions, tuples of syntactic values, etc. In all other cases (for instance, expr is a function application), a polymorphic mutable could have been created and generalization is therefore turned off for all variables occuring in contravariant or non-variant branches of the type. For instance, if the type of a non-value is’a list the variable is generalizable (list is a covariant type constructor), but not in ’a list -> ’a list(the left branch of-> is contravariant) or’a ref(refis non-variant).

Non-generalized type variables in a type cause no difficulties inside a given structure or compilation unit (the contents of a .ml file, or an interactive session), but they cannot be allowed inside signatures nor in compiled interfaces (.cmi file), because they could be used inconsistently later. Therefore, the compiler flags an error when a structure or compilation unit defines a valuenamewhose type contains non-generalized type variables. There are two ways to fix this error:

• Add a type constraint or a.mlifile to give a monomorphic type (without type variables) toname. For instance, instead of writing

let sort_int_list = Sort.list (<)

(* inferred type ’a list -> ’a list, with ’a not generalized *) write

let sort_int_list = (Sort.list (<) : int list -> int list);;

• If you really need name to have a polymorphic type, turn its defining expression into a function by adding an extra parameter. For instance, instead of writing

let map_length = List.map Array.length

(* inferred type ’a array list -> int list, with ’a not generalized *) write

let map_length lv = List.map Array.length lv Reference to undefined global mod

This error appears when trying to link an incomplete or incorrectly ordered set of files. Either

you have forgotten to provide an implementation for the compilation unit namedmodon the command line (typically, the file namedmod.cmo, or a library containing that file). Fix: add the missing.mlor.cmo file to the command line. Or, you have provided an implementation for the module named mod, but it comes too late on the command line: the implementation of modmust come before all bytecode object files that reference mod. Fix: change the order of .mland .cmofiles on the command line.

Of course, you will always encounter this error if you have mutually recursive functions across modules. That is, functionMod1.fcalls function Mod2.g, and functionMod2.gcalls function Mod1.f. In this case, no matter what permutations you perform on the command line, the program will be rejected at link-time. Fixes:

• Putfand gin the same module.

• Parameterize one function by the other. That is, instead of having mod1.ml: let f x = ... Mod2.g ...

mod2.ml: let g y = ... Mod1.f ...

define

mod1.ml: let f g x = ... g ...

mod2.ml: let rec g y = ... Mod1.f g ...

and linkmod1.cmobeforemod2.cmo.

• Use a reference to hold one of the two functions, as in : mod1.ml: let forward_g =

ref((fun x -> failwith "forward_g") : <type>) let f x = ... !forward_g ...

mod2.ml: let g y = ... Mod1.f ...

let _ = Mod1.forward_g := g The external function f is not available

This error appears when trying to link code that calls external functions written in C. As explained in chapter 18, such code must be linked with C libraries that implement the required fC function. If the C libraries in question are not shared libraries (DLLs), the code must be linked in “custom runtime” mode. Fix: add the required C libraries to the command line, and possibly the -customoption.

Dans le document The Objective Caml system release 3.12 (Page 164-167)