summaryrefslogtreecommitdiff
path: root/toplevel/himsg.ml
diff options
context:
space:
mode:
Diffstat (limited to 'toplevel/himsg.ml')
-rw-r--r--toplevel/himsg.ml1078
1 files changed, 667 insertions, 411 deletions
diff --git a/toplevel/himsg.ml b/toplevel/himsg.ml
index 8dd18163..9341f2f7 100644
--- a/toplevel/himsg.ml
+++ b/toplevel/himsg.ml
@@ -1,6 +1,6 @@
(************************************************************************)
(* v * The Coq Proof Assistant / The Coq Development Team *)
-(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2014 *)
+(* <O___,, * INRIA - CNRS - LIX - LRI - PPS - Copyright 1999-2015 *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
@@ -8,32 +8,131 @@
open Pp
open Util
-open Flags
open Names
open Nameops
open Namegen
open Term
open Termops
-open Inductive
open Indtypes
-open Sign
open Environ
open Pretype_errors
open Type_errors
open Typeclasses_errors
open Indrec
-open Reduction
open Cases
open Logic
open Printer
-open Glob_term
open Evd
-open Libnames
-open Declarations
+
+(* This simplifies the typing context of Cases clauses *)
+(* hope it does not disturb other typing contexts *)
+let contract env lc =
+ let l = ref [] in
+ let contract_context (na,c,t) env =
+ match c with
+ | Some c' when isRel c' ->
+ l := (Vars.substl !l c') :: !l;
+ env
+ | _ ->
+ let t' = Vars.substl !l t in
+ let c' = Option.map (Vars.substl !l) c in
+ let na' = named_hd env t' na in
+ l := (mkRel 1) :: List.map (Vars.lift 1) !l;
+ push_rel (na',c',t') env in
+ let env = process_rel_context contract_context env in
+ (env, List.map (Vars.substl !l) lc)
+
+let contract2 env a b = match contract env [a;b] with
+ | env, [a;b] -> env,a,b | _ -> assert false
+
+let contract3 env a b c = match contract env [a;b;c] with
+ | env, [a;b;c] -> env,a,b,c | _ -> assert false
+
+let contract4 env a b c d = match contract env [a;b;c;d] with
+ | env, [a;b;c;d] -> (env,a,b,c),d | _ -> assert false
+
+let contract1_vect env a v =
+ match contract env (a :: Array.to_list v) with
+ | env, a::l -> env,a,Array.of_list l
+ | _ -> assert false
+
+let rec contract3' env a b c = function
+ | OccurCheck (evk,d) -> let x,d = contract4 env a b c d in x,OccurCheck(evk,d)
+ | NotClean ((evk,args),env',d) ->
+ let env',d,args = contract1_vect env' d args in
+ contract3 env a b c,NotClean((evk,args),env',d)
+ | ConversionFailed (env',t1,t2) ->
+ let (env',t1,t2) = contract2 env' t1 t2 in
+ contract3 env a b c, ConversionFailed (env',t1,t2)
+ | NotSameArgSize | NotSameHead | NoCanonicalStructure
+ | MetaOccurInBody _ | InstanceNotSameType _
+ | UnifUnivInconsistency _ as x -> contract3 env a b c, x
+ | CannotSolveConstraint ((pb,env,t,u),x) ->
+ let env,t,u = contract2 env t u in
+ let y,x = contract3' env a b c x in
+ y,CannotSolveConstraint ((pb,env,t,u),x)
+
+(** Printers *)
let pr_lconstr c = quote (pr_lconstr c)
-let pr_lconstr_env e c = quote (pr_lconstr_env e c)
-let pr_ljudge_env e c = let v,t = pr_ljudge_env e c in (quote v,quote t)
+let pr_lconstr_env e s c = quote (pr_lconstr_env e s c)
+let pr_ljudge_env e s c = let v,t = pr_ljudge_env e s c in (quote v,quote t)
+
+(** A canonisation procedure for constr such that comparing there
+ externalisation catches more equalities *)
+let canonize_constr c =
+ (* replaces all the names in binders by [dn] ("default name"),
+ ensures that [alpha]-equivalent terms will have the same
+ externalisation. *)
+ let dn = Name.Anonymous in
+ let rec canonize_binders c =
+ match Term.kind_of_term c with
+ | Prod (_,t,b) -> mkProd(dn,t,b)
+ | Lambda (_,t,b) -> mkLambda(dn,t,b)
+ | LetIn (_,u,t,b) -> mkLetIn(dn,u,t,b)
+ | _ -> Term.map_constr canonize_binders c
+ in
+ canonize_binders c
+
+(** Tries to realize when the two terms, albeit different are printed the same. *)
+let display_eq ~flags env sigma t1 t2 =
+ (* terms are canonized, then their externalisation is compared syntactically *)
+ let open Constrextern in
+ let t1 = canonize_constr t1 in
+ let t2 = canonize_constr t2 in
+ let ct1 = Flags.with_options flags (fun () -> extern_constr false env sigma t1) () in
+ let ct2 = Flags.with_options flags (fun () -> extern_constr false env sigma t2) () in
+ Constrexpr_ops.constr_expr_eq ct1 ct2
+
+(** This function adds some explicit printing flags if the two arguments are
+ printed alike. *)
+let rec pr_explicit_aux env sigma t1 t2 = function
+| [] ->
+ (** no specified flags: default. *)
+ (quote (Printer.pr_lconstr_env env sigma t1), quote (Printer.pr_lconstr_env env sigma t2))
+| flags :: rem ->
+ let equal = display_eq ~flags env sigma t1 t2 in
+ if equal then
+ (** The two terms are the same from the user point of view *)
+ pr_explicit_aux env sigma t1 t2 rem
+ else
+ let open Constrextern in
+ let ct1 = Flags.with_options flags (fun () -> extern_constr false env sigma t1) ()
+ in
+ let ct2 = Flags.with_options flags (fun () -> extern_constr false env sigma t2) ()
+ in
+ quote (Ppconstr.pr_lconstr_expr ct1), quote (Ppconstr.pr_lconstr_expr ct2)
+
+let explicit_flags =
+ let open Constrextern in
+ [ []; (** First, try with the current flags *)
+ [print_implicits]; (** Then with implicit *)
+ [print_universes]; (** Then with universes *)
+ [print_universes; print_implicits]; (** With universes AND implicits *)
+ [print_implicits; print_coercions; print_no_symbol]; (** Then more! *)
+ [print_universes; print_implicits; print_coercions; print_no_symbol] (** and more! *) ]
+
+let pr_explicit env sigma t1 t2 = pr_explicit_aux env sigma t1 t2 explicit_flags
let pr_db env i =
try
@@ -42,8 +141,8 @@ let pr_db env i =
| Anonymous, _, _ -> str "<>"
with Not_found -> str "UNBOUND_REL_" ++ int i
-let explain_unbound_rel env n =
- let pe = pr_ne_context_of (str "In environment") env in
+let explain_unbound_rel env sigma n =
+ let pe = pr_ne_context_of (str "In environment") env sigma in
str "Unbound reference: " ++ pe ++
str "The reference " ++ int n ++ str " is free."
@@ -52,24 +151,25 @@ let explain_unbound_var env v =
str "No such section variable or assumption: " ++ var ++ str "."
let explain_not_type env sigma j =
- let j = j_nf_evar sigma j in
- let pe = pr_ne_context_of (str "In environment") env in
- let pc,pt = pr_ljudge_env env j in
+ let j = Evarutil.j_nf_evar sigma j in
+ let pe = pr_ne_context_of (str "In environment") env sigma in
+ let pc,pt = pr_ljudge_env env sigma j in
pe ++ str "The term" ++ brk(1,1) ++ pc ++ spc () ++
str "has type" ++ spc () ++ pt ++ spc () ++
str "which should be Set, Prop or Type."
-let explain_bad_assumption env j =
- let pe = pr_ne_context_of (str "In environment") env in
- let pc,pt = pr_ljudge_env env j in
+let explain_bad_assumption env sigma j =
+ let pe = pr_ne_context_of (str "In environment") env sigma in
+ let pc,pt = pr_ljudge_env env sigma j in
pe ++ str "Cannot declare a variable or hypothesis over the term" ++
brk(1,1) ++ pc ++ spc () ++ str "of type" ++ spc () ++ pt ++ spc () ++
str "because this term is not a type."
-let explain_reference_variables c =
- let pc = pr_lconstr c in
- str "The constant" ++ spc () ++ pc ++ spc () ++
- str "refers to variables which are not in the context."
+let explain_reference_variables id c =
+ (* c is intended to be a global reference *)
+ let pc = pr_global (Globnames.global_of_constr c) in
+ pc ++ strbrk " depends on the variable " ++ pr_id id ++
+ strbrk " which is not declared in the context."
let rec pr_disjunction pr = function
| [a] -> pr a
@@ -77,10 +177,16 @@ let rec pr_disjunction pr = function
| a::l -> pr a ++ str "," ++ spc () ++ pr_disjunction pr l
| [] -> assert false
-let explain_elim_arity env ind sorts c pj okinds =
+let pr_puniverses f env (c,u) =
+ f env c ++
+ (if Flags.is_universe_polymorphism () && not (Univ.Instance.is_empty u) then
+ str"(*" ++ Univ.Instance.pr Universes.pr_with_global_universes u ++ str"*)"
+ else mt())
+
+let explain_elim_arity env sigma ind sorts c pj okinds =
let env = make_all_name_different env in
- let pi = pr_inductive env ind in
- let pc = pr_lconstr_env env c in
+ let pi = pr_inductive env (fst ind) in
+ let pc = pr_lconstr_env env sigma c in
let msg = match okinds with
| Some(kp,ki,explanation) ->
let pki = pr_sort_family ki in
@@ -93,7 +199,7 @@ let explain_elim_arity env ind sorts c pj okinds =
| WrongArity ->
"wrong arity" in
let ppar = pr_disjunction (fun s -> quote (pr_sort_family s)) sorts in
- let ppt = pr_lconstr_env env ((strip_prod_assum pj.uj_type)) in
+ let ppt = pr_lconstr_env env sigma ((strip_prod_assum pj.uj_type)) in
hov 0
(str "the return type has sort" ++ spc () ++ ppt ++ spc () ++
str "while it" ++ spc () ++ str "should be " ++ ppar ++ str ".") ++
@@ -112,10 +218,10 @@ let explain_elim_arity env ind sorts c pj okinds =
fnl () ++ msg
let explain_case_not_inductive env sigma cj =
- let cj = j_nf_evar sigma cj in
+ let cj = Evarutil.j_nf_evar sigma cj in
let env = make_all_name_different env in
- let pc = pr_lconstr_env env cj.uj_val in
- let pct = pr_lconstr_env env cj.uj_type in
+ let pc = pr_lconstr_env env sigma cj.uj_val in
+ let pct = pr_lconstr_env env sigma cj.uj_type in
match kind_of_term cj.uj_type with
| Evar _ ->
str "Cannot infer a type for this expression."
@@ -125,116 +231,177 @@ let explain_case_not_inductive env sigma cj =
str "which is not a (co-)inductive type."
let explain_number_branches env sigma cj expn =
- let cj = j_nf_evar sigma cj in
+ let cj = Evarutil.j_nf_evar sigma cj in
let env = make_all_name_different env in
- let pc = pr_lconstr_env env cj.uj_val in
- let pct = pr_lconstr_env env cj.uj_type in
+ let pc = pr_lconstr_env env sigma cj.uj_val in
+ let pct = pr_lconstr_env env sigma cj.uj_type in
str "Matching on term" ++ brk(1,1) ++ pc ++ spc () ++
str "of type" ++ brk(1,1) ++ pct ++ spc () ++
str "expects " ++ int expn ++ str " branches."
let explain_ill_formed_branch env sigma c ci actty expty =
- let simp t = Reduction.nf_betaiota (nf_evar sigma t) in
- let c = nf_evar sigma c in
+ let simp t = Reduction.nf_betaiota env (Evarutil.nf_evar sigma t) in
+ let c = Evarutil.nf_evar sigma c in
let env = make_all_name_different env in
- let pc = pr_lconstr_env env c in
- let pa = pr_lconstr_env env (simp actty) in
- let pe = pr_lconstr_env env (simp expty) in
+ let pc = pr_lconstr_env env sigma c in
+ let pa, pe = pr_explicit env sigma (simp actty) (simp expty) in
strbrk "In pattern-matching on term" ++ brk(1,1) ++ pc ++
spc () ++ strbrk "the branch for constructor" ++ spc () ++
- quote (pr_constructor env ci) ++
+ quote (pr_puniverses pr_constructor env ci) ++
spc () ++ str "has type" ++ brk(1,1) ++ pa ++ spc () ++
str "which should be" ++ brk(1,1) ++ pe ++ str "."
-let explain_generalization env (name,var) j =
- let pe = pr_ne_context_of (str "In environment") env in
- let pv = pr_ltype_env env var in
- let (pc,pt) = pr_ljudge_env (push_rel_assum (name,var) env) j in
+let explain_generalization env sigma (name,var) j =
+ let pe = pr_ne_context_of (str "In environment") env sigma in
+ let pv = pr_ltype_env env sigma var in
+ let (pc,pt) = pr_ljudge_env (push_rel_assum (name,var) env) sigma j in
pe ++ str "Cannot generalize" ++ brk(1,1) ++ pv ++ spc () ++
str "over" ++ brk(1,1) ++ pc ++ str "," ++ spc () ++
str "it has type" ++ spc () ++ pt ++
spc () ++ str "which should be Set, Prop or Type."
-let explain_actual_type env sigma j pt =
- let j = j_nf_betaiotaevar sigma j in
- let pt = Reductionops.nf_betaiota sigma pt in
- let pe = pr_ne_context_of (str "In environment") env in
- let (pc,pct) = pr_ljudge_env env j in
- let pt = pr_lconstr_env env pt in
+let rec explain_unification_error env sigma p1 p2 = function
+ | None -> mt()
+ | Some e ->
+ let rec aux p1 p2 = function
+ | OccurCheck (evk,rhs) ->
+ let rhs = Evarutil.nf_evar sigma rhs in
+ [str "cannot define " ++ quote (pr_existential_key sigma evk) ++
+ strbrk " with term " ++ pr_lconstr_env env sigma rhs ++
+ strbrk " that would depend on itself"]
+ | NotClean ((evk,args),env,c) ->
+ let c = Evarutil.nf_evar sigma c in
+ let args = Array.map (Evarutil.nf_evar sigma) args in
+ [str "cannot instantiate " ++ quote (pr_existential_key sigma evk)
+ ++ strbrk " because " ++ pr_lconstr_env env sigma c ++
+ strbrk " is not in its scope" ++
+ (if Array.is_empty args then mt() else
+ strbrk ": available arguments are " ++
+ pr_sequence (pr_lconstr_env env sigma) (List.rev (Array.to_list args)))]
+ | NotSameArgSize | NotSameHead | NoCanonicalStructure ->
+ (* Error speaks from itself *) []
+ | ConversionFailed (env,t1,t2) ->
+ if Term.eq_constr t1 p1 && Term.eq_constr t2 p2 then [] else
+ let env = make_all_name_different env in
+ let t1 = Evarutil.nf_evar sigma t1 in
+ let t2 = Evarutil.nf_evar sigma t2 in
+ if not (Term.eq_constr t1 p1) || not (Term.eq_constr t2 p2) then
+ let t1, t2 = pr_explicit env sigma t1 t2 in
+ [str "cannot unify " ++ t1 ++ strbrk " and " ++ t2]
+ else []
+ | MetaOccurInBody evk ->
+ [str "instance for " ++ quote (pr_existential_key sigma evk) ++
+ strbrk " refers to a metavariable - please report your example"]
+ | InstanceNotSameType (evk,env,t,u) ->
+ let t, u = pr_explicit env sigma t u in
+ [str "unable to find a well-typed instantiation for " ++
+ quote (pr_existential_key sigma evk) ++
+ strbrk ": cannot ensure that " ++
+ t ++ strbrk " is a subtype of " ++ u]
+ | UnifUnivInconsistency p ->
+ if !Constrextern.print_universes then
+ [str "universe inconsistency: " ++
+ Univ.explain_universe_inconsistency Universes.pr_with_global_universes p]
+ else
+ [str "universe inconsistency"]
+ | CannotSolveConstraint ((pb,env,t,u),e) ->
+ let t = Evarutil.nf_evar sigma t in
+ let u = Evarutil.nf_evar sigma u in
+ (strbrk "cannot satisfy constraint " ++ pr_lconstr_env env sigma t ++
+ str " == " ++ pr_lconstr_env env sigma u)
+ :: aux t u e
+ in
+ match aux p1 p2 e with
+ | [] -> mt ()
+ | l -> spc () ++ str "(" ++
+ prlist_with_sep pr_semicolon (fun x -> x) l ++ str ")"
+
+let explain_actual_type env sigma j t reason =
+ let env = make_all_name_different env in
+ let j = Evarutil.j_nf_betaiotaevar sigma j in
+ let t = Reductionops.nf_betaiota sigma t in
+ (** Actually print *)
+ let pe = pr_ne_context_of (str "In environment") env sigma in
+ let pc = pr_lconstr_env env sigma (Environ.j_val j) in
+ let (pt, pct) = pr_explicit env sigma t (Environ.j_type j) in
+ let ppreason = explain_unification_error env sigma j.uj_type t reason in
pe ++
+ hov 0 (
str "The term" ++ brk(1,1) ++ pc ++ spc () ++
- str "has type" ++ brk(1,1) ++ pct ++ brk(1,1) ++
- str "while it is expected to have type" ++ brk(1,1) ++ pt ++ str "."
+ str "has type" ++ brk(1,1) ++ pct ++ spc () ++
+ str "while it is expected to have type" ++ brk(1,1) ++ pt ++
+ ppreason ++ str ".")
let explain_cant_apply_bad_type env sigma (n,exptyp,actualtyp) rator randl =
- let randl = jv_nf_betaiotaevar sigma randl in
- let exptyp = nf_evar sigma exptyp in
+ let randl = Evarutil.jv_nf_betaiotaevar sigma randl in
+ let exptyp = Evarutil.nf_evar sigma exptyp in
let actualtyp = Reductionops.nf_betaiota sigma actualtyp in
- let rator = j_nf_evar sigma rator in
+ let rator = Evarutil.j_nf_evar sigma rator in
let env = make_all_name_different env in
+ let actualtyp, exptyp = pr_explicit env sigma actualtyp exptyp in
let nargs = Array.length randl in
-(* let pe = pr_ne_context_of (str "in environment") env in*)
- let pr,prt = pr_ljudge_env env rator in
- let term_string1 = str (plural nargs "term") in
+(* let pe = pr_ne_context_of (str "in environment") env sigma in*)
+ let pr,prt = pr_ljudge_env env sigma rator in
+ let term_string1 = str (String.plural nargs "term") in
let term_string2 =
- if nargs>1 then str "The " ++ nth n ++ str " term" else str "This term" in
- let appl = prvect_with_sep pr_fnl
+ if nargs>1 then str "The " ++ pr_nth n ++ str " term" else str "This term"
+ in
+ let appl = prvect_with_sep fnl
(fun c ->
- let pc,pct = pr_ljudge_env env c in
+ let pc,pct = pr_ljudge_env env sigma c in
hov 2 (pc ++ spc () ++ str ": " ++ pct)) randl
in
- str "Illegal application (Type Error): " ++ (* pe ++ *) fnl () ++
+ str "Illegal application: " ++ (* pe ++ *) fnl () ++
str "The term" ++ brk(1,1) ++ pr ++ spc () ++
str "of type" ++ brk(1,1) ++ prt ++ spc () ++
str "cannot be applied to the " ++ term_string1 ++ fnl () ++
str " " ++ v 0 appl ++ fnl () ++ term_string2 ++ str " has type" ++
- brk(1,1) ++ pr_lconstr_env env actualtyp ++ spc () ++
+ brk(1,1) ++ actualtyp ++ spc () ++
str "which should be coercible to" ++ brk(1,1) ++
- pr_lconstr_env env exptyp ++ str "."
+ exptyp ++ str "."
let explain_cant_apply_not_functional env sigma rator randl =
- let randl = jv_nf_evar sigma randl in
- let rator = j_nf_evar sigma rator in
+ let randl = Evarutil.jv_nf_evar sigma randl in
+ let rator = Evarutil.j_nf_evar sigma rator in
let env = make_all_name_different env in
let nargs = Array.length randl in
-(* let pe = pr_ne_context_of (str "in environment") env in*)
- let pr = pr_lconstr_env env rator.uj_val in
- let prt = pr_lconstr_env env rator.uj_type in
- let appl = prvect_with_sep pr_fnl
+(* let pe = pr_ne_context_of (str "in environment") env sigma in*)
+ let pr = pr_lconstr_env env sigma rator.uj_val in
+ let prt = pr_lconstr_env env sigma rator.uj_type in
+ let appl = prvect_with_sep fnl
(fun c ->
- let pc = pr_lconstr_env env c.uj_val in
- let pct = pr_lconstr_env env c.uj_type in
+ let pc = pr_lconstr_env env sigma c.uj_val in
+ let pct = pr_lconstr_env env sigma c.uj_type in
hov 2 (pc ++ spc () ++ str ": " ++ pct)) randl
in
str "Illegal application (Non-functional construction): " ++
(* pe ++ *) fnl () ++
str "The expression" ++ brk(1,1) ++ pr ++ spc () ++
str "of type" ++ brk(1,1) ++ prt ++ spc () ++
- str "cannot be applied to the " ++ str (plural nargs "term") ++ fnl () ++
- str " " ++ v 0 appl
+ str "cannot be applied to the " ++ str (String.plural nargs "term") ++
+ fnl () ++ str " " ++ v 0 appl
let explain_unexpected_type env sigma actual_type expected_type =
- let actual_type = nf_evar sigma actual_type in
- let expected_type = nf_evar sigma expected_type in
- let pract = pr_lconstr_env env actual_type in
- let prexp = pr_lconstr_env env expected_type in
+ let actual_type = Evarutil.nf_evar sigma actual_type in
+ let expected_type = Evarutil.nf_evar sigma expected_type in
+ let pract, prexp = pr_explicit env sigma actual_type expected_type in
str "Found type" ++ spc () ++ pract ++ spc () ++
str "where" ++ spc () ++ prexp ++ str " was expected."
let explain_not_product env sigma c =
- let c = nf_evar sigma c in
- let pr = pr_lconstr_env env c in
+ let c = Evarutil.nf_evar sigma c in
+ let pr = pr_lconstr_env env sigma c in
str "The type of this term is a product" ++ spc () ++
str "while it is expected to be" ++
(if is_Type c then str " a sort" else (brk(1,1) ++ pr)) ++ str "."
(* TODO: use the names *)
(* (co)fixpoints *)
-let explain_ill_formed_rec_body env err names i fixenv vdefj =
+let explain_ill_formed_rec_body env sigma err names i fixenv vdefj =
let prt_name i =
match names.(i) with
Name id -> str "Recursive definition of " ++ pr_id id
- | Anonymous -> str "The " ++ nth i ++ str " definition" in
+ | Anonymous -> str "The " ++ pr_nth i ++ str " definition" in
let st = match err with
@@ -242,175 +409,188 @@ let explain_ill_formed_rec_body env err names i fixenv vdefj =
| NotEnoughAbstractionInFixBody ->
str "Not enough abstractions in the definition"
| RecursionNotOnInductiveType c ->
- str "Recursive definition on" ++ spc () ++ pr_lconstr_env env c ++ spc () ++
- str "which should be an inductive type"
+ str "Recursive definition on" ++ spc () ++ pr_lconstr_env env sigma c ++
+ spc () ++ str "which should be an inductive type"
| RecursionOnIllegalTerm(j,(arg_env, arg),le,lt) ->
let arg_env = make_all_name_different arg_env in
let called =
match names.(j) with
Name id -> pr_id id
- | Anonymous -> str "the " ++ nth i ++ str " definition" in
+ | Anonymous -> str "the " ++ pr_nth i ++ str " definition" in
let pr_db x = quote (pr_db env x) in
let vars =
match (lt,le) with
([],[]) -> assert false
| ([],[x]) -> str "a subterm of " ++ pr_db x
| ([],_) -> str "a subterm of the following variables: " ++
- prlist_with_sep pr_spc pr_db le
+ pr_sequence pr_db le
| ([x],_) -> pr_db x
| _ ->
str "one of the following variables: " ++
- prlist_with_sep pr_spc pr_db lt in
+ pr_sequence pr_db lt in
str "Recursive call to " ++ called ++ spc () ++
strbrk "has principal argument equal to" ++ spc () ++
- pr_lconstr_env arg_env arg ++ strbrk " instead of " ++ vars
+ pr_lconstr_env arg_env sigma arg ++ strbrk " instead of " ++ vars
| NotEnoughArgumentsForFixCall j ->
let called =
match names.(j) with
Name id -> pr_id id
- | Anonymous -> str "the " ++ nth i ++ str " definition" in
+ | Anonymous -> str "the " ++ pr_nth i ++ str " definition" in
str "Recursive call to " ++ called ++ str " has not enough arguments"
(* CoFixpoint guard errors *)
| CodomainNotInductiveType c ->
- str "The codomain is" ++ spc () ++ pr_lconstr_env env c ++ spc () ++
+ str "The codomain is" ++ spc () ++ pr_lconstr_env env sigma c ++ spc () ++
str "which should be a coinductive type"
| NestedRecursiveOccurrences ->
str "Nested recursive occurrences"
| UnguardedRecursiveCall c ->
- str "Unguarded recursive call in" ++ spc () ++ pr_lconstr_env env c
+ str "Unguarded recursive call in" ++ spc () ++ pr_lconstr_env env sigma c
| RecCallInTypeOfAbstraction c ->
str "Recursive call forbidden in the domain of an abstraction:" ++
- spc () ++ pr_lconstr_env env c
+ spc () ++ pr_lconstr_env env sigma c
| RecCallInNonRecArgOfConstructor c ->
str "Recursive call on a non-recursive argument of constructor" ++
- spc () ++ pr_lconstr_env env c
+ spc () ++ pr_lconstr_env env sigma c
| RecCallInTypeOfDef c ->
str "Recursive call forbidden in the type of a recursive definition" ++
- spc () ++ pr_lconstr_env env c
+ spc () ++ pr_lconstr_env env sigma c
| RecCallInCaseFun c ->
- str "Invalid recursive call in a branch of" ++ spc () ++ pr_lconstr_env env c
+ str "Invalid recursive call in a branch of" ++
+ spc () ++ pr_lconstr_env env sigma c
| RecCallInCaseArg c ->
str "Invalid recursive call in the argument of \"match\" in" ++ spc () ++
- pr_lconstr_env env c
+ pr_lconstr_env env sigma c
| RecCallInCasePred c ->
- str "Invalid recursive call in the \"return\" clause of \"match\" in" ++ spc () ++
- pr_lconstr_env env c
+ str "Invalid recursive call in the \"return\" clause of \"match\" in" ++
+ spc () ++ pr_lconstr_env env sigma c
| NotGuardedForm c ->
- str "Sub-expression " ++ pr_lconstr_env env c ++
+ str "Sub-expression " ++ pr_lconstr_env env sigma c ++
strbrk " not in guarded form (should be a constructor," ++
strbrk " an abstraction, a match, a cofix or a recursive call)"
+ | ReturnPredicateNotCoInductive c ->
+ str "The return clause of the following pattern matching should be" ++
+ strbrk " a coinductive type:" ++
+ spc () ++ pr_lconstr_env env sigma c
in
prt_name i ++ str " is ill-formed." ++ fnl () ++
- pr_ne_context_of (str "In environment") env ++
+ pr_ne_context_of (str "In environment") env sigma ++
st ++ str "." ++ fnl () ++
(try (* May fail with unresolved globals. *)
let fixenv = make_all_name_different fixenv in
- let pvd = pr_lconstr_env fixenv vdefj.(i).uj_val in
+ let pvd = pr_lconstr_env fixenv sigma vdefj.(i).uj_val in
str"Recursive definition is:" ++ spc () ++ pvd ++ str "."
with e when Errors.noncritical e -> mt ())
let explain_ill_typed_rec_body env sigma i names vdefj vargs =
- let vdefj = jv_nf_evar sigma vdefj in
- let vargs = Array.map (nf_evar sigma) vargs in
+ let vdefj = Evarutil.jv_nf_evar sigma vdefj in
+ let vargs = Array.map (Evarutil.nf_evar sigma) vargs in
let env = make_all_name_different env in
- let pvd,pvdt = pr_ljudge_env env (vdefj.(i)) in
- let pv = pr_lconstr_env env vargs.(i) in
+ let pvd = pr_lconstr_env env sigma vdefj.(i).uj_val in
+ let pvdt, pv = pr_explicit env sigma vdefj.(i).uj_type vargs.(i) in
str "The " ++
- (if Array.length vdefj = 1 then mt () else nth (i+1) ++ spc ()) ++
+ (match vdefj with [|_|] -> mt () | _ -> pr_nth (i+1) ++ spc ()) ++
str "recursive definition" ++ spc () ++ pvd ++ spc () ++
str "has type" ++ spc () ++ pvdt ++ spc () ++
str "while it should be" ++ spc () ++ pv ++ str "."
let explain_cant_find_case_type env sigma c =
- let c = nf_evar sigma c in
+ let c = Evarutil.nf_evar sigma c in
let env = make_all_name_different env in
- let pe = pr_lconstr_env env c in
+ let pe = pr_lconstr_env env sigma c in
str "Cannot infer type of pattern-matching on" ++ ws 1 ++ pe ++ str "."
let explain_occur_check env sigma ev rhs =
- let rhs = nf_evar sigma rhs in
+ let rhs = Evarutil.nf_evar sigma rhs in
let env = make_all_name_different env in
- let id = Evd.string_of_existential ev in
- let pt = pr_lconstr_env env rhs in
- str "Cannot define " ++ str id ++ str " with term" ++ brk(1,1) ++
- pt ++ spc () ++ str "that would depend on itself."
-
-let pr_ne_context_of header footer env =
- if Environ.rel_context env = empty_rel_context &
- Environ.named_context env = empty_named_context
- then footer
- else pr_ne_context_of header env
-
-let explain_hole_kind env evi = function
- | QuestionMark _ -> str "this placeholder"
- | CasesType ->
- str "the type of this pattern-matching problem"
- | BinderType (Name id) ->
- str "the type of " ++ Nameops.pr_id id
- | BinderType Anonymous ->
- str "the type of this anonymous binder"
- | ImplicitArg (c,(n,ido),b) ->
+ let pt = pr_lconstr_env env sigma rhs in
+ str "Cannot define " ++ pr_existential_key sigma ev ++ str " with term" ++
+ brk(1,1) ++ pt ++ spc () ++ str "that would depend on itself."
+
+let pr_trailing_ne_context_of env sigma =
+ if List.is_empty (Environ.rel_context env) &&
+ List.is_empty (Environ.named_context env)
+ then str "."
+ else (str " in environment:"++ pr_context_unlimited env sigma)
+
+let rec explain_evar_kind env sigma evk ty = function
+ | Evar_kinds.QuestionMark _ ->
+ strbrk "this placeholder of type " ++ ty
+ | Evar_kinds.CasesType false ->
+ strbrk "the type of this pattern-matching problem"
+ | Evar_kinds.CasesType true ->
+ strbrk "a subterm of type " ++ ty ++
+ strbrk " in the type of this pattern-matching problem"
+ | Evar_kinds.BinderType (Name id) ->
+ strbrk "the type of " ++ Nameops.pr_id id
+ | Evar_kinds.BinderType Anonymous ->
+ strbrk "the type of this anonymous binder"
+ | Evar_kinds.ImplicitArg (c,(n,ido),b) ->
let id = Option.get ido in
- str "the implicit parameter " ++
- pr_id id ++ spc () ++ str "of" ++
- spc () ++ Nametab.pr_global_env Idset.empty c
- | InternalHole ->
- str "an internal placeholder" ++
- Option.cata (fun evi ->
- let env = Evd.evar_env evi in
- str " of type " ++ pr_lconstr_env env evi.evar_concl ++
- pr_ne_context_of (str " in environment:"++ fnl ()) (mt ()) env)
- (mt ()) evi
- | TomatchTypeParameter (tyi,n) ->
- str "the " ++ nth n ++
- str " argument of the inductive type (" ++ pr_inductive env tyi ++
- str ") of this term"
- | GoalEvar ->
- str "an existential variable"
- | ImpossibleCase ->
- str "the type of an impossible pattern-matching clause"
- | MatchingVar _ ->
+ strbrk "the implicit parameter " ++ pr_id id ++ spc () ++ str "of" ++
+ spc () ++ Nametab.pr_global_env Id.Set.empty c ++
+ strbrk " whose type is " ++ ty
+ | Evar_kinds.InternalHole -> strbrk "an internal placeholder of type " ++ ty
+ | Evar_kinds.TomatchTypeParameter (tyi,n) ->
+ strbrk "the " ++ pr_nth n ++
+ strbrk " argument of the inductive type (" ++ pr_inductive env tyi ++
+ strbrk ") of this term"
+ | Evar_kinds.GoalEvar ->
+ strbrk "an existential variable of type " ++ ty
+ | Evar_kinds.ImpossibleCase ->
+ strbrk "the type of an impossible pattern-matching clause"
+ | Evar_kinds.MatchingVar _ ->
assert false
-
-let explain_not_clean env sigma ev t k =
- let t = nf_evar sigma t in
- let env = make_all_name_different env in
- let id = Evd.string_of_existential ev in
- let var = pr_lconstr_env env t in
- str "Tried to instantiate " ++ explain_hole_kind env None k ++
- str " (" ++ str id ++ str ")" ++ spc () ++
- str "with a term using variable " ++ var ++ spc () ++
- str "which is not in its scope."
-
-let explain_unsolvability = function
- | None -> mt()
- | Some (SeveralInstancesFound n) ->
- strbrk " (several distinct possible instances found)"
-
-let explain_typeclass_resolution env evi k =
+ | Evar_kinds.VarInstance id ->
+ strbrk "an instance of type " ++ ty ++
+ str " for the variable " ++ pr_id id
+ | Evar_kinds.SubEvar evk' ->
+ let evi = Evd.find sigma evk' in
+ let pc = match evi.evar_body with
+ | Evar_defined c -> pr_lconstr_env env sigma (Evarutil.nf_evar sigma c)
+ | Evar_empty -> assert false in
+ let ty' = Evarutil.nf_evar sigma evi.evar_concl in
+ pr_existential_key sigma evk ++ str " of type " ++ ty ++
+ str " in the partial instance " ++ pc ++
+ str " found for " ++ explain_evar_kind env sigma evk'
+ (pr_lconstr_env env sigma ty') (snd evi.evar_source)
+
+let explain_typeclass_resolution env sigma evi k =
match Typeclasses.class_of_constr evi.evar_concl with
- | Some c ->
- let env = Evd.evar_env evi in
+ | Some _ ->
+ let env = Evd.evar_filtered_env evi in
fnl () ++ str "Could not find an instance for " ++
- pr_lconstr_env env evi.evar_concl ++
- pr_ne_context_of (str " in environment:"++ fnl ()) (str ".") env
+ pr_lconstr_env env sigma evi.evar_concl ++
+ pr_trailing_ne_context_of env sigma
| _ -> mt()
-let explain_unsolvable_implicit env evi k explain =
- str "Cannot infer " ++ explain_hole_kind env (Some evi) k ++
- explain_unsolvability explain ++ str "." ++
- explain_typeclass_resolution env evi k
+let explain_placeholder_kind env sigma c e =
+ match e with
+ | Some (SeveralInstancesFound n) ->
+ strbrk " (several distinct possible type class instances found)"
+ | None ->
+ match Typeclasses.class_of_constr c with
+ | Some _ -> strbrk " (no type class instance found)"
+ | _ -> mt ()
+
+let explain_unsolvable_implicit env sigma evk explain =
+ let evi = Evarutil.nf_evar_info sigma (Evd.find_undefined sigma evk) in
+ let env = Evd.evar_filtered_env evi in
+ let type_of_hole = pr_lconstr_env env sigma evi.evar_concl in
+ let pe = pr_trailing_ne_context_of env sigma in
+ strbrk "Cannot infer " ++
+ explain_evar_kind env sigma evk type_of_hole (snd evi.evar_source) ++
+ explain_placeholder_kind env sigma evi.evar_concl explain ++ pe
let explain_var_not_found env id =
str "The variable" ++ spc () ++ pr_id id ++
spc () ++ str "was not found" ++
spc () ++ str "in the current" ++ spc () ++ str "environment" ++ str "."
-let explain_wrong_case_info env ind ci =
+let explain_wrong_case_info env (ind,u) ci =
let pi = pr_inductive (Global.env()) ind in
- if ci.ci_ind = ind then
+ if eq_ind ci.ci_ind ind then
str "Pattern-matching expression on an object of inductive type" ++
spc () ++ pi ++ spc () ++ str "has invalid information."
else
@@ -419,71 +599,86 @@ let explain_wrong_case_info env ind ci =
str "was given to a pattern-matching expression on the inductive type" ++
spc () ++ pc ++ str "."
-let explain_cannot_unify env sigma m n =
- let m = nf_evar sigma m in
- let n = nf_evar sigma n in
- let pm = pr_lconstr_env env m in
- let pn = pr_lconstr_env env n in
- str "Impossible to unify" ++ brk(1,1) ++ pm ++ spc () ++
- str "with" ++ brk(1,1) ++ pn ++ str "."
+let explain_cannot_unify env sigma m n e =
+ let env = make_all_name_different env in
+ let m = Evarutil.nf_evar sigma m in
+ let n = Evarutil.nf_evar sigma n in
+ let pm, pn = pr_explicit env sigma m n in
+ let ppreason = explain_unification_error env sigma m n e in
+ let pe = pr_ne_context_of (str "In environment") env sigma in
+ pe ++ str "Unable to unify" ++ brk(1,1) ++ pm ++ spc () ++
+ str "with" ++ brk(1,1) ++ pn ++ ppreason ++ str "."
let explain_cannot_unify_local env sigma m n subn =
- let pm = pr_lconstr_env env m in
- let pn = pr_lconstr_env env n in
- let psubn = pr_lconstr_env env subn in
- str "Impossible to unify" ++ brk(1,1) ++ pm ++ spc () ++
+ let pm = pr_lconstr_env env sigma m in
+ let pn = pr_lconstr_env env sigma n in
+ let psubn = pr_lconstr_env env sigma subn in
+ str "Unable to unify" ++ brk(1,1) ++ pm ++ spc () ++
str "with" ++ brk(1,1) ++ pn ++ spc () ++ str "as" ++ brk(1,1) ++
psubn ++ str " contains local variables."
-let explain_refiner_cannot_generalize env ty =
+let explain_refiner_cannot_generalize env sigma ty =
str "Cannot find a well-typed generalisation of the goal with type: " ++
- pr_lconstr_env env ty ++ str "."
+ pr_lconstr_env env sigma ty ++ str "."
-let explain_no_occurrence_found env c id =
- str "Found no subterm matching " ++ pr_lconstr_env env c ++
+let explain_no_occurrence_found env sigma c id =
+ str "Found no subterm matching " ++ pr_lconstr_env env sigma c ++
str " in " ++
(match id with
| Some id -> pr_id id
| None -> str"the current goal") ++ str "."
-let explain_cannot_unify_binding_type env m n =
- let pm = pr_lconstr_env env m in
- let pn = pr_lconstr_env env n in
+let explain_cannot_unify_binding_type env sigma m n =
+ let pm = pr_lconstr_env env sigma m in
+ let pn = pr_lconstr_env env sigma n in
str "This binding has type" ++ brk(1,1) ++ pm ++ spc () ++
str "which should be unifiable with" ++ brk(1,1) ++ pn ++ str "."
-let explain_cannot_find_well_typed_abstraction env p l =
+let explain_cannot_find_well_typed_abstraction env sigma p l e =
str "Abstracting over the " ++
- str (plural (List.length l) "term") ++ spc () ++
- hov 0 (pr_enum (pr_lconstr_env env) l) ++ spc () ++
- str "leads to a term" ++ spc () ++ pr_lconstr_env env p ++ spc () ++
- str "which is ill-typed."
+ str (String.plural (List.length l) "term") ++ spc () ++
+ hov 0 (pr_enum (pr_lconstr_env env sigma) l) ++ spc () ++
+ str "leads to a term" ++ spc () ++ pr_lconstr_goal_style_env env sigma p ++
+ spc () ++ str "which is ill-typed." ++
+ (match e with None -> mt () | Some e -> fnl () ++ str "Reason is: " ++ e)
+
+let explain_wrong_abstraction_type env sigma na abs expected result =
+ let ppname = match na with Name id -> pr_id id ++ spc () | _ -> mt () in
+ str "Cannot instantiate metavariable " ++ ppname ++ strbrk "of type " ++
+ pr_lconstr_env env sigma expected ++ strbrk " with abstraction " ++
+ pr_lconstr_env env sigma abs ++ strbrk " of incompatible type " ++
+ pr_lconstr_env env sigma result ++ str "."
let explain_abstraction_over_meta _ m n =
strbrk "Too complex unification problem: cannot find a solution for both " ++
pr_name m ++ spc () ++ str "and " ++ pr_name n ++ str "."
-let explain_non_linear_unification env m t =
+let explain_non_linear_unification env sigma m t =
strbrk "Cannot unambiguously instantiate " ++
pr_name m ++ str ":" ++
strbrk " which would require to abstract twice on " ++
- pr_lconstr_env env t ++ str "."
+ pr_lconstr_env env sigma t ++ str "."
+
+let explain_unsatisfied_constraints env sigma cst =
+ strbrk "Unsatisfied constraints: " ++
+ Univ.pr_constraints (Evd.pr_evd_level sigma) cst ++
+ spc () ++ str "(maybe a bugged tactic)."
let explain_type_error env sigma err =
let env = make_all_name_different env in
match err with
| UnboundRel n ->
- explain_unbound_rel env n
+ explain_unbound_rel env sigma n
| UnboundVar v ->
explain_unbound_var env v
| NotAType j ->
explain_not_type env sigma j
| BadAssumption c ->
- explain_bad_assumption env c
- | ReferenceVariables id ->
- explain_reference_variables id
+ explain_bad_assumption env sigma c
+ | ReferenceVariables (id,c) ->
+ explain_reference_variables id c
| ElimArity (ind, aritylst, c, pj, okinds) ->
- explain_elim_arity env ind aritylst c pj okinds
+ explain_elim_arity env sigma ind aritylst c pj okinds
| CaseNotInductive cj ->
explain_case_not_inductive env sigma cj
| NumberBranches (cj, n) ->
@@ -491,42 +686,128 @@ let explain_type_error env sigma err =
| IllFormedBranch (c, i, actty, expty) ->
explain_ill_formed_branch env sigma c i actty expty
| Generalization (nvar, c) ->
- explain_generalization env nvar c
+ explain_generalization env sigma nvar c
| ActualType (j, pt) ->
- explain_actual_type env sigma j pt
+ explain_actual_type env sigma j pt None
| CantApplyBadType (t, rator, randl) ->
explain_cant_apply_bad_type env sigma t rator randl
| CantApplyNonFunctional (rator, randl) ->
explain_cant_apply_not_functional env sigma rator randl
| IllFormedRecBody (err, lna, i, fixenv, vdefj) ->
- explain_ill_formed_rec_body env err lna i fixenv vdefj
+ explain_ill_formed_rec_body env sigma err lna i fixenv vdefj
| IllTypedRecBody (i, lna, vdefj, vargs) ->
explain_ill_typed_rec_body env sigma i lna vdefj vargs
| WrongCaseInfo (ind,ci) ->
explain_wrong_case_info env ind ci
+ | UnsatisfiedConstraints cst ->
+ explain_unsatisfied_constraints env sigma cst
+
+let pr_position (cl,pos) =
+ let clpos = match cl with
+ | None -> str " of the goal"
+ | Some (id,Locus.InHyp) -> str " of hypothesis " ++ pr_id id
+ | Some (id,Locus.InHypTypeOnly) -> str " of the type of hypothesis " ++ pr_id id
+ | Some (id,Locus.InHypValueOnly) -> str " of the body of hypothesis " ++ pr_id id in
+ int pos ++ clpos
+
+let explain_cannot_unify_occurrences env sigma nested ((cl2,pos2),t2) ((cl1,pos1),t1) e =
+ if nested then
+ str "Found nested occurrences of the pattern at positions " ++
+ int pos1 ++ strbrk " and " ++ pr_position (cl2,pos2) ++ str "."
+ else
+ let ppreason = match e with None -> mt() | Some (c1,c2,e) -> explain_unification_error env sigma c1 c2 (Some e) in
+ str "Found incompatible occurrences of the pattern" ++ str ":" ++
+ spc () ++ str "Matched term " ++ pr_lconstr_env env sigma t2 ++
+ strbrk " at position " ++ pr_position (cl2,pos2) ++
+ strbrk " is not compatible with matched term " ++
+ pr_lconstr_env env sigma t1 ++ strbrk " at position " ++
+ pr_position (cl1,pos1) ++ ppreason ++ str "."
+
+let pr_constraints printenv env sigma evars cstrs =
+ let (ev, evi) = Evar.Map.choose evars in
+ if Evar.Map.for_all (fun ev' evi' ->
+ eq_named_context_val evi.evar_hyps evi'.evar_hyps) evars
+ then
+ let l = Evar.Map.bindings evars in
+ let env' = reset_with_named_context evi.evar_hyps env in
+ let pe =
+ if printenv then
+ pr_ne_context_of (str "In environment:") env' sigma
+ else mt ()
+ in
+ let evs =
+ prlist
+ (fun (ev, evi) -> fnl () ++ pr_existential_key sigma ev ++
+ str " : " ++ pr_lconstr_env env' sigma evi.evar_concl) l
+ in
+ h 0 (pe ++ evs ++ pr_evar_constraints cstrs)
+ else
+ let filter evk _ = Evar.Map.mem evk evars in
+ pr_evar_map_filter ~with_univs:false filter sigma
+
+let explain_unsatisfiable_constraints env sigma constr comp =
+ let (_, constraints) = Evd.extract_all_conv_pbs sigma in
+ let undef = Evd.undefined_map (Evarutil.nf_evar_map_undefined sigma) in
+ (** Only keep evars that are subject to resolution and members of the given
+ component. *)
+ let is_kept evk evi = match comp with
+ | None -> Typeclasses.is_resolvable evi
+ | Some comp -> Typeclasses.is_resolvable evi && Evar.Set.mem evk comp
+ in
+ let undef =
+ let m = Evar.Map.filter is_kept undef in
+ if Evar.Map.is_empty m then undef
+ else m
+ in
+ match constr with
+ | None ->
+ str "Unable to satisfy the following constraints:" ++ fnl () ++
+ pr_constraints true env sigma undef constraints
+ | Some (ev, k) ->
+ let cstr =
+ let remaining = Evar.Map.remove ev undef in
+ if not (Evar.Map.is_empty remaining) then
+ str "With the following constraints:" ++ fnl () ++
+ pr_constraints false env sigma remaining constraints
+ else mt ()
+ in
+ let info = Evar.Map.find ev undef in
+ explain_typeclass_resolution env sigma info k ++ fnl () ++ cstr
let explain_pretype_error env sigma err =
- let env = env_nf_betaiotaevar sigma env in
+ let env = Evarutil.env_nf_betaiotaevar sigma env in
let env = make_all_name_different env in
match err with
| CantFindCaseType c -> explain_cant_find_case_type env sigma c
- | OccurCheck (n,c) -> explain_occur_check env sigma n c
- | NotClean (n,c,k) -> explain_not_clean env sigma n c k
- | UnsolvableImplicit (evi,k,exp) -> explain_unsolvable_implicit env evi k exp
+ | ActualTypeNotCoercible (j,t,e) ->
+ let {uj_val = c; uj_type = actty} = j in
+ let (env, c, actty, expty), e = contract3' env c actty t e in
+ let j = {uj_val = c; uj_type = actty} in
+ explain_actual_type env sigma j t (Some e)
+ | UnifOccurCheck (ev,rhs) -> explain_occur_check env sigma ev rhs
+ | UnsolvableImplicit (evk,exp) -> explain_unsolvable_implicit env sigma evk exp
| VarNotFound id -> explain_var_not_found env id
- | UnexpectedType (actual,expect) -> explain_unexpected_type env sigma actual expect
+ | UnexpectedType (actual,expect) ->
+ let env, actual, expect = contract2 env actual expect in
+ explain_unexpected_type env sigma actual expect
| NotProduct c -> explain_not_product env sigma c
- | CannotUnify (m,n) -> explain_cannot_unify env sigma m n
+ | CannotUnify (m,n,e) ->
+ let env, m, n = contract2 env m n in
+ explain_cannot_unify env sigma m n e
| CannotUnifyLocal (m,n,sn) -> explain_cannot_unify_local env sigma m n sn
- | CannotGeneralize ty -> explain_refiner_cannot_generalize env ty
- | NoOccurrenceFound (c, id) -> explain_no_occurrence_found env c id
- | CannotUnifyBindingType (m,n) -> explain_cannot_unify_binding_type env m n
- | CannotFindWellTypedAbstraction (p,l) ->
- explain_cannot_find_well_typed_abstraction env p l
+ | CannotGeneralize ty -> explain_refiner_cannot_generalize env sigma ty
+ | NoOccurrenceFound (c, id) -> explain_no_occurrence_found env sigma c id
+ | CannotUnifyBindingType (m,n) -> explain_cannot_unify_binding_type env sigma m n
+ | CannotFindWellTypedAbstraction (p,l,e) ->
+ explain_cannot_find_well_typed_abstraction env sigma p l
+ (Option.map (fun (env',e) -> explain_type_error env' sigma e) e)
+ | WrongAbstractionType (n,a,t,u) ->
+ explain_wrong_abstraction_type env sigma n a t u
| AbstractionOverMeta (m,n) -> explain_abstraction_over_meta env m n
- | NonLinearUnification (m,c) -> explain_non_linear_unification env m c
+ | NonLinearUnification (m,c) -> explain_non_linear_unification env sigma m c
| TypingError t -> explain_type_error env sigma t
-
+ | CannotUnifyOccurrences (b,c1,c2,e) -> explain_cannot_unify_occurrences env sigma b c1 c2 e
+ | UnsatisfiableConstraints (c,comp) -> explain_unsatisfiable_constraints env sigma c comp
(* Module errors *)
open Modops
@@ -541,14 +822,14 @@ let explain_not_match_error = function
| ModuleTypeFieldExpected ->
strbrk "a module type is expected"
| NotConvertibleInductiveField id | NotConvertibleConstructorField id ->
- str "types given to " ++ str (string_of_id id) ++ str " differ"
+ str "types given to " ++ str (Id.to_string id) ++ str " differ"
| NotConvertibleBodyField ->
str "the body of definitions differs"
| NotConvertibleTypeField (env, typ1, typ2) ->
str "expected type" ++ spc () ++
- quote (Printer.safe_pr_lconstr_env env typ2) ++ spc () ++
+ quote (Printer.safe_pr_lconstr_env env Evd.empty typ2) ++ spc () ++
str "but found type" ++ spc () ++
- quote (Printer.safe_pr_lconstr_env env typ1)
+ quote (Printer.safe_pr_lconstr_env env Evd.empty typ1)
| NotSameConstructorNamesField ->
str "constructor names differ"
| NotSameInductiveNameInBlockField ->
@@ -566,24 +847,45 @@ let explain_not_match_error = function
| RecordProjectionsExpected nal ->
(if List.length nal >= 2 then str "expected projection names are "
else str "expected projection name is ") ++
- pr_enum (function Name id -> str (string_of_id id) | _ -> str "_") nal
+ pr_enum (function Name id -> str (Id.to_string id) | _ -> str "_") nal
| NotEqualInductiveAliases ->
str "Aliases to inductive types do not match"
| NoTypeConstraintExpected ->
- strbrk "a definition whose type is constrained can only be subtype of a definition whose type is itself constrained"
+ strbrk "a definition whose type is constrained can only be subtype " ++
+ strbrk "of a definition whose type is itself constrained"
+ | PolymorphicStatusExpected b ->
+ let status b = if b then str"polymorphic" else str"monomorphic" in
+ str "a " ++ status b ++ str" declaration was expected, but a " ++
+ status (not b) ++ str" declaration was found"
+ | IncompatibleInstances ->
+ str"polymorphic universe instances do not match"
+ | IncompatibleUniverses incon ->
+ str"the universe constraints are inconsistent: " ++
+ Univ.explain_universe_inconsistency Universes.pr_with_global_universes incon
+ | IncompatiblePolymorphism (env, t1, t2) ->
+ str "conversion of polymorphic values generates additional constraints: " ++
+ quote (Printer.safe_pr_lconstr_env env Evd.empty t1) ++ spc () ++
+ str "compared to " ++ spc () ++
+ quote (Printer.safe_pr_lconstr_env env Evd.empty t2)
+ | IncompatibleConstraints cst ->
+ str " the expected (polymorphic) constraints do not imply " ++
+ quote (Univ.pr_constraints (Evd.pr_evd_level Evd.empty) cst)
let explain_signature_mismatch l spec why =
- str "Signature components for label " ++ str (string_of_label l) ++
+ str "Signature components for label " ++ str (Label.to_string l) ++
str " do not match:" ++ spc () ++ explain_not_match_error why ++ str "."
let explain_label_already_declared l =
- str ("The label "^string_of_label l^" is already declared.")
+ str ("The label "^Label.to_string l^" is already declared.")
let explain_application_to_not_path _ =
str "Application of modules is restricted to paths."
-let explain_not_a_functor mtb =
- str "Application of not a functor."
+let explain_not_a_functor () =
+ str "Application of a non-functor."
+
+let explain_is_a_functor () =
+ str "Illegal use of a functor."
let explain_incompatible_module_types mexpr1 mexpr2 =
str "Incompatible module types."
@@ -592,20 +894,11 @@ let explain_not_equal_module_paths mp1 mp2 =
str "Non equal modules."
let explain_no_such_label l =
- str "No such label " ++ str (string_of_label l) ++ str "."
+ str "No such label " ++ str (Label.to_string l) ++ str "."
let explain_incompatible_labels l l' =
str "Opening and closing labels are not the same: " ++
- str (string_of_label l) ++ str " <> " ++ str (string_of_label l') ++ str "!"
-
-let explain_signature_expected mtb =
- str "Signature expected."
-
-let explain_no_module_to_end () =
- str "No open module to end."
-
-let explain_no_module_type_to_end () =
- str "No open module type to end."
+ str (Label.to_string l) ++ str " <> " ++ str (Label.to_string l') ++ str "!"
let explain_not_a_module s =
quote (str s) ++ str " is not a module."
@@ -614,45 +907,41 @@ let explain_not_a_module_type s =
quote (str s) ++ str " is not a module type."
let explain_not_a_constant l =
- quote (pr_label l) ++ str " is not a constant."
+ quote (Label.print l) ++ str " is not a constant."
let explain_incorrect_label_constraint l =
str "Incorrect constraint for label " ++
- quote (pr_label l) ++ str "."
+ quote (Label.print l) ++ str "."
let explain_generative_module_expected l =
- str "The module " ++ str (string_of_label l) ++
- strbrk " is not generative. Only components of generative modules can be changed using the \"with\" construct."
-
-let explain_non_empty_local_context = function
- | None -> str "The local context is not empty."
- | Some l ->
- str "The local context of the component " ++
- str (string_of_label l) ++ str " is not empty."
+ str "The module " ++ str (Label.to_string l) ++ str " is not generative." ++
+ strbrk " Only components of generative modules can be changed" ++
+ strbrk " using the \"with\" construct."
let explain_label_missing l s =
- str "The field " ++ str (string_of_label l) ++ str " is missing in "
+ str "The field " ++ str (Label.to_string l) ++ str " is missing in "
++ str s ++ str "."
+let explain_higher_order_include () =
+ str "You cannot Include a higher-order structure."
+
let explain_module_error = function
| SignatureMismatch (l,spec,err) -> explain_signature_mismatch l spec err
| LabelAlreadyDeclared l -> explain_label_already_declared l
| ApplicationToNotPath mexpr -> explain_application_to_not_path mexpr
- | NotAFunctor mtb -> explain_not_a_functor mtb
+ | NotAFunctor -> explain_not_a_functor ()
+ | IsAFunctor -> explain_is_a_functor ()
| IncompatibleModuleTypes (m1,m2) -> explain_incompatible_module_types m1 m2
| NotEqualModulePaths (mp1,mp2) -> explain_not_equal_module_paths mp1 mp2
| NoSuchLabel l -> explain_no_such_label l
| IncompatibleLabels (l1,l2) -> explain_incompatible_labels l1 l2
- | SignatureExpected mtb -> explain_signature_expected mtb
- | NoModuleToEnd -> explain_no_module_to_end ()
- | NoModuleTypeToEnd -> explain_no_module_type_to_end ()
| NotAModule s -> explain_not_a_module s
| NotAModuleType s -> explain_not_a_module_type s
| NotAConstant l -> explain_not_a_constant l
| IncorrectWithConstraint l -> explain_incorrect_label_constraint l
| GenerativeModuleExpected l -> explain_generative_module_expected l
- | NonEmptyLocalContect lopt -> explain_non_empty_local_context lopt
| LabelMissing (l,s) -> explain_label_missing l s
+ | HigherOrderInclude -> explain_higher_order_include ()
(* Module internalization errors *)
@@ -681,72 +970,27 @@ let explain_module_internalization_error = function
(* Typeclass errors *)
let explain_not_a_class env c =
- pr_constr_env env c ++ str" is not a declared type class."
+ pr_constr_env env Evd.empty c ++ str" is not a declared type class."
let explain_unbound_method env cid id =
- str "Unbound method name " ++ Nameops.pr_id (snd id) ++ spc () ++ str"of class" ++ spc () ++
- pr_global cid ++ str "."
+ str "Unbound method name " ++ Nameops.pr_id (snd id) ++ spc () ++
+ str"of class" ++ spc () ++ pr_global cid ++ str "."
let pr_constr_exprs exprs =
hv 0 (List.fold_right
(fun d pps -> ws 2 ++ Ppconstr.pr_constr_expr d ++ pps)
exprs (mt ()))
-let explain_no_instance env (_,id) l =
- str "No instance found for class " ++ Nameops.pr_id id ++ spc () ++
- str "applied to arguments" ++ spc () ++
- prlist_with_sep pr_spc (pr_lconstr_env env) l
-
-let is_goal_evar evi = match evi.evar_source with (_, GoalEvar) -> true | _ -> false
-
-let pr_constraints printenv env evm =
- let l = Evd.to_list evm in
- assert(l <> []);
- let (ev, evi) = List.hd l in
- if List.for_all (fun (ev', evi') ->
- eq_named_context_val evi.evar_hyps evi'.evar_hyps) l
- then
- let pe = pr_ne_context_of (str "In environment:") (mt ())
- (reset_with_named_context evi.evar_hyps env) in
- (if printenv then pe ++ fnl () else mt ()) ++
- prlist_with_sep (fun () -> fnl ())
- (fun (ev, evi) -> str(string_of_existential ev) ++
- str " : " ++ pr_lconstr evi.evar_concl) l ++ fnl() ++
- pr_evar_map_constraints evm
- else
- pr_evar_map None evm
-
-let explain_unsatisfiable_constraints env evd constr =
- let evm = Evd.undefined_evars (Evarutil.nf_evar_map_undefined evd) in
- (* Remove goal evars *)
- let undef = fold_undefined
- (fun ev evi evm' ->
- if is_goal_evar evi then Evd.remove evm' ev else evm') evm evm
- in
- match constr with
- | None ->
- str"Unable to satisfy the following constraints:" ++ fnl() ++
- pr_constraints true env undef
- | Some (ev, k) ->
- explain_typeclass_resolution env (Evd.find evm ev) k ++ fnl () ++
- (let remaining = Evd.remove undef ev in
- if Evd.has_undefined remaining then
- str"With the following constraints:" ++ fnl() ++
- pr_constraints false env remaining
- else mt ())
-
let explain_mismatched_contexts env c i j =
str"Mismatched contexts while declaring instance: " ++ brk (1,1) ++
- hov 1 (str"Expected:" ++ brk (1, 1) ++ pr_rel_context env j) ++ fnl () ++ brk (1,1) ++
+ hov 1 (str"Expected:" ++ brk (1, 1) ++ pr_rel_context env Evd.empty j) ++
+ fnl () ++ brk (1,1) ++
hov 1 (str"Found:" ++ brk (1, 1) ++ pr_constr_exprs i)
-let explain_typeclass_error env err =
- match err with
- | NotAClass c -> explain_not_a_class env c
- | UnboundMethod (cid, id) -> explain_unbound_method env cid id
- | NoInstance (id, l) -> explain_no_instance env id l
- | UnsatisfiableConstraints (evd, c) -> explain_unsatisfiable_constraints env evd c
- | MismatchedContextInstance (c, i, j) -> explain_mismatched_contexts env c i j
+let explain_typeclass_error env = function
+ | NotAClass c -> explain_not_a_class env c
+ | UnboundMethod (cid, id) -> explain_unbound_method env cid id
+ | MismatchedContextInstance (c,i,j) -> explain_mismatched_contexts env c i j
(* Refiner errors *)
@@ -758,7 +1002,7 @@ let explain_refiner_bad_type arg ty conclty =
let explain_refiner_unresolved_bindings l =
str "Unable to find an instance for the " ++
- str (plural (List.length l) "variable") ++ spc () ++
+ str (String.plural (List.length l) "variable") ++ spc () ++
prlist_with_sep pr_comma pr_name l ++ str"."
let explain_refiner_cannot_apply t harg =
@@ -784,6 +1028,9 @@ let explain_meta_in_type c =
str "In refiner, a meta appears in the type " ++ brk(1,1) ++ pr_lconstr c ++
str " of another meta"
+let explain_no_such_hyp id =
+ str "No such hypothesis: " ++ pr_id id
+
let explain_refiner_error = function
| BadType (arg,ty,conclty) -> explain_refiner_bad_type arg ty conclty
| UnresolvedBindings t -> explain_refiner_unresolved_bindings t
@@ -793,50 +1040,51 @@ let explain_refiner_error = function
| DoesNotOccurIn (c,hyp) -> explain_does_not_occur_in c hyp
| NonLinearProof c -> explain_non_linear_proof c
| MetaInType c -> explain_meta_in_type c
+ | NoSuchHyp id -> explain_no_such_hyp id
(* Inductive errors *)
-let error_non_strictly_positive env c v =
- let pc = pr_lconstr_env env c in
- let pv = pr_lconstr_env env v in
+let error_non_strictly_positive env c v =
+ let pc = pr_lconstr_env env Evd.empty c in
+ let pv = pr_lconstr_env env Evd.empty v in
str "Non strictly positive occurrence of " ++ pv ++ str " in" ++
brk(1,1) ++ pc ++ str "."
let error_ill_formed_inductive env c v =
- let pc = pr_lconstr_env env c in
- let pv = pr_lconstr_env env v in
+ let pc = pr_lconstr_env env Evd.empty c in
+ let pv = pr_lconstr_env env Evd.empty v in
str "Not enough arguments applied to the " ++ pv ++
str " in" ++ brk(1,1) ++ pc ++ str "."
let error_ill_formed_constructor env id c v nparams nargs =
- let pv = pr_lconstr_env env v in
- let atomic = (nb_prod c = 0) in
+ let pv = pr_lconstr_env env Evd.empty v in
+ let atomic = Int.equal (nb_prod c) 0 in
str "The type of constructor" ++ brk(1,1) ++ pr_id id ++ brk(1,1) ++
str "is not valid;" ++ brk(1,1) ++
strbrk (if atomic then "it must be " else "its conclusion must be ") ++
pv ++
(* warning: because of implicit arguments it is difficult to say which
parameters must be explicitly given *)
- (if nparams<>0 then
- strbrk " applied to its " ++ str (plural nparams "parameter")
+ (if not (Int.equal nparams 0) then
+ strbrk " applied to its " ++ str (String.plural nparams "parameter")
else
mt()) ++
- (if nargs<>0 then
- str (if nparams<>0 then " and" else " applied") ++
- strbrk " to some " ++ str (plural nargs "argument")
+ (if not (Int.equal nargs 0) then
+ str (if not (Int.equal nparams 0) then " and" else " applied") ++
+ strbrk " to some " ++ str (String.plural nargs "argument")
else
mt()) ++ str "."
let pr_ltype_using_barendregt_convention_env env c =
(* Use goal_concl_style as an approximation of Barendregt's convention (?) *)
- quote (pr_goal_concl_style_env env c)
+ quote (pr_goal_concl_style_env env Evd.empty c)
let error_bad_ind_parameters env c n v1 v2 =
let pc = pr_ltype_using_barendregt_convention_env env c in
- let pv1 = pr_lconstr_env env v1 in
- let pv2 = pr_lconstr_env env v2 in
+ let pv1 = pr_lconstr_env env Evd.empty v1 in
+ let pv2 = pr_lconstr_env env Evd.empty v2 in
str "Last occurrence of " ++ pv2 ++ str " must have " ++ pv1 ++
- str " as " ++ nth n ++ str " argument in " ++ brk(1,1) ++ pc ++ str "."
+ str " as " ++ pr_nth n ++ str " argument in " ++ brk(1,1) ++ pc ++ str "."
let error_same_names_types id =
str "The name" ++ spc () ++ pr_id id ++ spc () ++
@@ -852,7 +1100,8 @@ let error_same_names_overlap idl =
prlist_with_sep pr_comma pr_id idl ++ str "."
let error_not_an_arity env c =
- str "The type" ++ spc () ++ pr_lconstr_env env c ++ spc () ++ str "is not an arity."
+ str "The type" ++ spc () ++ pr_lconstr_env env Evd.empty c ++ spc () ++
+ str "is not an arity."
let error_bad_entry () =
str "Bad inductive definition."
@@ -864,12 +1113,12 @@ let error_large_non_prop_inductive_not_in_type () =
let error_not_allowed_case_analysis isrec kind i =
str (if isrec then "Induction" else "Case analysis") ++
- strbrk " on sort " ++ pr_sort kind ++
+ strbrk " on sort " ++ pr_sort Evd.empty kind ++
strbrk " is not allowed for inductive definition " ++
- pr_inductive (Global.env()) i ++ str "."
+ pr_inductive (Global.env()) (fst i) ++ str "."
let error_not_mutual_in_scheme ind ind' =
- if ind = ind' then
+ if eq_ind ind ind' then
str "The inductive type " ++ pr_inductive (Global.env()) ind ++
str " occurs twice."
else
@@ -890,7 +1139,8 @@ let explain_inductive_error = function
| SameNamesOverlap idl -> error_same_names_overlap idl
| NotAnArity (env, c) -> error_not_an_arity env c
| BadEntry -> error_bad_entry ()
- | LargeNonPropInductiveNotInType -> error_large_non_prop_inductive_not_in_type ()
+ | LargeNonPropInductiveNotInType ->
+ error_large_non_prop_inductive_not_in_type ()
(* Recursion schemes errors *)
@@ -901,9 +1151,9 @@ let explain_recursion_scheme_error = function
(* Pattern-matching errors *)
-let explain_bad_pattern env cstr ty =
+let explain_bad_pattern env sigma cstr ty =
let env = make_all_name_different env in
- let pt = pr_lconstr_env env ty in
+ let pt = pr_lconstr_env env sigma ty in
let pc = pr_constructor env cstr in
str "Found the constructor " ++ pc ++ brk(1,1) ++
str "while matching a term of type " ++ pt ++ brk(1,1) ++
@@ -918,128 +1168,134 @@ let explain_bad_constructor env cstr ind =
str "is expected."
let decline_string n s =
- if n = 0 then "no "^s^"s"
- else if n = 1 then "1 "^s
+ if Int.equal n 0 then "no "^s^"s"
+ else if Int.equal n 1 then "1 "^s
else (string_of_int n^" "^s^"s")
let explain_wrong_numarg_constructor env cstr n =
str "The constructor " ++ pr_constructor env cstr ++
- str " expects " ++ str (decline_string n "argument") ++ str "."
+ str " (in type " ++ pr_inductive env (inductive_of_constructor cstr) ++
+ str ") expects " ++ str (decline_string n "argument") ++ str "."
let explain_wrong_numarg_inductive env ind n =
str "The inductive type " ++ pr_inductive env ind ++
str " expects " ++ str (decline_string n "argument") ++ str "."
-let explain_wrong_predicate_arity env pred nondep_arity dep_arity=
- let env = make_all_name_different env in
- let pp = pr_lconstr_env env pred in
- str "The elimination predicate " ++ spc () ++ pp ++ fnl () ++
- str "should be of arity" ++ spc () ++
- pr_lconstr_env env nondep_arity ++ spc () ++
- str "(for non dependent case) or" ++
- spc () ++ pr_lconstr_env env dep_arity ++ spc () ++ str "(for dependent case)."
-
-let explain_needs_inversion env x t =
- let env = make_all_name_different env in
- let px = pr_lconstr_env env x in
- let pt = pr_lconstr_env env t in
- str "Sorry, I need inversion to compile pattern matching on term " ++
- px ++ str " of type: " ++ pt ++ str "."
-
let explain_unused_clause env pats =
(* Without localisation
let s = if List.length pats > 1 then "s" else "" in
(str ("Unused clause with pattern"^s) ++ spc () ++
- hov 0 (prlist_with_sep pr_spc pr_cases_pattern pats) ++ str ")")
+ hov 0 (pr_sequence pr_cases_pattern pats) ++ str ")")
*)
str "This clause is redundant."
let explain_non_exhaustive env pats =
str "Non exhaustive pattern-matching: no clause found for " ++
- str (plural (List.length pats) "pattern") ++
- spc () ++ hov 0 (prlist_with_sep pr_spc pr_cases_pattern pats)
+ str (String.plural (List.length pats) "pattern") ++
+ spc () ++ hov 0 (pr_sequence pr_cases_pattern pats)
-let explain_cannot_infer_predicate env typs =
+let explain_cannot_infer_predicate env sigma typs =
let env = make_all_name_different env in
let pr_branch (cstr,typ) =
let cstr,_ = decompose_app cstr in
- str "For " ++ pr_lconstr_env env cstr ++ str ": " ++ pr_lconstr_env env typ
+ str "For " ++ pr_lconstr_env env sigma cstr ++ str ": " ++ pr_lconstr_env env sigma typ
in
str "Unable to unify the types found in the branches:" ++
- spc () ++ hov 0 (prlist_with_sep pr_fnl pr_branch (Array.to_list typs))
+ spc () ++ hov 0 (prlist_with_sep fnl pr_branch (Array.to_list typs))
-let explain_pattern_matching_error env = function
+let explain_pattern_matching_error env sigma = function
| BadPattern (c,t) ->
- explain_bad_pattern env c t
+ explain_bad_pattern env sigma c t
| BadConstructor (c,ind) ->
explain_bad_constructor env c ind
| WrongNumargConstructor (c,n) ->
explain_wrong_numarg_constructor env c n
| WrongNumargInductive (c,n) ->
explain_wrong_numarg_inductive env c n
- | WrongPredicateArity (pred,n,dep) ->
- explain_wrong_predicate_arity env pred n dep
- | NeedsInversion (x,t) ->
- explain_needs_inversion env x t
| UnusedClause tms ->
explain_unused_clause env tms
| NonExhaustive tms ->
explain_non_exhaustive env tms
| CannotInferPredicate typs ->
- explain_cannot_infer_predicate env typs
+ explain_cannot_infer_predicate env sigma typs
let explain_reduction_tactic_error = function
- | Tacred.InvalidAbstraction (env,c,(env',e)) ->
+ | Tacred.InvalidAbstraction (env,sigma,c,(env',e)) ->
str "The abstracted term" ++ spc () ++
- quote (pr_goal_concl_style_env env c) ++
+ quote (pr_goal_concl_style_env env sigma c) ++
spc () ++ str "is not well typed." ++ fnl () ++
explain_type_error env' Evd.empty e
-let explain_ltac_call_trace (nrep,last,trace,loc) =
- let calls =
- (nrep,last) :: List.rev (List.map(fun(n,_,ck)->(n,ck))trace) in
- let tacexpr_differ te te' =
- (* NB: The following comparison may raise an exception
- since a tacexpr may embed a functional part via a TacExtend *)
- try te <> te' with Invalid_argument _ -> false
+let is_defined_ltac trace =
+ let rec aux = function
+ | (_, Proof_type.LtacNameCall f) :: tail ->
+ not (Tacenv.is_ltac_for_ml_tactic f)
+ | (_, Proof_type.LtacAtomCall _) :: tail ->
+ false
+ | _ :: tail -> aux tail
+ | [] -> false in
+ aux (List.rev trace)
+
+let explain_ltac_call_trace last trace loc =
+ let calls = last :: List.rev_map snd trace in
+ let pr_call ck = match ck with
+ | Proof_type.LtacNotationCall kn -> quote (KerName.print kn)
+ | Proof_type.LtacNameCall cst -> quote (Pptactic.pr_ltac_constant cst)
+ | Proof_type.LtacMLCall t ->
+ quote (Pptactic.pr_glob_tactic (Global.env()) t)
+ | Proof_type.LtacVarCall (id,t) ->
+ quote (Nameops.pr_id id) ++ strbrk " (bound to " ++
+ Pptactic.pr_glob_tactic (Global.env()) t ++ str ")"
+ | Proof_type.LtacAtomCall te ->
+ quote (Pptactic.pr_glob_tactic (Global.env())
+ (Tacexpr.TacAtom (Loc.ghost,te)))
+ | Proof_type.LtacConstrInterp (c, { Pretyping.ltac_constrs = vars }) ->
+ quote (pr_glob_constr_env (Global.env()) c) ++
+ (if not (Id.Map.is_empty vars) then
+ strbrk " (with " ++
+ prlist_with_sep pr_comma
+ (fun (id,c) ->
+ pr_id id ++ str ":=" ++ Printer.pr_lconstr_under_binders c)
+ (List.rev (Id.Map.bindings vars)) ++ str ")"
+ else mt())
in
- let pr_call (n,ck) =
- (match ck with
- | Proof_type.LtacNotationCall s -> quote (str s)
- | Proof_type.LtacNameCall cst -> quote (Pptactic.pr_ltac_constant cst)
- | Proof_type.LtacVarCall (id,t) ->
- quote (Nameops.pr_id id) ++ strbrk " (bound to " ++
- Pptactic.pr_glob_tactic (Global.env()) t ++ str ")"
- | Proof_type.LtacAtomCall (te,otac) -> quote
- (Pptactic.pr_glob_tactic (Global.env())
- (Tacexpr.TacAtom (dummy_loc,te)))
- ++ (match !otac with
- | Some te' when tacexpr_differ (Obj.magic te') te ->
- strbrk " (expanded to " ++ quote
- (Pptactic.pr_tactic (Global.env())
- (Tacexpr.TacAtom (dummy_loc,te')))
- ++ str ")"
- | _ -> mt ())
- | Proof_type.LtacConstrInterp (c,(vars,unboundvars)) ->
- let filter =
- function (id,None) -> None | (id,Some id') -> Some(id,([],mkVar id')) in
- let unboundvars = list_map_filter filter unboundvars in
- quote (pr_glob_constr_env (Global.env()) c) ++
- (if unboundvars <> [] or vars <> [] then
- strbrk " (with " ++
- prlist_with_sep pr_comma
- (fun (id,c) ->
- pr_id id ++ str ":=" ++ Printer.pr_lconstr_under_binders c)
- (List.rev vars @ unboundvars) ++ str ")"
- else mt())) ++
- (if n=2 then str " (repeated twice)"
- else if n>2 then str " (repeated "++int n++str" times)"
- else mt()) in
- if calls <> [] then
- let kind_of_last_call = match list_last calls with
- | (_,Proof_type.LtacConstrInterp _) -> ", last term evaluation failed."
- | _ -> ", last call failed." in
+ match calls with
+ | [] -> mt ()
+ | _ ->
+ let kind_of_last_call = match List.last calls with
+ | Proof_type.LtacConstrInterp _ -> ", last term evaluation failed."
+ | _ -> ", last call failed."
+ in
hov 0 (str "In nested Ltac calls to " ++
pr_enum pr_call calls ++ strbrk kind_of_last_call)
+
+let skip_extensions trace =
+ let rec aux = function
+ | (_,Proof_type.LtacNameCall f as tac) :: _
+ when Tacenv.is_ltac_for_ml_tactic f -> [tac]
+ | (_,(Proof_type.LtacNotationCall _ | Proof_type.LtacMLCall _) as tac)
+ :: _ -> [tac]
+ | t :: tail -> t :: aux tail
+ | [] -> [] in
+ List.rev (aux (List.rev trace))
+
+let extract_ltac_trace trace eloc =
+ let trace = skip_extensions trace in
+ let (loc,c),tail = List.sep_last trace in
+ if is_defined_ltac trace then
+ (* We entered a user-defined tactic,
+ we display the trace with location of the call *)
+ let msg = hov 0 (explain_ltac_call_trace c tail eloc ++ fnl()) in
+ Some msg, loc
else
- mt ()
+ (* We entered a primitive tactic, we don't display trace but
+ report on the finest location *)
+ let best_loc =
+ if not (Loc.is_ghost eloc) then eloc else
+ (* trace is with innermost call coming first *)
+ let rec aux = function
+ | (loc,_)::tail when not (Loc.is_ghost loc) -> loc
+ | _::tail -> aux tail
+ | [] -> Loc.ghost in
+ aux trace in
+ None, best_loc