expander: fix shadowing require after shadowing define

Refines the repair in 11fd70c3dd to properly handle a `require` that
should be allowed to shadow the initial require.
This commit is contained in:
Matthew Flatt 2018-03-02 12:58:20 -07:00
parent 2104d02a23
commit e78eb0563a
3 changed files with 14277 additions and 13969 deletions

View File

@ -712,6 +712,17 @@
(test "last" dynamic-require ''definition-shadows-later-require/2 'result)
(module definition-shadows-require-shadowing-initial-require racket/base
(provide result)
(define version 42)
(module M racket/base
(provide (all-defined-out))
(define version 42))
(require 'M)
(define result version))
(test 42 dynamic-require ''definition-shadows-require-shadowing-initial-require 'result)
(err/rt-test
(eval
'(module m racket/base

View File

@ -297,14 +297,6 @@
(define defined? (and b (eq? (requires+provides-self r+p)
(module-binding-module b))))
(cond
[(and (not defined?) (not check-not-required?))
;; Not defined, and we're shadowing all requires -- so, it's ok,
;; but binding is non-simple
(set-requires+provides-all-bindings-simple?! r+p #f)
;; Also, record the `require` binding, in case we see another
;; `require` for the same identifier
(hash-set! (requires+provides-also-required r+p) (module-binding-sym b) b)
#f]
[(and defined?
;; In case `#%module-begin` is expanded multiple times, check
;; that the definition has been seen this particular expansion
@ -316,11 +308,13 @@
;; Doesn't count as previously defined
#f]
[else
(define define-shadowing-require? (and (not defined?) (not check-not-required?)))
(define mpi (intern-mpi r+p (module-binding-nominal-module b)))
(define at-mod (hash-ref (requires+provides-requires r+p) mpi #f))
(define ok-binding (if (procedure? ok-binding/delayed)
(define ok-binding (and (not define-shadowing-require?)
(if (procedure? ok-binding/delayed)
(ok-binding/delayed)
ok-binding/delayed))
ok-binding/delayed)))
(define (raise-already-bound defined?)
(raise-syntax-error who
(string-append "identifier already "
@ -333,7 +327,8 @@
orig-s
id))
(cond
[(not at-mod)
[(and (not at-mod)
(not define-shadowing-require?))
;; Binding is from an enclosing context; if it's from an
;; enclosing module, then we've already marked bindings
;; a non-simple --- otherwise, we don't care
@ -374,18 +369,31 @@
(define nominal-phase (module-binding-nominal-require-phase b))
(define sym-to-reqds (hash-ref at-mod nominal-phase #hasheq()))
(define reqds (hash-ref sym-to-reqds (syntax-e id) null))
(for ([r (in-list-ish reqds)])
(define only-can-can-shadow-require?
(for/fold ([only-can-can-shadow-require? #t]) ([r (in-list-ish reqds)])
(cond
[(if (bulk-required? r)
(bulk-required-can-be-shadowed? r)
(required-can-be-shadowed? r))
;; Shadowing --- ok, but non-simple
(set-requires+provides-all-bindings-simple?! r+p #f)]
[else (raise-already-bound defined?)]))
(set-requires+provides-all-bindings-simple?! r+p #f)
only-can-can-shadow-require?]
[define-shadowing-require? #f]
[else (raise-already-bound defined?)])))
(cond
[define-shadowing-require?
;; Not defined, but defining now (shadowing all requires);
;; make sure we indicated that the binding is non-simple
(set-requires+provides-all-bindings-simple?! r+p #f)
(unless only-can-can-shadow-require?
;; Record the `require` binding, if it's non-shadowable,
;; in case we see another `require` for the same identifier
(hash-set! (requires+provides-also-required r+p) (module-binding-sym b) b))]
[else
(when (and remove-shadowed!? (not (null? reqds)))
;; Same work as in `remove-required-id!`
(hash-set! sym-to-reqds (syntax-e id)
(remove-non-matching-requireds reqds id phase mpi nominal-phase (syntax-e id))))
(remove-non-matching-requireds reqds id phase mpi nominal-phase (syntax-e id))))])
#f])])]))
(define (add-defined-syms! r+p syms phase)

File diff suppressed because it is too large Load Diff