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

Exclude MissingFields if RHS have an index signature #741

Closed
kdy1 opened this issue Feb 22, 2023 · 6 comments
Closed

Exclude MissingFields if RHS have an index signature #741

kdy1 opened this issue Feb 22, 2023 · 6 comments
Assignees

Comments

@kdy1
Copy link
Member

kdy1 commented Feb 22, 2023

Related test case:

stc fails with


  x context:
  | lhs = instanceof  Obj;
  | rhs = StringTo#1;
  | Member as {
  |     [x: string]: any;
  | };
  | lhs (normalized) = Obj#1;
  | Member as {
  |     hello: string;
  |     world: number;
  | };
  | rhs (normalized) = StringTo#1;
  | Member as {
  |     [x: string]: any;
  | }; (at crates/stc_ts_file_analyzer/src/analyzer/assign/mod.rs:588:73)
  | context: tried to assign a type to an interface (at crates/stc_ts_file_analyzer/src/analyzer/assign/mod.rs:2277:18)
  | context: tried to assign to type elements by converting rhs to a type literal (at crates/stc_ts_file_analyzer/src/analyzer/assign/type_el.rs:228:30)
  | MissingFields {
  |     span: Span {
  |         lo: BytePos(
  |             2092,
  |         ),
  |         hi: BytePos(
  |             2099,
  |         ),
  |         ctxt: #0,
  |     },
  |     fields: [
  |         hello: string,
  |         world: number,
  |     ],
  | }
    ,-[$DIR/tests/conformance/types/members/objectTypeWithStringAndNumberIndexSignatureToAny.ts:91:1]
 91 |
 92 |     someObj = sToAny;
    :     ^^^^^^^
 93 |     someObj = nToNumber;
    `----

but it should success because the RHS contains an index signature

@awareness481
Copy link
Contributor

What's causing me issues here is that it seems like the type gets converted to type Interface by this line

ty = ty.fold_with(&mut TypeFactsHandler { analyzer: self, facts });

dbg!("before fold white: ", &ty);
ty = ty.fold_with(&mut TypeFactsHandler { analyzer: self, facts });
dbg!("after fold with: ", &ty);
[crates/stc_ts_file_analyzer/src/ty/type_facts.rs:72] "before fold with: " = "before fold with: "
[crates/stc_ts_file_analyzer/src/ty/type_facts.rs:72] &ty = Instance { span: Span { lo: BytePos(1229), hi: BytePos(1242), ctxt: #0 }, ty: StringTo<any>, metadata: InstanceMetadata { common: CommonTypeMetadata { implicit: false, infected_by_this_in_object_literal: false, prevent_converting_to_children: false, contains_infer_type: false, prevent_complex_simplification: false, resolved_from_var: false, prevent_generalization: false, destructure_key: DestructureId(0) } }, tracker: Tracker { _priv: () } }

[crates/stc_ts_file_analyzer/src/ty/type_facts.rs:74] "after fold with: " = "after fold with: "
[crates/stc_ts_file_analyzer/src/ty/type_facts.rs:74] &ty = Instance { span: Span { lo: BytePos(1229), hi: BytePos(1242), ctxt: #0 }, ty: Interface { span: Span { lo: BytePos(1229), hi: BytePos(1242), ctxt: #0 }, name: StringTo#2, type_params: Some(<T#3>), extends: [], body: [IndexSignature { span: Span { lo: BytePos(27), hi: BytePos(42), ctxt: #0 }, params: [(string)], type_ann: Some(any), readonly: false, is_static: false }], metadata: InterfaceMetadata { common: CommonTypeMetadata { implicit: false, infected_by_this_in_object_literal: false, prevent_converting_to_children: false, contains_infer_type: false, prevent_complex_simplification: false, resolved_from_var: false, prevent_generalization: false, destructure_key: DestructureId(0) } }, tracker: Tracker { _priv: () } }, metadata: InstanceMetadata { common: CommonTypeMetadata { implicit: false, infected_by_this_in_object_literal: false, prevent_converting_to_children: false, contains_infer_type: false, prevent_complex_simplification: false, resolved_from_var: false, prevent_generalization: false, destructure_key: DestructureId(0) } }, tracker: Tracker { _priv: () } }

Is this intended?

The ts code im using is this: (not representing the test code but im just using it to debug)

interface StringTo<T> {
  [x: string]: T;
}

interface NumberTo<T> {
  [x: number]: T;
}

interface StringAndNumberTo<T> extends StringTo<T>, NumberTo<T> {}

interface Obj {
  hello: string;
  world: number;
}

type NumberToNumber = NumberTo<number>;

interface StringToAnyNumberToNumber extends StringTo<any>, NumberToNumber {}

function f3(
  sToAny: StringTo<any>,
  nToNumber: NumberToNumber,
  strToAnyNumToNum: StringToAnyNumberToNumber,
  someObj: Obj
) {
  someObj = sToAny;
}

@kdy1
Copy link
Member Author

kdy1 commented Feb 25, 2023

I think it's a bug of the TypeFactHandler, but not sure how it did happen

@kdy1
Copy link
Member Author

kdy1 commented Feb 25, 2023

I came back to my macbook, and checked the source code of TypeFactsHandler, but not sure why it creates Interface.
The only line mention Interface is

Type::Interface(..) | Type::TypeLit(..) | Type::Class(..) => return false,
but it seems innocent

@kdy1 kdy1 added this to the v0.0.1: Correctness milestone Feb 25, 2023
@awareness481
Copy link
Contributor

If it's any help I've deduced that this line is directly responsible:

ty = ty.fold_children_with(self);

You can try putting return ty; before it and you'll see that the type won't get converted to Interface but if you do

        ty = ty.fold_children_with(self);
        return ty;

you will get Interface back.

@kdy1
Copy link
Member Author

kdy1 commented Feb 26, 2023

I'll try resolving this one

@kdy1
Copy link
Member Author

kdy1 commented Mar 3, 2023

Closing as it's now normalized.
Tracking issue for reverting normalization: #768

@kdy1 kdy1 closed this as completed Mar 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants