We're updating the issue view to help you get more done. 

Compiler doesn't preserve metadata for LazySeq literals

Description

The analyzer in Compiler.java forces evaluation of lazyseq literals, but loses the compile time original metadata of that form, meaning that a type hint will be lost.

Example demonstrating this issue:

1 2 3 4 5 6 7 user=> (set! *warn-on-reflection* true) true user=> (list '.substring (with-meta (concat '(identity) '("foo")) {:tag 'String}) 0) (.substring (identity "foo") 0) user=> (eval (list '.substring (with-meta (concat '(identity) '("foo")) {:tag 'String}) 0)) Reflection warning, NO_SOURCE_PATH:6:1 - call to method substring on java.lang.Object can't be resolved (no such method). "foo"

Forcing the concat call to an ASeq rather than a LazySeq fixes this issue:

1 2 user=> (eval (list '.hashCode (with-meta (seq (concat '(identity) '("foo"))) {:tag 'String}))) 101574

This ticket blocks http://dev.clojure.org/jira/browse/CLJ-1444 since clojure.core/sequence might return a lazyseq.

This bug affected both tools.analyzer and tools.reader and forced me to commit a fix in tools.reader to work around this issue, see: http://dev.clojure.org/jira/browse/TANAL-99

The proposed patch trivially preserves the form metadata after realizing the lazyseq

Approach: Keep a copy of the original form, and apply its metadata to the realized lazyseq
Patch: clj-1586-2.patch
Screened by: Alex Miller

Environment

None

Status

Assignee

Unassigned

Reporter

Nicola Mometto

Approval

Ok

Patch

Code and Test

Fix versions

Priority

Major