stc icon indicating copy to clipboard operation
stc copied to clipboard

Overload handling should handle constructor

Open kdy1 opened this issue 2 years ago • 6 comments

Problem

https://github.com/dudykr/stc/blob/269f6c07676f728e667ca5fb4c80d7f17f66a98d/crates/stc_ts_type_checker/tests/conformance/types/objectTypeLiteral/constructSignatures/constructSignaturesWithOverloads2.ts#L15-L24

should pass, but stc fails to verify it.

Currently we only check overloads for methods, so overload selection for new fails

Solution

We should handle constructor from extract https://github.com/dudykr/stc/blob/805667830752f229f1674d034e1e9b0eb3fcb076/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs#L1215-L1647

kdy1 avatar Nov 05 '22 19:11 kdy1

Hi, I would like to take this!

yamgent avatar Nov 06 '22 00:11 yamgent

Thanks!

kdy1 avatar Nov 06 '22 00:11 kdy1

Updated the issue to reflect the real solution

kdy1 avatar Nov 06 '22 06:11 kdy1

EDIT: GitHub is currently showing this post in the wrong place, this should be after "Updated the issue..." post. Writing this here in case someone is confused...


Ok, so I tried the new real solution by doing something like this:

diff --git a/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs b/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs
index d655cf6e..523e5722 100644
--- a/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs
+++ b/crates/stc_ts_file_analyzer/src/analyzer/expr/call_new.rs
@@ -1515,20 +1515,19 @@ impl Analyzer<'_, '_> {
                 )
             }
 
-            // Type::Constructor(ty::Constructor {
-            //     ref params,
-            //     ref type_params,
-            //     ref ret_ty,
-            //     ..
-            // }) if kind == ExtractKind::New => self.try_instantiate_simple(
-            //     span,
-            //     ty.span(),
-            //     &ret_ty,
-            //     params,
-            //     type_params.as_ref(),
-            //     args,
-            //     type_args,
-            // ),
+            Type::Constructor(c) if kind == ExtractKind::New => self.get_return_type(
+                span,
+                kind,
+                expr,
+                c.type_params.as_ref().map(|v| &*v.params),
+                &c.params,
+                *c.type_ann.clone(),
+                type_args,
+                args,
+                arg_types,
+                spread_arg_types,
+                type_ann,
+            ),
             Type::Union(..) => {
                 self.get_best_return_type(span, expr, ty.clone(), kind, type_args, args, arg_types, spread_arg_types, type_ann)
             }

However, I don't see any change in the behaviour. In fact, I don't think it was the path taken by the code anyway. ty is Type::Union, so it goes to get_best_return_type() -> extract_callee_candidates(), which does add all 3 CallCandidates of C2.

...am I missing something really obvious here?

image

yamgent avatar Nov 06 '22 09:11 yamgent

The type should not be Type::Constructor. It will be ClassDef with multiple ClassMember::Consturctors. But in this case, because of the declaration merging of TypeScript, the type will be stored in an intersection or a union (I don't remember exactly)

By stored in, I mean class C2 and namespace (module C2) will exist in the same vector, and you may need to adjust logic to exclude namespace (module keyword, again) from the union or intersection

kdy1 avatar Nov 06 '22 09:11 kdy1

Oh it's a union. namespace is rendered as any in type dump

kdy1 avatar Nov 06 '22 09:11 kdy1

@kdy1 I think this issue can be closed since it is fixed by #222?

yamgent avatar Nov 15 '22 14:11 yamgent

You are right, thanks!

kdy1 avatar Nov 15 '22 14:11 kdy1