2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!有关如何工作的更多信息,请参阅 关于 页面。

+1
错误

没有存在的命名空间定义的 var 引用将导致此错误

user> (def foo/bar 1) 编译错误在 def 编译中 (REPL:1:1)。不能在当前命名空间之外创建定义

原因: 编译器 lookupVar() 如果有资格变量中的命名空间不存在,则返回 null。

建议: 指出符号并通过带有文件/行/列信息的 CompilerException 抛出错误消息将改善错误信息。这可能是不太明显,但在这种情况下可能只有这种错误发生。如果是这样,错误消息可以更具体地指出命名空间是部分不存在。

补丁: clj-1400-4.diff

审核: Alex Miller

14 条回答

0

评论者:scottbale

在我看来,这看起来像是相对容易解决的问题,除非我漏掉了什么;将任务分配给自己。

0

评论者:scottbale

将补丁 {{clj-1400-1.diff}} 应用到 {{Compiler.java}}。

使用此补丁,示例现在将如下所示

user> (def foo/bar 1) CompilerException java.lang.RuntimeException: 有资格的符号 foo/bar 指向不存在的命名空间:foo,编译:(NO_SOURCE_PATH:1:1)

我不确定 {{if(namesStaticMember(sym))}}(链接:见下文)和第二个分支是否甚至必要。仅从检查来看,我怀疑它不是。

(链接:脚注)

`
public static boolean namesStaticMember(Symbol sym){

return sym.ns != null && namespaceFor(sym) == null;

}
`

0

评论者:scottbale

补丁:代码和测试

0

评论者:scottbale

我在实际源文件上进行了测试,异常信息包括了所需的文件/行/列信息

user=> CompilerException java.lang.RuntimeException: 有资格的符号 goo/bar 指向不存在的命名空间:goo,编译:( /home/scott/dev/foo.clj:3:1 )

0

评论者:jafingerhut

补丁 clj-1400-1.diff 中的 Jun 26 2014 日期,在 2014 年 8 月 29 日对 Clojure 进行了一些提交之后,不再可以干净地应用于最新的 master 版本。在那一天之前可以干净地应用。

我还没有检查更新这个补丁是否容易或困难。请参阅此维基页面上关于更新补丁的一些提示:“更新过时的补丁”部分:http://dev.clojure.org/display/community/Developing Patches

0

评论者:scottbale

附上一个更新的补丁:“clj-1400-2.diff”。我已经移除了过时的补丁。

0

评论者:alexmiller

有几个评论需要解决
- 编译器差异使用了空格,而不是制表符,这使得比较更加困难。我附上一个 -3.diff 来修复这个问题。
- namesStaticMember 的调用看起来很奇怪。那个方法的名称对于这种用途来说很令人混淆。除此之外,我认为它做了你不需要的事情。那个方法将尝试根据当前 ns 解析有资格的名称,但我想你甚至不需要这样做。你只是想知道 sym 是否有 ns (sym.ns != null) - 这不是足够吗?
- 在什么情况下会触发其他错误“变量不存在”?换句话说,在什么情况下 lookupVar 不会在这里创建一个新的 var?如果没有这样的情况,那么可以删除这个用例。如果有这样的情况,那么添加一个测试案例。

0

评论者:scottbale

同意你提到的所有三点。附件是更新后的补丁文件,clj-1400-4.diff。
我在Compiler.java中使用了Tab 经过对lookupVar(...)调用的仔细检查,我认为仅在这张票据的情况下会返回null(符号拥有尚未加载数空间的非null命名空间)。因此,我已经删除了条件语句和第2个分支。
* (测试未更改)

0

评论者:scottbale

(补丁文件命名正确)

0

评论者:alexmiller

你可以根据票据描述的提示,抛出带有问题位置的CompilerException。

0

评论者:scottbale

对不起,我应该提到这一点,因为这对我来说也不明显(并且实际上我直到现在才意识到):RuntimeException已经被捕获并以CompilerException的形式封装。

我不确定Compiler.java中哪个try-catch块发生这种情况,因为有几个。但是,您可以在输出中看到异常是CompilerException,并且有文件|行|列信息

在Repl...

user> (def foo/bar 1) CompilerException java.lang.RuntimeException: 有资格的符号 foo/bar 指向不存在的命名空间:foo,编译:(NO_SOURCE_PATH:1:1)

...或者在源文件中

user=> CompilerException java.lang.RuntimeException: 有资格的符号 goo/bar 指向不存在的命名空间:goo,编译:( /home/scott/dev/foo.clj:3:1 )

此外,在抛出当前补丁的RuntimeException的点,CompilerException的{{source}} {{line}}和{{col}}参数不可用,或者至少不是afaict(据我所知)。

0

评论者:alexmiller

我将在稍后跟进这个补丁 - Rich认为它做了太多的假设。我认为我们已经验证了许多这些假设,但需要再次检查。

0

评论者:alexmiller

截至 Clojure 1.10 的更新错误结果。现在正在抛出带有文件/行/列的编译语法错误阶段异常。

0
参考:https://clojure.atlassian.net/browse/CLJ-1400(由 hlewisship 报告)
...