8.4 Common errors

8.4.1. Cannot find file filename
8.4.2. Corrupted compiled interface filename
8.4.3. This expression has type t_1, but is used with type t_2
8.4.4. The type of this expression, t, contains type variables that cannot be generalized
8.4.5. Reference to undefined global mod
8.4.6. The external function f is not available

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

8.4.1 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.

If filename has the format mod.cmo, this means you are trying to link a bytecode object file that does not exist yet. Fix: compile mod.ml first.

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 -I options to the command line.

8.4.2 Corrupted compiled interface filename

The compiler produces this error when it tries to read a compiled interface file (.cmi file) that has the wrong structure. This means something went wrong when this .cmi file 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 .cmi file, and rebuild it.

8.4.3 This expression has type t_1, but is used with type t_2

This is by far the most common type error in programs. Type t_1 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. Type t_2 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 types t_1 and t_2 are not compatible, then the error above is produced.

In some cases, it is hard to understand why the two types t_1 and t_2 are incompatible. For instance, the compiler can report that "expression of type foo cannot be used with type foo", 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 "expression C of type foo cannot be used with type foo".

8.4.4 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 generalized (which means that the type t is valid only for one instantiation of the variables). In a let binding let 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, generalization is performed at let bindings only if the bound expression expr belongs 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 (ref is 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 value name whose type contains non-generalized type variables.

There are two ways to fix this error:

  • Add a type constraint or a .mli file to give a monomorphic type (without type variables) to name. 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

8.4.5 Reference to undefined global mod

このエラーは不完全または不正確な順番でファイルをリンクしようとしたとき、または mod という名前のコンパイルユニットの実装 (普通このファイルは mod.cmo という名前か、ライブラリ中にそういう名前で入っているかのどちらか) をコマンドラインに指定し忘れていたときに発生します。 .ml.cmo ファイルをコマンドラインに追加してください。 mod という名前のモジュールを含む実装をちゃんとコマンドラインに指定している場合は、コマンドライン上の位置が後ろすぎるのでしょう。 mod の実装は mod を参照するバイトコードオブジェクトファイルのどれよりも前にないといけません。 コマンドライン上の .ml.cmo ファイルの順番を適当に変えてください。

このエラーはモジュール間で相互再帰する関数を作ると当然発生します。 つまり関数 Mod1.f が関数 Mod2.g を呼び、かつ関数 Mod2.g が関数 Mod1.f を呼ぶときです。 この場合、コマンドラインの順番をどのように変えてもプログラムはリンク時に拒否されます。 対策として以下のようにしてください。

  • 関数 fg は同じモジュールに置く。

  • 片方から関数をパラメータ化する。 つまり、次のような例は

    mod1.ml:    let f x = ... Mod2.g ...
    mod2.ml:    let g y = ... Mod1.f ...

    以下のように定義します。

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

    リンクは mod1.cmomod2.cmo より前にしてください。

  • 片方の関数を持つ参照を使う

    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

8.4.6 The external function f is not available

このエラーは C で書かれた外部関数を呼ぶコードをリンクするとき発生します。 18 章で説明するように、f という C 関数を使用する実装は C ライブラリとリンクしなければいけません。 C ライブラリが共有ライブラリ (DLL) でない場合は、カスタムランタイムモードでリンクしなければなりません。 コマンドラインに使用する C ライブラリを追加して、必要なら -custom オプションも追加してください。