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

[bug] Type error with Self in function argument #187

Closed
1 of 5 tasks
mrodz opened this issue Mar 13, 2024 · 1 comment · Fixed by #188
Closed
1 of 5 tasks

[bug] Type error with Self in function argument #187

mrodz opened this issue Mar 13, 2024 · 1 comment · Fixed by #188
Assignees
Labels
bug Something isn't working
Milestone

Comments

@mrodz
Copy link
Owner

mrodz commented Mar 13, 2024

Documentation Status

Snippet Responsible

class Person {
    name: str
    friends: [Self...]

    constructor(self, name: str) {
        self.name = name
        self.friends = []
    }
    
    fn add_friend(self, friend: Self) {
        self.friends.push(friend)
    }
}

Stack Trace of Error (--verbose, --no-pb)

[ Trace ] INIT Virtual Stack at MODULE
[00:00:00] Parsing (./bug.ms):   Done in 211.1µs                                                                                                                                                                                                                              [ Debug ] pre-walk ".\\bug.ms"
[ Debug ] registering new file ".\\bug.ms" (File { declarations: RefCell { value: [] }, location: ".\\bug.mmm", exports: RefCell { value: [] }, public_types: RefCell { value: {} }, compiled: CompilationLock(Cell { value: false }) }) -- Adding to: []
[ Trace ] Virtual Stack PUSH: Class <UNKNOWN> -> No
[ Trace ] + name: str
[00:00:00] Validating (./bug.ms): /                                                                                                                                                                                                                                           [ Trace ] + friends: [Self...]
[ Trace ] + name: str
[ Debug ] ++ name used to have type str, but now it has type str
[ Trace ] + friend: Self
[ Trace ] + add_friend: fn(Self)
[ Trace ] Virtual Stack POP
[ Trace ] in scope Module, adding type Person = Person
[ Info ] DONE preloading module .\bug.ms
[ Info ] + mod "./bug.ms" ModuleType { exported_members: RefCell { value: [] }, public_types: RefCell { value: {} }, name: ".\\bug.ms" }
[ Info ] + finished preload of ".\\bug.ms"
[ Trace ] Virtual Stack PUSH: Class <UNKNOWN> -> No
[ Trace ] + name: str
[ Trace ] + friends: [Self...]
[ Trace ] + name: str
[ Debug ] ++ name used to have type str, but now it has type str
[ Trace ] + friend: Self
[ Trace ] + add_friend: fn(Self)
[ Trace ] + Person: Person
[ Trace ] class Person { ... }
[ Trace ] + name: str
[ Debug ] ++ name used to have type str, but now it has type str
[ Trace ] + friends: [Self...]
[ Debug ] ++ friends used to have type [Self...], but now it has type [Self...]
[ Trace ] Virtual Stack PUSH: fn(???) -> Void
[ Trace ] + self: Self
[ Trace ] + name: str
[ Debug ] lhs:Native(Str(StrWrapper(None))) rhs:Native(Str(StrWrapper(None))) f:TypecheckFlags { executing_class: Some(ClassType { name: "Person", path_str: ".\\bug.mmm", fields: [Ident { name: "name", ty: Some(Native(Str(StrWrapper(None)))), read_only: false }, Ident { name: "friends", ty: Some(List(Open(Class(<self referential class Person>)))), read_only: false }, Ident { name: "$constructor", ty: Some(Function(FunctionType { parameters: Named([Ident { name: "name", ty: Some(Native(Str(StrWrapper(None)))), read_only: false }]), return_type: RefCell { value: Void }, is_associated_fn: false, is_constructor: true })), read_only: true }, Ident { name: "add_friend", ty: Some(Function(FunctionType { parameters: Named([Ident { name: "friend", ty: Some(ClassSelf), read_only: false }]), return_type: RefCell { value: Void }, is_associated_fn: true, is_constructor: false })), read_only: false }] }), lhs_allow_optional_unwrap: true, force_rhs_to_be_unwrapped_lhs: false, signature_check: false, enforce_str_comptime_len_if_present: false }
[ Debug ] lhs:List(Mixed([])) rhs:List(Open(Class(ClassType { name: "Person", path_str: ".\\bug.mmm", fields: [Ident { name: "name", ty: Some(Native(Str(StrWrapper(None)))), read_only: false }, Ident { name: "friends", ty: Some(List(Open(ClassSelf))), read_only: false }, Ident { name: "$constructor", ty: Some(Function(FunctionType { parameters: Named([Ident { name: "name", ty: Some(Native(Str(StrWrapper(None)))), read_only: false }]), return_type: RefCell { value: Void }, is_associated_fn: false, is_constructor: true })), read_only: true }, Ident { name: "add_friend", ty: Some(Function(FunctionType { parameters: Named([Ident { name: "friend", ty: Some(ClassSelf), read_only: false }]), return_type: RefCell { value: Void }, is_associated_fn: true, is_constructor: false })), read_only: false }] }))) f:TypecheckFlags { executing_class: Some(ClassType { name: "Person", path_str: ".\\bug.mmm", fields: [Ident { name: "name", ty: Some(Native(Str(StrWrapper(None)))), read_only: false }, Ident { name: "friends", ty: Some(List(Open(Class(<self referential class Person>)))), read_only: false }, Ident { name: "$constructor", ty: Some(Function(FunctionType { parameters: Named([Ident { name: "name", ty: Some(Native(Str(StrWrapper(None)))), read_only: false }]), return_type: RefCell { value: Void }, is_associated_fn: false, is_constructor: true })), read_only: true }, Ident { name: "add_friend", ty: Some(Function(FunctionType { parameters: Named([Ident { name: "friend", ty: Some(ClassSelf), read_only: false }]), return_type: RefCell { value: Void }, is_associated_fn: true, is_constructor: false })), read_only: false }] }), lhs_allow_optional_unwrap: true, force_rhs_to_be_unwrapped_lhs: false, signature_check: false, enforce_str_comptime_len_if_present: false }
[ Trace ] Virtual Stack POP
[ Trace ] Virtual Stack PUSH: fn(???) -> Void
[ Trace ] + self: Self
[ Trace ] + friend: Self
[ Debug ] lhs:Class(ClassType { name: "Person", path_str: ".\\bug.mmm", fields: [Ident { name: "name", ty: Some(Native(Str(StrWrapper(None)))), read_only: false }, Ident { name: "friends", ty: Some(List(Open(ClassSelf))), read_only: false }, Ident { name: "$constructor", ty: Some(Function(FunctionType { parameters: Named([Ident { name: "name", ty: Some(Native(Str(StrWrapper(None)))), read_only: false }]), return_type: RefCell { value: Void }, is_associated_fn: false, is_constructor: true })), read_only: true }, Ident { name: "add_friend", ty: Some(Function(FunctionType { parameters: Named([Ident { name: "friend", ty: Some(ClassSelf), read_only: false }]), return_type: RefCell { value: Void }, is_associated_fn: true, is_constructor: false })), read_only: false }] }) rhs:ClassSelf f:TypecheckFlags { executing_class: None, lhs_allow_optional_unwrap: false, force_rhs_to_be_unwrapped_lhs: false, signature_check: false, enforce_str_comptime_len_if_present: false }
[ Error ] ./bug.ms:11:21 > type mismatch when calling function (argument #1 was expected to be `Person` based on type signature, instead found `Self`)
        + hint: `Self` in this context means a function's associated class > "friend"
[ Trace ] Virtual Stack POP
[ Trace ] Virtual Stack POP
[00:00:00] Validating (./bug.ms):   !!! Error !!!
  --> ./bug.ms:11:21
   |
11 |            self.friends.push(friend)
   |                              ^----^
   |
   = type mismatch when calling function (argument #1 was expected to be `Person` based on type signature, instead found `Self`)
        + hint: `Self` in this context means a function's associated class
Error: Did not compile successfully (1 Error)

Expected Behavior

Allow this snippet, as Self does indeed refer to Person.

Any ideas where MScript breaks?

  • Bytecode Interpreter
  • Compiler
  • Optimizer
  • Not Sure (It's okay!)
  • Other: please explain

Brain Dump (Optional)

Not sure yet

@mrodz mrodz added the bug Something isn't working label Mar 13, 2024
@mrodz
Copy link
Owner Author

mrodz commented Mar 13, 2024

It appears as though ClassSelf is overly permissive (when calling a function) and allows instances of other classes as well.

class A {
    fn foo(self, other: Self) {
        # ...
    }
}

class B {
    fn bar(self) {
        a = A()
        a.foo(self) # this line passes type checking, even though it shouldn't
    }
}

@mrodz mrodz self-assigned this Mar 13, 2024
mrodz added a commit that referenced this issue Mar 26, 2024
@mrodz mrodz linked a pull request Mar 26, 2024 that will close this issue
@mrodz mrodz added this to the v1.0.0-rc.5 milestone Apr 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant