From ebd7cec8348d212e0dcd2490bdf559b671fe9b8d Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 5 Nov 2019 19:35:04 -0700 Subject: [PATCH] expander: fix higher-phase variable/syntax provide tracking The check for whether a provided identifier is syntax or a variable cuold incorrectly inspect a module that is not yet prepared for the relevant phase. --- .../racket-test-core/tests/racket/module.rktl | 21 +++++++++++++++++++ .../expand/binding-for-transformer.rkt | 1 + racket/src/racket/src/startup.inc | 6 +++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pkgs/racket-test-core/tests/racket/module.rktl b/pkgs/racket-test-core/tests/racket/module.rktl index 0b102e4527..541ba61d8a 100644 --- a/pkgs/racket-test-core/tests/racket/module.rktl +++ b/pkgs/racket-test-core/tests/racket/module.rktl @@ -3096,6 +3096,27 @@ case of module-leve bindings; it doesn't cover local bindings. exn:fail:contract? #rx"write: linklet is not serializable")) +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Make sure that re-exports at higher phases correctly track whether +;; the export is a variable or syntax + +(for ([meta '(1 2)]) + (define name (string->symbol (format "submodule-reexports-macro-at-meta-~a" meta))) + (eval `(module ,name racket/base + (module foo racket/base + (require (for-syntax racket/base)) + (provide x) + (define-syntax x 5)) + (module bar racket/base + (require (for-meta ,meta (submod ".." foo))) + (provide (for-meta ,meta x))))) + + (namespace-require `(submod ',name bar)) + + (let-values ([(vals stxes) (module->exports `(submod ',name bar))]) + (test 0 length vals) + (test 1 length stxes))) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/racket/src/expander/expand/binding-for-transformer.rkt b/racket/src/expander/expand/binding-for-transformer.rkt index 844c1689ef..2cf5abddc2 100644 --- a/racket/src/expander/expand/binding-for-transformer.rkt +++ b/racket/src/expander/expand/binding-for-transformer.rkt @@ -25,6 +25,7 @@ [else ;; Use `binding-lookup` to both check for taints and determine whether the ;; binding is a transformer or variable binding + (namespace-visit-available-modules! ns (+ at-phase (module-binding-phase b))) (define-values (val primitive? insp protected?) (binding-lookup b empty-env null ns at-phase id)) (not (variable? val))])) diff --git a/racket/src/racket/src/startup.inc b/racket/src/racket/src/startup.inc index 08ea2f1156..069ab2a6a2 100644 --- a/racket/src/racket/src/startup.inc +++ b/racket/src/racket/src/startup.inc @@ -73665,6 +73665,10 @@ static const char *startup_source = " #f)))" "(provided-as-transformer? b/p_0))))" "(let-values()" +"(let-values((()" +"(begin" +"(namespace-visit-available-modules! ns_0(+ at-phase_0(module-binding-phase b_0)))" +"(values))))" "(let-values(((val_0 primitive?_0 insp_0 protected?_0)" "(let-values(((b1_0) b_0)" "((empty-env2_0) empty-env)" @@ -73673,7 +73677,7 @@ static const char *startup_source = "((at-phase5_0) at-phase_0)" "((id6_0) id_0))" "(binding-lookup52.1 #f #f b1_0 empty-env2_0 null3_0 ns4_0 at-phase5_0 id6_0))))" -"(not(variable? val_0))))))))" +"(not(variable? val_0)))))))))" "(define-values(layers) '(raw phaseless id))" "(define-values(provide-form-name) 'provide)" "(define-values"