Skip to content

Commit

Permalink
Implement record constructor typechecking
Browse files Browse the repository at this point in the history
Summary: Very easy fix, but it should improve buck2 typechecking greatly.

Reviewed By: JakobDegen

Differential Revision: D64216008

fbshipit-source-id: 1477824b42bc8cb3da0ca745a11cad9ae5761a78
  • Loading branch information
stepancheg authored and facebook-github-bot committed Oct 11, 2024
1 parent 616c7fc commit dfdd63e
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 5 deletions.
16 changes: 13 additions & 3 deletions starlark/src/values/types/record/record_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ use crate::typing::starlark_value::TyStarlarkValue;
use crate::typing::user::TyUser;
use crate::typing::user::TyUserFields;
use crate::typing::user::TyUserParams;
use crate::typing::ParamIsRequired;
use crate::typing::ParamSpec;
use crate::typing::Ty;
use crate::util::ArcStr;
use crate::values::function::FUNCTION_TYPE;
use crate::values::record::field::FieldGen;
use crate::values::record::matcher::RecordTypeMatcher;
Expand Down Expand Up @@ -321,9 +323,17 @@ where
TypeInstanceId::gen(),
TyUserParams {
callable: Some(TyCallable::new(
// TODO(nga): more precise parameter types
// https://www.internalfb.com/tasks/?t=184025179
ParamSpec::kwargs(Ty::any()),
ParamSpec::new_named_only(self.fields.iter().map(|(name, field)| {
(
ArcStr::from(name.as_str()),
if field.default.is_some() {
ParamIsRequired::No
} else {
ParamIsRequired::Yes
},
field.ty(),
)
}))?,
ty_record.dupe(),
)),
..TyUserParams::default()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# @generated
# To regenerate, run:
# ```
# STARLARK_RUST_REGENERATE_GOLDEN_TESTS=1 cargo test -p starlark --lib
# ```

Program:

Rec = record(a = int, b = str)

def test():
Rec(c = [])

Error:

error: Unexpected parameter named `c`
--> assert.bzl:4:9
|
4 | Rec(c = [])
| ^^^^^^
|
4 changes: 2 additions & 2 deletions starlark/src/values/types/record/ty_record_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ def f(rec: MyRec) -> int:

#[test]
fn test_typecheck_record_type_call() {
// TODO(nga): this should fail.
assert::pass(
assert::fail_golden(
"src/values/types/record/ty_record_type/typecheck_record_type_call.golden",
r#"
MyRec = record(x = int)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# @generated
# To regenerate, run:
# ```
# STARLARK_RUST_REGENERATE_GOLDEN_TESTS=1 cargo test -p starlark --lib
# ```

Program:

MyRec = record(x = int)

def test():
MyRec(x = "")

Error:

error: Expected type `int` but got `str`
--> assert.bzl:4:11
|
4 | MyRec(x = "")
| ^^^^^^
|

0 comments on commit dfdd63e

Please sign in to comment.