Skip to content

Commit

Permalink
Fix ParamSpec bug in typecheck
Browse files Browse the repository at this point in the history
Summary:
We create a new version of parse_annotation that accepts scoped type variables.

We can collect type variables from resolution generally speaking and then turn them into a scope.

What concerns me is that there are still places in the typechecker that still don't do that. I think overtime I need to observe user reports and put more unittests after variance.

So far, I've fixed the bugs that

Reviewed By: stroxler

Differential Revision: D63868697

fbshipit-source-id: 001afe8f8aea56bed980c90033f3b51c1a80cb37
  • Loading branch information
migeed-z authored and facebook-github-bot committed Oct 4, 2024
1 parent a365097 commit 24f9c51
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 3 deletions.
10 changes: 10 additions & 0 deletions source/analysis/globalResolution.ml
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,16 @@ let parse_annotation ({ dependency; _ } as resolution) =
~scoped_type_variables:None


let parse_annotation_with_scoped_typed_variables
({ dependency; _ } as resolution)
~scoped_type_variables
=
AttributeResolution.ReadOnly.parse_annotation
?dependency
(attribute_resolution resolution)
~scoped_type_variables


let global ({ dependency; _ } as resolution) =
AttributeResolution.ReadOnly.global (attribute_resolution resolution) ?dependency

Expand Down
7 changes: 7 additions & 0 deletions source/analysis/globalResolution.mli
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ val parse_annotation
Expression.t ->
Type.t

val parse_annotation_with_scoped_typed_variables
: t ->
scoped_type_variables:Type.Variable.t Identifier.Map.t option ->
?validation:AttributeResolution.type_validation_policy ->
Expression.expression Node.t ->
Type.t

val global : t -> Reference.t -> AttributeResolution.Global.t option

val get_typed_dictionary : t -> Type.t -> Type.TypedDictionary.t option
Expand Down
2 changes: 1 addition & 1 deletion source/analysis/test/integration/typeVariableTest.ml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ let test_type_variable_scoping =
def decorator3[**L, M](x: Callable[L, M]) -> int:
...
|}
["Invalid type [31]: Expression `typing.Callable[(L, M)]` is not a valid type."];
[];
(* PEP695 generic methods from non-generic classes *)
labeled_test_case __FUNCTION__ __LINE__
@@ assert_type_errors
Expand Down
32 changes: 30 additions & 2 deletions source/analysis/typeCheck.ml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,26 @@ module type Signature = sig
include Fixpoint.State with type t := t
end

(* A helper function which converts type parameters to a type variable map *)
let scoped_type_variables_as_map scoped_type_variables_list =
let empty_string_map = Identifier.Map.empty in
let update_map map key value =
match Map.add ~key ~data:value map with
| `Ok new_map -> new_map
| `Duplicate -> map
in
let named_values = List.map ~f:(fun x -> Type.Variable.name x, x) scoped_type_variables_list in
let create_mapping_from_type_variable_assoc_list =
List.fold_left
~f:(fun map (key, value) -> update_map map key value)
~init:empty_string_map
named_values
in
match named_values with
| [] -> None
| _ -> Some create_mapping_from_type_variable_assoc_list


let error_and_location_from_typed_dictionary_mismatch
{ Node.value = mismatch; location = define_location }
=
Expand Down Expand Up @@ -636,8 +656,13 @@ module State (Context : Context) = struct
else
errors, Type.Top
in
let type_variables_in_scope = Resolution.all_type_variables_in_scope resolution in
let scoped_type_variables = scoped_type_variables_as_map type_variables_in_scope in
let annotation =
GlobalResolution.parse_annotation ~validation:NoValidation global_resolution expression
(GlobalResolution.parse_annotation_with_scoped_typed_variables ~scoped_type_variables)
~validation:NoValidation
global_resolution
expression
in
let errors =
match annotation with
Expand Down Expand Up @@ -6551,6 +6576,7 @@ module State (Context : Context) = struct
let global_resolution = Resolution.global_resolution resolution in
(* collect type parameters for functions *)
let type_params, _ = get_type_params_as_variables type_params global_resolution in
let scoped_type_variables = scoped_type_variables_as_map type_params in
(* Add them to the resolution *)
let resolution =
type_params
Expand Down Expand Up @@ -6715,7 +6741,9 @@ module State (Context : Context) = struct
if String.is_prefix ~prefix:"**" name then
match
annotation
>>| GlobalResolution.parse_annotation global_resolution
>>| GlobalResolution.parse_annotation_with_scoped_typed_variables
global_resolution
~scoped_type_variables
>>| Type.unpack_value
|> Option.value ~default:None
>>| GlobalResolution.get_typed_dictionary global_resolution
Expand Down

0 comments on commit 24f9c51

Please sign in to comment.