Skip to content

Commit

Permalink
Check default parameter value type (#132)
Browse files Browse the repository at this point in the history
* Check default parameter value type (fixes #112)
  • Loading branch information
CharlesTaylor7 committed Apr 14, 2024
1 parent 05031e2 commit 24e35b9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 3 deletions.
11 changes: 11 additions & 0 deletions checker/specification/specification.md
Expand Up @@ -315,6 +315,17 @@ function func(a: number) {

- Expected string, found number

#### Default parameter value type check

```ts
function outer(a: number) {
function inner(b: string = Math.floor(a)) {
}
}
```

- Cannot use a default value of type number for parameter of type string

#### (simple) return type checking

```ts
Expand Down
21 changes: 18 additions & 3 deletions checker/src/diagnostics.rs
Expand Up @@ -357,6 +357,11 @@ mod defined_errors_and_warnings {
name: &'a str,
position: SpanWithSource,
},
InvalidDefaultParameter {
at: SpanWithSource,
expected: TypeStringRepresentation,
found: TypeStringRepresentation,
},
/// TODO temp, needs more info
FunctionDoesNotMeetConstraint {
function_constraint: TypeStringRepresentation,
Expand Down Expand Up @@ -649,14 +654,24 @@ mod defined_errors_and_warnings {
position: returned_position,
kind,
},
TypeCheckError::CatchTypeDoesNotMatch {
TypeCheckError::InvalidDefaultParameter {
expected,
found,
at,
} => Diagnostic::Position {
reason: format!(
"Cannot use a default value of type {found} for parameter of type {expected}",
),
position: at,
kind,
},
TypeCheckError::CatchTypeDoesNotMatch {
expected,
found,
at,
} => Diagnostic::Position {
reason: format!(
"Cannot catch type {found} because the try block throws {expected}",

"Cannot catch type {found} because the try block throws {expected}",
),
position: at,
kind,
Expand Down
31 changes: 31 additions & 0 deletions checker/src/features/functions.rs
Expand Up @@ -12,7 +12,9 @@ use crate::{
information::{merge_info, LocalInformation},
CanReferenceThis, ContextType, Syntax,
},
diagnostics::{TypeCheckError, TypeStringRepresentation},
events::RootReference,
subtyping::{type_is_subtype, BasicEquality, SubTypeResult},
types::{
self,
classes::ClassValue,
Expand Down Expand Up @@ -194,6 +196,35 @@ pub fn synthesise_function_default_value<'a, T: crate::ReadFromFS, A: ASTImpleme
},
);

let mut basic_equality = BasicEquality::default();

let result = type_is_subtype(
parameter_constraint,
value,
&mut basic_equality,
environment,
&checking_data.types,
);

if let SubTypeResult::IsNotSubType(_) = result {
let expected = TypeStringRepresentation::from_type_id(
parameter_ty,
environment,
&checking_data.types,
false,
);

let found =
TypeStringRepresentation::from_type_id(value, environment, &checking_data.types, false);
let at = A::expression_position(expression).with_source(environment.get_source());

checking_data.diagnostics_container.add_error(TypeCheckError::InvalidDefaultParameter {
at,
expected,
found,
});
}

// Abstraction of `typeof parameter === "undefined"` to generate less types.
let is_undefined_condition = checking_data.types.register_type(Type::Constructor(
Constructor::TypeRelationOperator(types::TypeRelationOperator::Extends {
Expand Down
11 changes: 11 additions & 0 deletions checker/src/types/mod.rs
Expand Up @@ -387,6 +387,17 @@ pub struct BasicEquality {
pub allow_errors: bool,
}

impl Default for BasicEquality {
fn default() -> Self {
Self {
add_property_restrictions: false,
position: source_map::Nullable::NULL,
object_constraints: Default::default(),
allow_errors: false,
}
}
}

/// For subtyping

pub trait SubTypeBehavior<'a> {
Expand Down

0 comments on commit 24e35b9

Please sign in to comment.