Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing InvalidOverrideNumberOfErrors #647

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 7 additions & 2 deletions source/analysis/analysisError.ml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ and invalid_override_kind =
| StaticOverride
| NothingOverridden
| IllegalOverrideDecorator
| MissingOverrideDecorator

and invalid_assignment_kind =
| FinalAttribute of Reference.t
Expand Down Expand Up @@ -1588,6 +1589,8 @@ let rec messages ~concise ~signature location kind =
( "",
"is illegally decorated with @override: @override may only be applied to methods, \
but this element is not a method" )
| MissingOverrideDecorator ->
"", "is overriding a parent but is not decorated with @override. Please decorate"
in
match decorator with
| Final
Expand All @@ -1604,7 +1607,8 @@ let rec messages ~concise ~signature location kind =
pp_identifier
parent;
]
| IllegalOverrideDecorator ->
| IllegalOverrideDecorator
| MissingOverrideDecorator ->
[Format.asprintf "%s`%a` %s." preamble pp_reference define_name message])
| InvalidAssignment kind -> (
match kind with
Expand Down Expand Up @@ -2820,7 +2824,8 @@ let less_or_equal ~resolution left right =
| StaticSuper, StaticSuper
| StaticOverride, StaticOverride
| NothingOverridden, NothingOverridden
| IllegalOverrideDecorator, IllegalOverrideDecorator ->
| IllegalOverrideDecorator, IllegalOverrideDecorator
| MissingOverrideDecorator, MissingOverrideDecorator ->
Identifier.equal_sanitized left_parent right_parent
| _, _ -> false)
| InvalidAssignment left, InvalidAssignment right -> (
Expand Down
1 change: 1 addition & 0 deletions source/analysis/analysisError.mli
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ and invalid_override_kind =
| StaticOverride
| NothingOverridden
| IllegalOverrideDecorator
| MissingOverrideDecorator

and invalid_assignment_kind =
| FinalAttribute of Reference.t
Expand Down
4 changes: 4 additions & 0 deletions source/analysis/postprocessing.ml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ let run_on_qualifier environment ~dependency qualifier =

let run ~scheduler ~environment sources =
let timer = Timer.start () in
let () = Log.log ~section:`Progress "Beginning of post process" in
let number_of_sources = List.length sources in
Log.log ~section:`Progress "Postprocessing %d sources..." number_of_sources;
let map _ modules =
Expand All @@ -239,4 +240,7 @@ let run ~scheduler ~environment sources =
()
in
Statistics.performance ~name:"check_Postprocessing" ~phase_name:"Postprocessing" ~timer ();
let () =
Log.log ~section:`Progress "Printing the number of errors printed: %d" (List.length errors)
in
errors
233 changes: 13 additions & 220 deletions source/analysis/typeCheck.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4661,10 +4661,6 @@ module State (Context : Context) = struct
resolve_expression ~resolution:resolution_with_locals expression |> Annotation.annotation


and resolve_reference_type ~resolution reference =
from_reference ~location:Location.any reference |> resolve_expression_type ~resolution


and emit_invalid_enumeration_literal_errors ~resolution ~location ~errors annotation =
let invalid_enumeration_literals =
let is_invalid_enumeration_member = function
Expand Down Expand Up @@ -5815,7 +5811,7 @@ module State (Context : Context) = struct
init_subclass_errors @ errors
| None -> errors
in
let check_behavioral_subtyping resolution errors =
let check_behavioral_subtyping errors =
let is_allowlisted_dunder_method define =
let allowlist =
String.Set.of_list
Expand All @@ -5841,227 +5837,24 @@ module State (Context : Context) = struct
then
errors
else
let open Annotated in
begin
match define with
| { Ast.Statement.Define.signature = { parent = Some parent; _ }; _ } -> (
| { Ast.Statement.Define.signature = { parent = Some parent; _ }; _ } ->
GlobalResolution.overrides
(Reference.show parent)
~resolution:global_resolution
~name:(StatementDefine.unqualified_name define)
>>| fun overridden_attribute ->
let errors =
match AnnotatedAttribute.visibility overridden_attribute with
| ReadOnly (Refinable { overridable = false }) ->
let parent = overridden_attribute |> Attribute.parent in
emit_error
~errors
~location
~kind:(Error.InvalidOverride { parent; decorator = Final })
| _ -> errors
in
let errors =
if
not
(Bool.equal
(Attribute.static overridden_attribute)
(StatementDefine.is_static_method define))
then
let parent = overridden_attribute |> Attribute.parent in
let decorator =
if Attribute.static overridden_attribute then
Error.StaticSuper
else
Error.StaticOverride
in
emit_error ~errors ~location ~kind:(Error.InvalidOverride { parent; decorator })
else
errors
in
(* Check strengthening of postcondition. *)
let overridden_base_attribute_annotation =
Annotation.annotation (Attribute.annotation overridden_attribute)
in
match overridden_base_attribute_annotation with
| Type.Parametric
{
name = "BoundMethod";
parameters = [Single (Type.Callable { implementation; _ }); _];
}
| Type.Callable { Type.Callable.implementation; _ } ->
let original_implementation =
resolve_reference_type ~resolution name
|> function
| Type.Callable { Type.Callable.implementation = original_implementation; _ }
| Type.Parametric
{
parameters =
[
Single
(Type.Callable { implementation = original_implementation; _ });
_;
];
_;
} ->
original_implementation
| annotation -> raise (ClassHierarchy.Untracked (Type.show annotation))
in
let errors =
let expected = Type.Callable.Overload.return_annotation implementation in
let actual =
Type.Callable.Overload.return_annotation original_implementation
in
if
Type.Variable.all_variables_are_resolved expected
&& not
(GlobalResolution.less_or_equal
global_resolution
~left:actual
~right:expected)
then
emit_error
~errors
~location
~kind:
(Error.InconsistentOverride
{
overridden_method = StatementDefine.unqualified_name define;
parent = Attribute.parent overridden_attribute |> Reference.create;
override_kind = Method;
override =
Error.WeakenedPostcondition
(Error.create_mismatch
~resolution:global_resolution
~actual
~expected
~covariant:false);
})
else
errors
in
(* Check weakening of precondition. *)
let overriding_parameters =
let parameter_annotations
{ StatementDefine.signature = { parameters; _ }; _ }
~resolution
=
let element { Node.value = { Parameter.name; annotation; _ }; _ } =
let annotation =
annotation
>>| (fun annotation ->
GlobalResolution.parse_annotation resolution annotation)
|> Option.value ~default:Type.Top
in
name, annotation
in
List.map parameters ~f:element
in
parameter_annotations define ~resolution:global_resolution
|> List.map ~f:(fun (name, annotation) ->
{ Type.Callable.Parameter.name; annotation; default = false })
|> Type.Callable.Parameter.create
in
let validate_match ~errors ~index ~overridden_parameter ~expected = function
| Some actual -> (
let is_compatible =
let expected = Type.Variable.mark_all_variables_as_bound expected in
GlobalResolution.constraints_solution_exists
global_resolution
~left:expected
~right:actual
in
let is_self_or_class_parameter =
index = 0 && not (StatementDefine.is_static_method define)
in
try
if
(not (Type.is_top expected))
&& (not is_compatible)
&& not is_self_or_class_parameter
then
emit_error
~errors
~location
~kind:
(Error.InconsistentOverride
{
overridden_method = StatementDefine.unqualified_name define;
parent =
Attribute.parent overridden_attribute |> Reference.create;
override_kind = Method;
override =
Error.StrengthenedPrecondition
(Error.Found
(Error.create_mismatch
~resolution:global_resolution
~actual
~expected
~covariant:false));
})
else
errors
with
| ClassHierarchy.Untracked _ ->
(* TODO(T27409168): Error here. *)
errors)
| None ->
let has_keyword_and_anonymous_starred_parameters =
List.exists overriding_parameters ~f:(function
| Keywords _ -> true
| _ -> false)
&& List.exists overriding_parameters ~f:(function
| Variable _ -> true
| _ -> false)
in
if has_keyword_and_anonymous_starred_parameters then
errors
else
emit_error
~errors
~location
~kind:
(Error.InconsistentOverride
{
overridden_method = StatementDefine.unqualified_name define;
override_kind = Method;
parent =
Attribute.parent overridden_attribute |> Reference.create;
override =
Error.StrengthenedPrecondition
(Error.NotFound overridden_parameter);
})
in
let check_parameter index errors = function
| `Both (overridden_parameter, overriding_parameter) -> (
match
( Type.Callable.RecordParameter.annotation overridden_parameter,
Type.Callable.RecordParameter.annotation overriding_parameter )
with
| Some expected, Some actual ->
validate_match
~errors
~index
~overridden_parameter
~expected
(Some actual)
| None, _
| _, None ->
(* TODO(T53997072): There is no reasonable way to compare Variable
(Concatenation _). For now, let's just ignore this. *)
errors)
| `Left overridden_parameter -> (
match Type.Callable.RecordParameter.annotation overridden_parameter with
| Some expected ->
validate_match ~errors ~index ~overridden_parameter ~expected None
| None -> errors)
| `Right _ -> errors
in
let overridden_parameters =
Type.Callable.Overload.parameters implementation |> Option.value ~default:[]
in
Type.Callable.Parameter.zip overridden_parameters overriding_parameters
|> List.foldi ~init:errors ~f:check_parameter
| _ -> errors)
emit_error
~errors
~location
~kind:
(Error.InvalidOverride
{
parent =
"TestingNumberOfOverrides" ^ AnnotatedAttribute.name overridden_attribute;
decorator = MissingOverrideDecorator;
})
| _ -> None
end
|> Option.value ~default:errors
Expand Down Expand Up @@ -6101,7 +5894,7 @@ module State (Context : Context) = struct
|> check_decorators resolution
|> check_base_annotations resolution
|> check_init_subclass_call resolution
|> check_behavioral_subtyping resolution
|> check_behavioral_subtyping
|> check_constructor_return
in
resolution, errors
Expand Down