diff --git a/src/services/autocomplete/autocomplete_js.ml b/src/services/autocomplete/autocomplete_js.ml index 36c0c07ce47..73443eb6ee6 100644 --- a/src/services/autocomplete/autocomplete_js.ml +++ b/src/services/autocomplete/autocomplete_js.ml @@ -162,7 +162,7 @@ module Inference = struct let type_of_match_member_pattern cx loc mem = Match_pattern.type_of_member_pattern cx - ~on_identifier:(Statement.identifier ~encl_ctx:Type.NoContext) + ~on_identifier:Statement.identifier ~on_expression:Statement.expression (loc, mem) end diff --git a/src/typing/match_pattern.ml b/src/typing/match_pattern.ml index a26dd54c730..6f2f56ecbfb 100644 --- a/src/typing/match_pattern.ml +++ b/src/typing/match_pattern.ml @@ -95,7 +95,7 @@ let rec member cx ~on_identifier ~on_expression mem = match base with | BaseIdentifier (loc, id) -> let exp = (loc, Ast.Expression.Identifier (loc, id)) in - (exp, BaseIdentifier ((loc, on_identifier cx id loc), id)) + (exp, BaseIdentifier ((loc, on_identifier ~encl_ctx:Type.OtherTest cx id loc), id)) | BaseMember mem -> let (exp, mem) = member cx ~on_identifier ~on_expression mem in (exp, BaseMember mem) @@ -179,7 +179,7 @@ let rec pattern_ cx ~on_identifier ~on_expression ~on_binding ~in_or_pattern acc in AsPattern { AsPattern.pattern = p; target; comments } | IdentifierPattern (loc, x) -> - let t = on_identifier cx x loc in + let t = on_identifier ~encl_ctx:Type.OtherTest cx x loc in IdentifierPattern ((loc, t), x) | BindingPattern x -> BindingPattern (binding_pattern cx ~on_binding ~in_or_pattern ~loc acc x) | WildcardPattern x -> WildcardPattern x diff --git a/src/typing/match_pattern.mli b/src/typing/match_pattern.mli index 8c711fb80df..e2ed3f25a37 100644 --- a/src/typing/match_pattern.mli +++ b/src/typing/match_pattern.mli @@ -9,7 +9,8 @@ module Ast = Flow_ast val pattern : Context.t -> - on_identifier:(Context.t -> ALoc.t Ast.Identifier.t' -> ALoc.t -> Type.t) -> + on_identifier: + (encl_ctx:Type.enclosing_context -> Context.t -> ALoc.t Ast.Identifier.t' -> ALoc.t -> Type.t) -> on_expression: (Context.t -> (ALoc.t, ALoc.t) Ast.Expression.t -> (ALoc.t, ALoc.t * Type.t) Ast.Expression.t) -> on_binding: @@ -20,7 +21,8 @@ val pattern : val type_of_member_pattern : Context.t -> - on_identifier:(Context.t -> ALoc.t Ast.Identifier.t' -> ALoc.t -> Type.t) -> + on_identifier: + (encl_ctx:Type.enclosing_context -> Context.t -> ALoc.t Ast.Identifier.t' -> ALoc.t -> Type.t) -> on_expression: (Context.t -> (ALoc.t, ALoc.t) Ast.Expression.t -> (ALoc.t, ALoc.t * Type.t) Ast.Expression.t) -> (ALoc.t, ALoc.t) Ast.MatchPattern.MemberPattern.t -> diff --git a/src/typing/statement.ml b/src/typing/statement.ml index 2cb1285f345..3f71083d0f2 100644 --- a/src/typing/statement.ml +++ b/src/typing/statement.ml @@ -1221,7 +1221,8 @@ module Make Flow_ast.Expression.Identifier (Flow_ast_utils.match_root_ident case_loc) ) pattern - ~on_identifier:(fun cx -> identifier cx empty_syntactic_flags) + ~on_identifier:(fun ~encl_ctx cx -> + identifier cx { empty_syntactic_flags with Primitive_literal.encl_ctx }) ~on_expression:expression ~on_binding:(fun ~use_op ~name_loc ~kind name t -> init_var kind cx ~use_op t name_loc; @@ -2493,7 +2494,7 @@ module Make shorthand; } ) -> - let (((_, kt), _) as k') = expression cx k in + let (((_, kt), _) as k') = expression cx ~encl_ctx:IndexContext k in let (((_, vt), _) as v') = expression cx ~as_const v in let computed = mk_computed k kt vt in ( ObjectExpressionAcc.add_computed cx computed acc, @@ -2516,7 +2517,7 @@ module Make value = (fn_loc, fn); } ) -> - let (((_, kt), _) as k') = expression cx k in + let (((_, kt), _) as k') = expression cx ~encl_ctx:IndexContext k in let ((_, vt), v') = expression cx (fn_loc, Ast.Expression.Function fn) in let fn = match v' with @@ -2946,7 +2947,8 @@ module Make cx (case_loc, Identifier (Flow_ast_utils.match_root_ident case_loc)) pattern - ~on_identifier:(fun cx -> identifier cx empty_syntactic_flags) + ~on_identifier:(fun ~encl_ctx cx -> + identifier cx { empty_syntactic_flags with Primitive_literal.encl_ctx }) ~on_expression:expression ~on_binding:(fun ~use_op ~name_loc ~kind name t -> init_var kind cx ~use_op t name_loc; @@ -4539,7 +4541,7 @@ module Make ) in let eval_index () = - let (((_, tind), _) as index) = expression cx index in + let (((_, tind), _) as index) = expression ~encl_ctx:IndexContext cx index in (tind, index) in let conf = @@ -4836,7 +4838,7 @@ module Make ) in let eval_args_and_expr () = - let (((_, elem_t), _) as expr) = expression cx expr in + let (((_, elem_t), _) as expr) = expression ~encl_ctx:IndexContext cx expr in let (argts, arguments_ast) = arg_list cx arguments in ((argts, elem_t), (arguments_ast, expr)) in @@ -4973,7 +4975,8 @@ module Make | SwitchTest _ | OtherTest -> BoolModuleT.at loc - | NoContext -> + | NoContext + | IndexContext -> let reason = mk_reason (RUnaryOperator ("not", desc_of_t arg)) loc in Operators.unary_not cx reason arg in @@ -5074,7 +5077,9 @@ module Make and visit_eq_test cx ~encl_ctx loc left right = let check ~encl_ctx = expression cx ~encl_ctx in match encl_ctx with - | NoContext -> check ~encl_ctx:NoContext + | NoContext + | IndexContext -> + check ~encl_ctx | SwitchTest _ | OtherTest -> let reconstruct_ast = check ~encl_ctx:OtherTest in @@ -5142,7 +5147,9 @@ module Make let (((_, t2), _) as right) = reconstruct_ast right in begin match encl_ctx with - | NoContext -> () + | NoContext + | IndexContext -> + () | SwitchTest _ | OtherTest -> matching_prop_check cx left right; @@ -5452,7 +5459,7 @@ module Make let reason = mk_reason (RPropertyAssignment None) lhs_loc in let lhs_reason = mk_expression_reason _object in let (o, _object) = typecheck_object _object in - let (((_, i), _) as index) = expression cx index in + let (((_, i), _) as index) = expression ~encl_ctx:IndexContext cx index in let use_op = make_op ~lhs:reason ~prop:(mk_reason (desc_of_reason lhs_prop_reason) iloc) in let upper = maybe_chain lhs_reason (SetElemT (use_op, reason, i, mode, t, None)) in Flow.flow cx (o, upper); @@ -6471,7 +6478,8 @@ module Make | SwitchTest _ | OtherTest -> OptTestPropT (use_op, reason, id, mk_named_prop ~reason:prop_reason prop_name, hint) - | NoContext -> + | NoContext + | IndexContext -> OptGetPropT { use_op; diff --git a/src/typing/type.ml b/src/typing/type.ml index ff60cf78925..26b270b5e03 100644 --- a/src/typing/type.ml +++ b/src/typing/type.ml @@ -897,6 +897,8 @@ module rec TypeTerm : sig } (* `if(C){}`, `while(C){}`, `C?e1:e2`, `invariant(C)`, ... *) | OtherTest + (* `o[C]`, `o[C]=e`, `{[C]:e}`, `o[C]()` *) + | IndexContext (* Bindings created from destructuring annotations should themselves act like * annotations. That is, `var {p}: {p: string}; p = 0` should be an error, diff --git a/src/typing/type_operation_utils.ml b/src/typing/type_operation_utils.ml index 4424860692f..e421f2a0c0e 100644 --- a/src/typing/type_operation_utils.ml +++ b/src/typing/type_operation_utils.ml @@ -256,6 +256,7 @@ module Operators = struct explanation = None; } | NoContext + | IndexContext | OtherTest -> let reasons = FlowError.ordered_reasons (reason_of_t l, reason_of_t r) in Error_message.EComparison reasons) @@ -282,6 +283,7 @@ module Operators = struct match encl_ctx with | SwitchTest _ -> Some (Lazy.force comparison_error) | NoContext + | IndexContext | OtherTest -> None end