
hey, I’m having some trouble moving from racket 6.5 to 6.8. On racket 6.5 I can do the following: Welcome to Racket v6.5.
-> (require typed/json)
->
(struct my-test ())
-> (jsexpr? (my-test)) - : Boolean
#f
but in 6.8 things go awry:
Welcome to Racket v6.8.
> (require typed/json)
> (struct my-test ())
> (my-test)
- : my-test
#<my-test>
> (jsexpr? (my-test))
; jsexpr?: contract violation
; any-wrap/c: Unable to protect opaque value passed as `Any`
; value: #<my-test>
; in: the 1st argument of
; a part of the or/c of
; (or/c
; struct-predicate-procedure?/c
; (-> Any boolean?))
; contract from: (interface for jsexpr?)
; blaming: <pkgs>/typed-racket-more/typed/json.rkt
; (assuming the contract is correct)
; at: <pkgs>/typed-racket-more/typed/json.rkt:11.24
; [,bt for context]
`

any idea why the predicate from (require/typed/provide json …) is throwing contract violations on structs ?

@mebassett I think I can provide a high level answer, others may be able to give you a more precise answer and suggestion with how to proceed

basically, the Typed Racket developers realized that things like predicates imported from untyped code with the type (->Any Boolean)
need to be careful to ensure soundness

that predicate could totally muck with the data it is given, and so to prevent any mucking, a thin wrapper is placed around the data being tested by the imported predicate to ensure it is not abused

that’s the any-wrap/c
contract that is failing

it can’t protect the opaque struct my-test

solutions?

- don’t make the struct opaque

- if it’s too burdonsome to have the added safety of the any-wrap/c contract on values passed to
jsexpr?

and you trust that jsexpr?
isn’t going to muck with values passed to it

you could do the following:

#lang typed/racket
(require (except-in typed/json jsexpr?)
typed/racket/unsafe)
(unsafe-require/typed json [jsexpr? (-> Any Boolean)])
(struct my-test () #:transparent)
(jsexpr? (my-test))

here, we’re unsafely importing the jsexpr?
predicate, telling the type system “just trust me! don’t worry about things I pass to it! you don’t need to wrap them! I promise!”

(we’re also telling the type system to assume the result is always a Boolean
)

anyway, there’s probably a crappy description of the precise issue at hand, and some potential solutions

maybe someone else can provide some sage advice w.r.t. the “best” solution for something like this

Thanks for the response. I do remember something like this being a warning in 6.6. It is vexing that this crops up as a runtime error, rather than a compile-time error. In some cases I don’t have control over using an opaque structure or not. Say if I require/typed/provide Gregor, and then pass a gregor-date-struct into jsexpr?. Code compiles but throws a runtime error, which violates my naive understanding of “safe”.

I believe one of the releases made it a compile time warning

and then it was made an error in a later version

well safe code in any language can throw runtime errors

well, any language within reason

but yes, this was a nasty surprise, sorry for the inconvenience

@samth or some of the other TR devs might be able to provide better answer(s) as well

your answer matched with my prior reasoning of what was going on. I was more hoping I was wrong. :slightly_smiling_face:

thanks for the help.

I think the unsafe-require is the best option, and we should make a typed/json library that does that

while I have you both here - is there a public roadmap for typed/racket? It would be nice to know what y’all are working on and where its going.

I don’t think there is currently a clean, consolidated public roadmap

you might be able to infer one from various sources… but having an explicit public roadmap would be nice

(me personally, I just finished internal improvements so TR is more performant and less bloated time/space wise, and I’m starting to finally add in the refinement types extension I’ve already prototyped)

refinement types are super useful.

my goal is to get them added before the summer (when I’ll likely be off at an internship)

(and there’s no longer any TR “to do’s” before adding refinements in my hopper)

@stchang: Thanks for the PRs. Let me know when I should merge.

@lexi.lambda i just merged

though it looks like you could have merged at any time, since my changes are compatible with the old version

@lexi.lambda a lot of the most recent changes were from your feedback so thanks for that

@stchang: I’m glad to hear it :)

we’re using the aws cloudformation dsl for production services now :)

biggest worry currently is package management, which is still imo the biggest barrier to me feeling comfortable with racket in production

specifically, versioning

@mflatt @samth: what is the status of the sandboxing stuff mentioned in this PR? https://github.com/racket/racket/pull/1206 I think it would be important for fixing the package management issues I currently have

@lexi.lambda “tethering” is in place, and that’s intended to make raco sandbox init
easy, but I never tried to build that sandbox layer

See http://docs.racket-lang.org/raco/dirs.html?q=tether#%28def._%28%28lib._setup%2Fdirs..rkt%29._find-addon-tethered-console-bin-dir%29%29 and between those docs and the PR conversation, maybe you’ll be able to infer what I had in mind

@mflatt: I admit, I don’t really understand… if tethering is to avoid having to set PLTADDONDIR
, why do both those functions require (find-system-path 'addon-dir)
? I’m sure I’m misunderstanding their intent.

Maybe that was the wrong place to point to, and the end of http://docs.racket-lang.org/raco/config-file.html is better

The idea is that you create a configuration that chains to your regular installation, but also defines config-tethered-console-bin-dir
and config-tethered-gui-bin-dir
; then run racket -G <new-config-dir> -l- raco setup
to get binaries that have the <new-config-dir>
configuration built in

To use the sandbox, you’d use the executables that have <new-config-dir>
wired in

I see, that makes sense. I think maybe I don’t fully understand how addon-dir itself works… if I install a package into the addon directory, then specify the right incantation in the configuration, will racket
load those packages?

Similarly, if I set the configuration properly, will raco pkg install
install packages into that directory?

Or is that the stuff that still needs to be implemented?

User-scope packages are installed/found within the addon directory

Ok, that makes sense. For that reason, if I wanted to use that feature for sandboxing, then I should really probably avoid installing any packages in installation scope (since packages can’t be installed in both user and installation scope)?

Right; if I understand your goal, then you want a minimal Racket installation to use for creating sandboxes

Yeah, pretty much. This isn’t very important right now, but I’m imagining a future world where the package system supports multiple versions of packages and raco pkg install
does constraint solving.

In that world, sandboxes would be extremely important to avoid dependency hell, since you couldn’t have multiple versions of the same package installed globally, but you would want different projects to use different versions.

A small weirdness here: does this mean I would need to install and recompile DrRacket in every project I want to use it with?

Yes, as long as you want to be able to have different installations of anything DrRacket depends on (otherwise, you could start with a base Racket installation that includes DrRacket, instead of a minimal Racket installation)

Right, yeah. That might be ok, but DrRacket depends on a lot (especially since racket-doc depends on a lot).