Skip to content

Commit

Permalink
Add parameter inference for passing as argument, getting a property f…
Browse files Browse the repository at this point in the history
…rom and calling
  • Loading branch information
kaleidawave committed Aug 26, 2024
1 parent e69e2c5 commit d4142fe
Show file tree
Hide file tree
Showing 19 changed files with 383 additions and 250 deletions.
4 changes: 2 additions & 2 deletions checker/specification/specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -4599,10 +4599,10 @@ proxy1 satisfies { c: "d" };
```ts
function makeObservable(obj, cb: (kind: string, prop: string, value: any) => void) {
return new Proxy(obj, {
get(on, prop: string, _rec) {
get(on: { [a: string]: any }, prop: string, _rec) {
cb("get", prop, on[prop])
},
set(on, prop: string, _value, _rec) {
set(on: { [a: string]: any }, prop: string, _value, _rec) {
cb("set", prop, on[prop])
},
})
Expand Down
42 changes: 42 additions & 0 deletions checker/specification/staging.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
Currently implementing:

> This file is for work-in-progress and can help separating features that are being implemented to regressions
### Constraint inference

> Aka backwards inference
#### From argument

```ts
function cos(a) {
return Math.cos(a)
}

cos satisfies (a: number) => number;
cos(2);
cos("hi")
```

- Argument of type "hi" is not assignable to parameter of type number

#### Property access

```ts
function printName(a) {
return a.name
}

printName satisfies string;
```

- Expected string, found (a: { name: any }) => any

#### Function call

```ts
function printName(a) {
return a(1, 2)
}

printName satisfies string;
```

- Expected string, found (a: (a: 1, b: 2) => any) => any
1 change: 1 addition & 0 deletions checker/src/context/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,7 @@ impl<'a> Environment<'a> {
others: SubTypingOptions::default(),
// TODO don't think there is much case in constraining it here
object_constraints: None,
constraint_inference_requests: Some(Vec::new()),
};

let result =
Expand Down
6 changes: 6 additions & 0 deletions checker/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ pub struct Context<T: ContextType> {
pub possibly_mutated_objects: HashMap<TypeId, TypeId>,
pub possibly_mutated_variables: HashSet<VariableId>,

pub constraint_inference_requests: crate::Map<TypeId, TypeId>,

// pub (crate) info: info,
pub info: LocalInformation,
}
Expand Down Expand Up @@ -565,6 +567,7 @@ impl<T: ContextType> Context<T> {
info: Default::default(),
possibly_mutated_objects: Default::default(),
possibly_mutated_variables: Default::default(),
constraint_inference_requests: Default::default(),
}
}

Expand Down Expand Up @@ -608,6 +611,7 @@ impl<T: ContextType> Context<T> {
mut info,
possibly_mutated_objects,
possibly_mutated_variables,
constraint_inference_requests,
} = new_environment;

// if let Some(self_state) = self.context_type.get_state_mut() {
Expand All @@ -621,6 +625,8 @@ impl<T: ContextType> Context<T> {
self.possibly_mutated_objects.extend(possibly_mutated_objects);
self.possibly_mutated_variables.extend(possibly_mutated_variables);

self.constraint_inference_requests.extend(constraint_inference_requests);

// TODO
// self.tasks_to_run.extend(tasks_to_run.into_iter());

Expand Down
1 change: 1 addition & 0 deletions checker/src/context/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ impl RootContext {
info,
possibly_mutated_objects: Default::default(),
possibly_mutated_variables: Default::default(),
constraint_inference_requests: Default::default(),
}
}

Expand Down
1 change: 1 addition & 0 deletions checker/src/events/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ pub(crate) fn apply_events(
contributions: None,
object_constraints: None,
others: crate::subtyping::SubTypingOptions::default(),
constraint_inference_requests: None,
};

let result = type_is_subtype(
Expand Down
31 changes: 17 additions & 14 deletions checker/src/features/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,7 @@ where
// function.get_name()
// );

// Marked here as mutating things here
let info = function_environment.info;
let variable_names = function_environment.variable_names;

Expand All @@ -849,6 +850,7 @@ where
others: crate::subtyping::SubTypingOptions::default(),
// TODO don't think there is much case in constraining it here
object_constraints: None,
constraint_inference_requests: None,
};

let result = crate::subtyping::type_is_subtype(
Expand Down Expand Up @@ -891,22 +893,23 @@ where
TypeId::UNDEFINED_TYPE
};

// Constraint inference here
{
// let mut _back_requests = HashMap::<(), ()>::new();
// for (on, to) in requests {
// let type_to_alter = checking_data.types.get_type_by_id(on);
// if let Type::RootPolyType(
// PolyNature::Parameter { .. } | PolyNature::FreeVariable { .. },
// ) = type_to_alter
// {
// checking_data.types.set_inferred_constraint(on, to);
// } else if let Type::Constructor(constructor) = type_to_alter {
// crate::utilities::notify!("TODO constructor {:?}", constructor);
// } else {
// crate::utilities::notify!("TODO {:?}", type_to_alter);
// }
// crate::utilities::notify!("TODO temp, setting inferred constraint. No nesting");
// }
for (on, to) in function_environment.constraint_inference_requests {
let type_to_alter = checking_data.types.get_type_by_id(on);
if let Type::RootPolyType(
PolyNature::Parameter { .. } | PolyNature::FreeVariable { .. },
) = type_to_alter
{
checking_data.types.set_inferred_constraint(on, to);
} else if let Type::Constructor(constructor) = type_to_alter {
crate::utilities::notify!("TODO constructor {:?}", constructor);
} else {
crate::utilities::notify!("TODO {:?}", type_to_alter);
}
crate::utilities::notify!("TODO temp, setting inferred constraint. No nesting");
}
}

// TODO this fixes prototypes and properties being lost during printing and subtyping of the return type
Expand Down
1 change: 1 addition & 0 deletions checker/src/features/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ pub mod tsc {
contributions: Default::default(),
others: subtyping::SubTypingOptions { allow_errors: false },
object_constraints: None,
constraint_inference_requests: None,
};

let result = subtyping::type_is_subtype(
Expand Down
2 changes: 2 additions & 0 deletions checker/src/synthesis/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,7 @@ pub(super) fn build_overloaded_function(
contributions: None,
object_constraints: None,
others: Default::default(),
constraint_inference_requests: None,
},
environment,
types,
Expand Down Expand Up @@ -805,6 +806,7 @@ pub(super) fn build_overloaded_function(
contributions: None,
object_constraints: None,
others: Default::default(),
constraint_inference_requests: None,
},
environment,
types,
Expand Down
93 changes: 50 additions & 43 deletions checker/src/synthesis/type_annotations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,60 +175,67 @@ pub fn synthesise_type_annotation<T: crate::ReadFromFS>(
&mut checking_data.types,
)
} else {
synthesise_type_annotation(
let argument = synthesise_type_annotation(
argument_type_annotation,
environment,
checking_data,
)
};

{
use crate::types::subtyping;

let mut state = subtyping::State {
already_checked: Default::default(),
mode: Default::default(),
contributions: Default::default(),
others: subtyping::SubTypingOptions {
allow_errors: true,
},
object_constraints: None,
};

let result = subtyping::type_is_subtype(
parameter_restriction,
argument,
&mut state,
environment,
&checking_data.types,
);

if let subtyping::SubTypeResult::IsNotSubType(_matches) =
result
{
let error =
TypeCheckError::GenericArgumentDoesNotMeetRestriction {
parameter_restriction:
TypeStringRepresentation::from_type_id(
parameter_restriction,
use crate::types::subtyping;

let mut state = subtyping::State {
already_checked: Default::default(),
mode: Default::default(),
contributions: Default::default(),
others: subtyping::SubTypingOptions {
allow_errors: true,
},
object_constraints: None,
constraint_inference_requests: None,
};

let result = subtyping::type_is_subtype(
parameter_restriction,
argument,
&mut state,
environment,
&checking_data.types,
);

if let subtyping::SubTypeResult::IsNotSubType(
_matches,
) = result
{
let error =
TypeCheckError::GenericArgumentDoesNotMeetRestriction {
parameter_restriction:
TypeStringRepresentation::from_type_id(
parameter_restriction,
environment,
&checking_data.types,
checking_data.options.debug_types,
),
argument: TypeStringRepresentation::from_type_id(
argument,
environment,
&checking_data.types,
checking_data.options.debug_types,
),
argument: TypeStringRepresentation::from_type_id(
argument,
environment,
&checking_data.types,
checking_data.options.debug_types,
),
position: argument_type_annotation
.get_position()
.with_source(environment.get_source()),
};

checking_data.diagnostics_container.add_error(error);
position: argument_type_annotation
.get_position()
.with_source(environment.get_source()),
};

checking_data
.diagnostics_container
.add_error(error);
}
}
}

argument
};

let position = argument_type_annotation
.get_position()
.with_source(environment.get_source());
Expand Down
Loading

0 comments on commit d4142fe

Please sign in to comment.