Skip to content

Commit fa7aa5b

Browse files
committed
improve warning message
including the original source location, and suggesting the positive-predicate alternative
1 parent bf6c3cf commit fa7aa5b

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

typed-racket-lib/typed-racket/base-env/prims-contract.rkt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,13 +306,14 @@
306306
(define (define-predicate stx)
307307
(syntax-parse stx
308308
[(_ name:id ty:expr)
309+
#:with ty* (syntax-property #'ty 'orig-stx-ctx stx)
309310
#`(begin
310311
;; We want the value bound to name to have a nice object name. Using the built in mechanism
311312
;; of define has better performance than procedure-rename.
312313
#,(ignore
313314
(syntax/loc stx
314315
(define name
315-
(let ([pred (make-predicate ty)])
316+
(let ([pred (make-predicate ty*)])
316317
(lambda (x) (pred x))))))
317318
;; not a require, this is just the unchecked declaration syntax
318319
#,(internal (syntax/loc stx (require/typed-internal name (Any -> Boolean : ty)))))]))
@@ -321,9 +322,10 @@
321322
(define (make-predicate stx)
322323
(syntax-parse stx
323324
[(_ ty:expr)
325+
#:with ty* (syntax-property #'ty 'orig-stx-ctx (or (syntax-property #'ty 'orig-stx-ctx) stx))
324326
; passing #t for exact? makes it produce a warning on Opaque types
325327
(define name (syntax-local-lift-expression
326-
(make-contract-def-rhs #'ty #t #t #f)))
328+
(make-contract-def-rhs #'ty* #t #t #f)))
327329
(define (check-valid-type _)
328330
(define type (parse-type #'ty))
329331
(define vars (fv type))

typed-racket-lib/typed-racket/private/type-contract.rkt

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
(define (generate-contract-def stx cache sc-cache)
9191
(define prop (get-contract-def-property stx))
9292
(match-define (contract-def type-stx flat? exact? maker? typed-side) prop)
93+
(define orig-stx-ctx (and type-stx (syntax-property type-stx 'orig-stx-ctx)))
9394
(define *typ (if type-stx (parse-type type-stx) t:-Dead-Code))
9495
(define kind (if (and type-stx flat?) 'flat 'impersonator))
9596
(syntax-parse stx #:literals (define-values)
@@ -104,18 +105,19 @@
104105
((map fld-t (Struct-flds ty)) #f . t:->* . *typ)])]
105106
[else *typ]))
106107
(match-define (list defs ctc)
107-
(type->contract
108-
typ
109-
;; this value is from the typed side (require/typed, make-predicate, etc)
110-
;; unless it's used for with-type
111-
#:typed-side (from-typed? typed-side)
112-
#:kind kind
113-
#:exact? exact?
114-
#:cache cache
115-
#:sc-cache sc-cache
116-
(type->contract-fail
117-
typ type-stx
118-
#:ctc-str (if flat? "predicate" "contract"))))
108+
(parameterize ([current-syntax-context orig-stx-ctx])
109+
(type->contract
110+
typ
111+
;; this value is from the typed side (require/typed, make-predicate, etc)
112+
;; unless it's used for with-type
113+
#:typed-side (from-typed? typed-side)
114+
#:kind kind
115+
#:exact? exact?
116+
#:cache cache
117+
#:sc-cache sc-cache
118+
(type->contract-fail
119+
typ type-stx
120+
#:ctc-str (if flat? "predicate" "contract")))))
119121
(ignore ; should be ignored by the optimizer
120122
(quasisyntax/loc stx
121123
(begin #,@defs (define-values (n) #,ctc))))]
@@ -546,9 +548,21 @@
546548
(promise/sc (t->sc t))]
547549
[(Opaque: p?)
548550
(when exact?
549-
(eprintf
550-
"warning: Opaque predicates cannot be used as exact decisions yes/no:\n predicate: ~s\n"
551-
(syntax-e p?)))
551+
(define stx (current-syntax-context))
552+
(display-syntax-warning
553+
#f
554+
(format
555+
(string-append
556+
"warning: cannot safely generate exact predicate for Opaque type\n"
557+
(case (and (syntax? stx) (pair? (syntax-e stx)) (syntax-e (car (syntax-e stx))))
558+
[(define-predicate) " (consider using define-positive-predicate instead)\n"]
559+
[(make-predicate) " (consider using make-positive-predicate instead)\n"]
560+
[else " (consider generating a positive-predicate instead)\n"])
561+
" type: ~a\n"
562+
" pred: ~s\n")
563+
type
564+
(syntax-e p?))
565+
stx))
552566
(flat/sc #`(flat-named-contract (quote #,(syntax-e p?)) #,p?))]
553567
[(Continuation-Mark-Keyof: t)
554568
(continuation-mark-key/sc (t->sc t))]
@@ -1237,3 +1251,13 @@
12371251
[(== t:-NonPosExtFlonum) nonpositive-extflonum/sc]
12381252
[(== t:-ExtFlonum) extflonum/sc]
12391253
[else #f]))
1254+
1255+
1256+
1257+
;; display-syntax-warning is like raise-syntax-error, except that it displays to
1258+
;; stderr and keeps going, instead of raising an exception
1259+
(define (display-syntax-warning name message [expr #f] [sub-expr #f])
1260+
(define (display-exn e) ((error-display-handler) (exn-message e) e))
1261+
(with-handlers ([exn:fail:syntax? display-exn])
1262+
(raise-syntax-error name message expr sub-expr)))
1263+

0 commit comments

Comments
 (0)