Skip to content
Permalink
Browse files

[trusted-types] Add $Trusted/$Private type annotations

Summary:
Adding preliminary syntax for trusted type annotations, `$Trusted<T>` and `$Private<T>`. Right now these types are no-ops and are equivalent to `T`, but trusted typing will use `$Trusted<T>` to mean the same thing as the more compact syntax for trusted types (tentatively `*T`): it is a non-supertype of `any` while behaving like `T` otherwise. The `$Private<T>` annotation is something that programmers shouldn't have to worry about (because it will be inferred where needed); essentially it is a non-*sub*type of `any` in the same way that trusted types are non-supertypes of `any`. The `$Private` syntax will exist for testing purposes and maybe niche use cases.

* `$Trusted<any>` and `$Private<any>` are invalid types, mainly because they don't really make sense semantically.
* Only `DefT`s can be made trusted or private, at least for now. This does mean that we can't write the following:
```type T = number
var x: $Trusted<T> = 42;
```
* I think this is a restriction that should eventually be able to be lifted, but it might not be trivial to implement trusted non-`DefT`s in the type system--hence keeping this restriction right now.

Reviewed By: dsainati1

Differential Revision: D13867988

fbshipit-source-id: 47e994e9f20b9b80cb9fb2aab434bab7d6575437
  • Loading branch information...
mvitousek authored and facebook-github-bot committed Feb 5, 2019
1 parent 306096a commit fa0a8ef899925ed2b0939cb03678eceec821f5d0
@@ -2665,6 +2665,10 @@ let dump_flow_error =
spf "EPredAnnot (%s)" (string_of_aloc loc)
| ERefineAnnot loc ->
spf "ERefineAnnot (%s)" (string_of_aloc loc)
| ETrustedAnnot loc ->
spf "ETrustedAnnot (%s)" (string_of_aloc loc)
| EPrivateAnnot loc ->
spf "EPrivateAnnot (%s)" (string_of_aloc loc)
| EUnexpectedTypeof loc ->
spf "EUnexpectedTypeof (%s)" (string_of_aloc loc)
| EFunPredCustom ((reason1, reason2), msg) ->
@@ -106,6 +106,8 @@ type error_message =
| EUnsupportedKeyInObjectType of ALoc.t
| EPredAnnot of ALoc.t
| ERefineAnnot of ALoc.t
| ETrustedAnnot of ALoc.t
| EPrivateAnnot of ALoc.t
| EUnexpectedTypeof of ALoc.t
| EFunPredCustom of (reason * reason) * string
| EIncompatibleWithShape of reason * reason * use_op
@@ -352,6 +354,8 @@ let util_use_op_of_msg nope util = function
| EUnsupportedKeyInObjectType (_)
| EPredAnnot (_)
| ERefineAnnot (_)
| ETrustedAnnot (_)
| EPrivateAnnot (_)
| EUnexpectedTypeof (_)
| EFunPredCustom (_, _)
| EInternal (_, _)
@@ -1580,6 +1584,16 @@ let rec error_of_msg ~trace_reasons ~source_file : error_message -> ALoc.t Error
text "type argument must be a number literal.";
]

| ETrustedAnnot loc ->
mk_error ~trace_infos loc [
text "Not a valid type to mark as "; code "$Trusted"; text ".";
]

| EPrivateAnnot loc ->
mk_error ~trace_infos loc [
text "Not a valid type to mark as "; code "$Private"; text ".";
]

| EUnexpectedTypeof loc ->
mk_error ~trace_infos ~kind:InferWarning loc
[code "typeof"; text " can only be used to get the type of variables."]
@@ -21,3 +21,9 @@ type trust = unit
(* Currently, bogus_trust is the only way to create trust, since actual trust
tracking is unimplemented. *)
let bogus_trust () = ()


(* Given a trust datum, add (if not already present) the requirement that it
be trusted or private. *)
let make_trusted () = ()
let make_private () = ()
@@ -8,3 +8,6 @@
type trust

val bogus_trust: unit -> trust

val make_trusted: trust -> trust
val make_private: trust -> trust
@@ -816,7 +816,28 @@ let rec convert cx tparams_map = Ast.Type.(function
| _ ->
error_type cx loc (FlowError.ERefineAnnot loc) t_ast
)

| "$Trusted" ->
check_type_arg_arity cx loc t_ast targs 1 (fun () ->
match convert_type_params () with
| [DefT (_, _, AnyT _)], _ ->
error_type cx loc (FlowError.ETrustedAnnot loc) t_ast
| [DefT (rs, trust, ty)], targs ->
reconstruct_ast
(DefT (rs, make_trusted trust, ty))
targs
| _ ->
error_type cx loc (FlowError.ETrustedAnnot loc) t_ast
)
| "$Private" ->
check_type_arg_arity cx loc t_ast targs 1 (fun () ->
match convert_type_params () with
| [DefT (rs, trust, ty)], targs ->
reconstruct_ast
(DefT (rs, make_private trust, ty))
targs
| _ ->
error_type cx loc (FlowError.EPrivateAnnot loc) t_ast
)
(* other applications with id as head expr *)
| _ ->
let reason = mk_reason (RType name) loc in
No changes.
@@ -0,0 +1,8 @@
//@flow

declare function f(x: $Trusted<number>): $Private<number>;
declare var x: $Trusted<$Private<($Private<number>)=>$Trusted<number>>>;
declare var y: $Trusted<any>;
type T = $Trusted<number>;
declare var z: $Trusted<T>
(32: $Trusted<number>)
@@ -0,0 +1,18 @@
Error --------------------------------------------------------------------------------------------------- syntax.js:5:16

Not a valid type to mark as `$Trusted`.

5| declare var y: $Trusted<any>;
^^^^^^^^^^^^^


Error --------------------------------------------------------------------------------------------------- syntax.js:7:16

Not a valid type to mark as `$Trusted`.

7| declare var z: $Trusted<T>
^^^^^^^^^^^



Found 2 errors

0 comments on commit fa0a8ef

Please sign in to comment.
You can’t perform that action at this time.