I think there are two problems in this example.
The first problem is that preserved syntax properties were not actually preserved in bytecode for a syntax object that has no source location. (I'm assuming that Alexis's tests were run in DrRacket in it's default mode of compiling bytecode for `require`d files.) I'll push a repair for that bug. The second problem is that syntax objects as property values don't work the way that you want. That limitation is why, even with the property-presevation bug fixed, the `free-identifier=?` test fails. Unfortunately, that's a limitation of syntax objects and properties that's difficult to resolve. To explain a little more, consider the program https://gist.github.com/mflatt/d569d8f3a89e6815cf18df26adc11053 For now, look at just the `property` submodule. The `quote-syntax/add-example-property` macro is like `quote-syntax`, except that it adds an 'example property that holds the current time at compile time. An expression like (syntax-property (quote-syntax/add-example-property id) 'example) accesses that compile-time value at run time. If you compile the program to bytecode, the value shown by running the module later still reports the time that the module was compiled. Now consider the enclosing module, which uses the `property` submodule and accesses the time for both a freshly quoted term and the value of `id` as exported by the submodule: (require 'property) (syntax-property (quote-syntax/add-example-property new-id) 'example) (syntax-property id 'example) I think you won't be too surprised that the freshly quoted identifier has a newer time than the one reported for `id`. Even though both values were obtained from the same `compile-time` variable, each module compilation (submodule and enclosing module) gets a fresh instance of `compile-time`. In "format-id1.rkt", instead of `compile-time` bound to a timestamp, you have a quoted syntax object that you can image being implicitly lifted as (define-for-syntax compile-time #'id^) In much the same way that `(current-inexact-milliseconds)` in (define-for-syntax compile-time (current-inexact-milliseconds)) produces a different result for each subsequent compile-time use of the modules, `#'id^` produces a different syntax object depending on how its enclosing module is instantiated. Imagine taking the compiled bytecode, saving it in two places, and loading it as a module from each place; the `#'id` evaluations for the copies will produce identifiers that claim to be from different modules relative to the filesystem. So, here's the limitation: the implicit lifting that happens for a quoted syntax object, which enables a kind of re-evaluation of that syntax object in each module instance, doesn't happen for syntax-property values. More generally, changes to the scope of a syntax object are not propagated to property values that happen to be themselves syntax objects. When you put a syntax object into a property, then you get whatever that syntax object meant at the time it was attached as a property. That might still sound ok for your case, because you compile and use "format-id1.rkt" in-place. Still, the information attached to `#'id^` changes. While compiling the module, the attached binding information says "the current module being compiled". When compiling "format-id2.rkt", the attached binding information for that `#'id^` says "format-id1.rkt". To summarize, don't try to attach syntax objects as property values like that. I know this advice sounds ironic, given that the original use of properties was for syntax-valued keys like 'origin. Properties like 'origin are meant to be extracted from just-expanded programs, though, as opposed to used in a later compilation step. At the same time, those uses of properties are why we can't just make `syntax-property` reject property values that are syntax objects. At Tue, 13 Dec 2016 14:16:49 -0800, Alexis King wrote: > > On Dec 13, 2016, at 11:23 AM, 'William J. Bowman' via Racket Users > > <racket-users@googlegroups.com> wrote: > > > > Notice that #'x is not the same identifier as x, and thus does not > > have the same syntax-properties. > > I’m not convinced this is correct. > > If you insert println statements in the body of define^, inside the > with-syntax block, you get the following: > > (println (syntax-property #'x 'definition)) > (println (syntax-property-preserved? #'x 'definition)) > > ; => #<syntax:format-id1.rkt:49:12 id^> > ; => #t > > The syntax properties are definitely maintained in templates used > by `syntax`. > > > Why does this issue only comes up across a file boundary? I suspect > > this has to do with the behavior of make-rename-transformer. Since > > #'x was not getting 'not-free-identifier=? correctly, > > make-rename-transformer was optimizing this away, although I thought > > I was preventing that. > > This is more interesting, and it was my first instinct, too. For > that reason, I replaced uses of make-rename-transformer with uses > of make-variable-like-transformer from syntax/transformer, but the > behavior was the same, so I don’t think this has to do with > make-rename-transformer specifically. However, something more > interesting happens. > > I changed the macro that define^ defines to insert some debugging > calls on macro invocation: > > (define-syntax (id stx) > (println (syntax-property #'x 'definition)) > (println (syntax-property-preserved? #'x 'definition)) > ((set!-transformer-procedure > (make-variable-like-transformer #'x)) > stx)) > > The output of this is much more interesting. When running the source > module, format-id1.rkt, the result is as one would expect: > > ; => #<syntax:format-id1.rkt:49:12 id^> > ; => #t > > However, when using the defined identifier from format-id2.rkt, the > result is different: > > ; => #f > ; => #f > > This is extremely interesting, since the first example demonstrates > that the syntax property is most definitely marked as preserved, > yet it gets lost by the time format-id2 tries to get at it, despite > the fact that it should be the same exact syntax object. > > My guess as to what’s going on here is that the issue is not with > make-rename-transformer but with quote-syntax. The above program > expands into a macro definition that has (quote-syntax x) in it, > and the x has a preserved syntax property on it. However, that > property is not actually preserved, despite being marked as preserved. > This is different from other uses of preserved syntax properties > that attach their syntax properties to expressions in the resulting > program, rather than quoted pieces of syntax. > > This feels very confusing, and it certainly feels like a bug, but > maybe Matthew has an explanation for this behavior that I don’t > currently understand? > > Alexis > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.