fix some "phaseless" module holes

This commit is contained in:
Matthew Flatt 2013-02-26 18:30:20 -07:00
parent 30c381f0b1
commit 2e652fc2b3
5 changed files with 49 additions and 8 deletions

View File

@ -629,7 +629,7 @@ is specified as @tech{phaseless} (such as
@racketmodname[racket/kernel]).
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@subsection[#:tag "module-redeclare"]{Module Re-declarations}
@subsection[#:tag "module-redeclare"]{Module Redeclarations}
@section-index["modules" "re-define"]
@ -642,9 +642,17 @@ module body. If a new variable definition has a counterpart in the old
declaration, it effectively assigns to the old variable.
If a module is @tech{instantiate}d in any @tech{phase}s before it is
re-declared, each re-declaration of the module is immediately
redeclared, each redeclaration of the module is immediately
@tech{instantiate}d in the same @tech{phase}s.
If the current @tech{inspector} does not manage a module's declaration
inspector (see @secref["modprotect"]), then the module cannot be
redeclared. Similarly, a @tech{phaseless} module cannot be redeclared.
Even if redeclrection succeeds, instantiation of a module that is
previously instantiated may fail if instantiation for the
redeclaration attempts to modify variables that are constant (see
@racket[compile-enforce-module-constants]).
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@subsection[#:tag "submodules"]{Submodules}

View File

@ -992,8 +992,9 @@ to syntax transformers, via @racket[syntax-local-name].
@section[#:tag "phaseless-grammar"]{Phaseless Module Declarations}
A module is @tech{phaseless} only if it fits the following grammar,
which uses non-terminals from @secref["fully-expanded"], and only if
it includes no uses of @racket[quote-syntax] or @racket[#%variable-reference]:
which uses non-terminals from @secref["fully-expanded"], only if
it includes no uses of @racket[quote-syntax] or @racket[#%variable-reference],
and only if no module-level binding is @racket[set!]ed.
@racketgrammar*[
#:literals (module module* #%plain-module-begin begin #%provide

View File

@ -9,7 +9,7 @@
(define i (open-input-bytes (get-output-bytes o)))
(define e (zo-parse i))
(unless (equal? is? (and (memq 'phaseless (mod-flags (compilation-top-code e))) #t))
(error 'phaseless "failed: ~s ~s\n" is? form))))
(error 'phaseless "failed: ~s ~s" is? form))))
(check-phaseless #t '(define-values (x) 5))
(check-phaseless #t '(define-values (x) '5))
@ -35,6 +35,7 @@
(check-phaseless #f '(define-values (x) #(x)))
(check-phaseless #f '(define-values (x) '(x)))
(check-phaseless #f '(define-values (x) (lambda () (set! x 8))))
(check-phaseless #f '(define-values (x) (quote-syntax x)))
(check-phaseless #f '(define-values (x) (lambda () (quote-syntax x))))
(check-phaseless #f '(define-values (x) (#%variable-reference)))
@ -74,5 +75,22 @@
(check-attach namespace-attach-module)
(check-attach namespace-attach-module-declaration))
;; Check disallowing redeclaration:
(parameterize ([current-namespace (make-base-namespace)])
(parameterize ([compile-enforce-module-constants #f])
(eval `(module m racket/kernel
(#%provide x)
(define-values (x) 5)))
(compile `(module m racket/kernel
(#%provide x)
(define-values (x) 6)))
(unless (void?
(with-handlers ([exn:fail? void])
(eval `(module m racket/kernel
(#%provide x)
(define-values (x) 6)))
'ok))
(error 'phaseless "redeclaration should have been disallowed"))))
(displayln "All tests passed.")

View File

@ -1203,6 +1203,7 @@ set_syntax (Scheme_Object *form, Scheme_Comp_Env *env, Scheme_Compile_Info *rec,
var = scheme_register_toplevel_in_prefix(var, env, rec, drec, 0, NULL);
if (env->genv->module)
SCHEME_TOPLEVEL_FLAGS(var) |= SCHEME_TOPLEVEL_MUTATED;
env->prefix->non_phaseless = 1;
}
scheme_compile_rec_done_local(rec, drec);

View File

@ -6272,7 +6272,7 @@ static Scheme_Object *do_module_execute(Scheme_Object *data, Scheme_Env *genv,
Scheme_Object *prefix,
Scheme_Object *supermodule)
{
Scheme_Module *m;
Scheme_Module *m, *old_m;
Scheme_Env *env;
Scheme_Env *old_menv;
Scheme_Config *config;
@ -6366,13 +6366,26 @@ static Scheme_Object *do_module_execute(Scheme_Object *data, Scheme_Env *genv,
if (old_menv) {
if (scheme_module_protected_wrt(old_menv->guard_insp, insp) || old_menv->attached) {
scheme_contract_error("module->namespace",
"current code inspector cannot re-declare module",
"current code inspector cannot redeclare module",
"module name", 1, m->modname,
NULL);
return NULL;
}
}
if (old_menv)
old_m = old_menv->module;
else
old_m = (Scheme_Module *)scheme_hash_get(env->module_registry->loaded, m->modname);
if (old_m && old_m->phaseless) {
scheme_contract_error("module->namespace",
"cannot redeclare phaseless module",
"module name", 1, m->modname,
NULL);
return NULL;
}
if (!set_in_pre) {
/* execute pre-submodules: */
execute_submodules(m, 1, genv, set_cache, set_in_pre, prefix);
@ -7117,7 +7130,7 @@ static Scheme_Object *do_module(Scheme_Object *form, Scheme_Comp_Env *env,
m->tt_requires = scheme_null;
m->dt_requires = scheme_null;
if (iim && iim->phaseless)
if (iim && iim->phaseless && rec[drec].comp)
m->phaseless = scheme_true;
if (iidx) {