From 0caae7c2c89c8f099e45a3d04708dbcf3dd9b1b0 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 23 Aug 2018 15:21:11 -0400 Subject: [PATCH] fix #28593, macro hygiene problems in type definitions (#28706) (cherry picked from commit cd850de63cce34f53ec9120e04b26bde7e38ac2c) --- src/julia-syntax.scm | 18 +++++++++++++----- src/macroexpand.scm | 36 ++++++++++++++++++++++++++---------- test/syntax.jl | 27 +++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 15 deletions(-) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index abce5e47b6c20..4a3d43613cff1 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -200,9 +200,17 @@ (let ((bounds (map analyze-typevar params))) (values (map car bounds) bounds))) +(define (unmangled-name v) + (if (eq? v '||) + v + (let ((s (string v))) + (if (eqv? (string.char s 0) #\#) + (symbol (last (string-split s "#"))) + v)))) + ;; construct expression to allocate a TypeVar -(define (bounds-to-TypeVar v) - (let ((v (car v)) +(define (bounds-to-TypeVar v (unmangle #f)) + (let ((v ((if unmangle unmangled-name identity) (car v))) (lb (cadr v)) (ub (caddr v))) `(call (core TypeVar) ',v @@ -836,7 +844,7 @@ (block (global ,name) (const ,name) ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) (struct_type ,name (call (core svec) ,@params) (call (core svec) ,@(map quotify field-names)) ,super (call (core svec) ,@field-types) ,mut ,min-initialized))) @@ -877,7 +885,7 @@ (scope-block (block ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) (abstract_type ,name (call (core svec) ,@params) ,super)))))) (define (primitive-type-def-expr n name params super) @@ -888,7 +896,7 @@ (scope-block (block ,@(map (lambda (v) `(local ,v)) params) - ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v))) params bounds) + ,@(map (lambda (n v) (make-assignment n (bounds-to-TypeVar v #t))) params bounds) (primitive_type ,name (call (core svec) ,@params) ,n ,super)))))) ;; take apart a type signature, e.g. T{X} <: S{Y} diff --git a/src/macroexpand.scm b/src/macroexpand.scm index 2c7a040e39f53..abad3407656fd 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -135,16 +135,21 @@ (if var (list 'varlist var) '())) ;; type definition - (pattern-lambda (struct mut (<: (curly tn . tvars) super) body) - (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) - (typevar-names tvars))) - (pattern-lambda (struct mut (curly tn . tvars) body) - (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) - (typevar-names tvars))) - (pattern-lambda (struct mut (<: tn super) body) - (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) - (pattern-lambda (struct mut tn body) - (list 'varlist (cons (unescape tn) (unescape tn)) '(new . new))) + (pattern-lambda (struct mut spec body) + (let ((tn (typedef-expr-name spec)) + (tv (typedef-expr-tvars spec))) + (list* 'varlist (cons (unescape tn) (unescape tn)) '(new . new) + (typevar-names tv)))) + (pattern-lambda (abstract spec) + (let ((tn (typedef-expr-name spec)) + (tv (typedef-expr-tvars spec))) + (list* 'varlist (cons (unescape tn) (unescape tn)) + (typevar-names tv)))) + (pattern-lambda (primitive spec nb) + (let ((tn (typedef-expr-name spec)) + (tv (typedef-expr-tvars spec))) + (list* 'varlist (cons (unescape tn) (unescape tn)) + (typevar-names tv)))) )) ; vars-introduced-by-patterns @@ -178,6 +183,17 @@ (cadr e) e)) +(define (typedef-expr-name e) + (cond ((atom? e) e) + ((or (eq? (car e) 'curly) (eq? (car e) '<:)) (typedef-expr-name (cadr e))) + (else e))) + +(define (typedef-expr-tvars e) + (cond ((atom? e) '()) + ((eq? (car e) '<:) (typedef-expr-tvars (cadr e))) + ((eq? (car e) 'curly) (cddr e)) + (else '()))) + (define (typevar-expr-name e) (car (analyze-typevar e))) ;; get the list of names from a list of `where` variable expressions diff --git a/test/syntax.jl b/test/syntax.jl index 4e4417dd5a3b6..9e12206ad8325 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1646,3 +1646,30 @@ end # issue #28576 @test Meta.isexpr(Meta.parse("1 == 2 ?"), :incomplete) @test Meta.isexpr(Meta.parse("1 == 2 ? 3 :"), :incomplete) + +# issue #28593 +macro a28593() + quote + abstract type A28593{S<:Real, V<:AbstractVector{S}} end + end +end + +macro b28593() + quote + struct B28593{S<:Real, V<:AbstractVector{S}} end + end +end + +macro c28593() + quote + primitive type C28593{S<:Real, V<:AbstractVector{S}} 32 end + end +end + +@a28593 +@b28593 +@c28593 + +@test A28593.var.name === :S +@test B28593.var.name === :S +@test C28593.var.name === :S