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

You can obtain a val from a box field via recover #4244

Closed
chalcolith opened this issue Nov 15, 2022 · 13 comments · Fixed by #4458
Closed

You can obtain a val from a box field via recover #4244

chalcolith opened this issue Nov 15, 2022 · 13 comments · Fixed by #4458
Assignees
Labels
triggers release Major issue that when fixed, results in an "emergency" release

Comments

@chalcolith
Copy link
Member

In the following code

class Foo
  let s: String box
  
  new create(s': String box) =>
    s = s'
  
  fun get_s(): String val =>
    recover val s end

actor Main
  new create(env: Env) =>
    let s = String
    s.append("world")
    let foo = Foo(s)
    env.out.print("hello " + foo.get_s())

The get_s() function should not compile, as recovering a val from a box is a leak in the type system.

@ponylang-main ponylang-main added the discuss during sync Should be discussed during an upcoming sync label Nov 15, 2022
@SeanTAllen SeanTAllen added triggers release Major issue that when fixed, results in an "emergency" release help wanted Extra attention is needed bug needs investigation This needs to be looked into before its "ready for work" labels Nov 15, 2022
@jemc jemc changed the title You can obtain a vail from a box via recover You can obtain a val from a box via recover Nov 15, 2022
@jemc
Copy link
Member

jemc commented Nov 22, 2022

This is the error message we should be getting here:

if(!sendable(type))
{
if(!sendable(l_type))
{
errorframe_t frame = NULL;
ast_error_frame(&frame, ast, "can't access non-sendable field of "
"non-sendable object inside of a recover expression");
errorframe_report(&frame, opt->check.errors);
return false;
}
}

@jasoncarr0
Copy link
Contributor

This seems to be related to the sendability check for arrow types:

  fun get_s(): String val =>
    let f: this->(Foo box) = this // this works
    // let f: (Foo box) = this // this doesn't
    recover val f.s end

https://playground.ponylang.io/?gist=b6e61f17abf5e3f0b46f68e65ec2ddf6

@SeanTAllen
Copy link
Member

@jasoncarr0 @jemc at sync today we merged a triggers release issue fix. I am prepping to do a release for that, however, if you think this would be fixed "soon-ish" like within a few days, I would hold the release to include this as well.

Should I hold or go ahead with the release?

@jemc
Copy link
Member

jemc commented Nov 23, 2022

@SeanTAllen - I say go ahead with the release.

@jasoncarr0
Copy link
Contributor

I would say go ahead because I'm not sure how long it would take for a fix depending on the details of the issue.

@jemc jemc changed the title You can obtain a val from a box via recover You can obtain a val from a box field via recover Dec 6, 2022
@SeanTAllen SeanTAllen removed help wanted Extra attention is needed discuss during sync Should be discussed during an upcoming sync labels Dec 6, 2022
@SeanTAllen
Copy link
Member

@jasoncarr0 checking it to see if you are making progress on this.

@ponylang-main ponylang-main added the discuss during sync Should be discussed during an upcoming sync label Jan 5, 2023
@jasoncarr0
Copy link
Contributor

jasoncarr0 commented Jan 10, 2023

I haven't been making progress / working on this much, I know that the issue is that the current code takes the lower bound (so that lb(this->box) turns into lb({ref,val,box}->box) turns into lb({box,val,box}) into val which counts as sendable for the recover block). But trying to fix this naively just ran into some errors about what is supported. It's probably something very simple

@jemc jemc removed the discuss during sync Should be discussed during an upcoming sync label Jan 24, 2023
@SeanTAllen SeanTAllen added the help wanted Extra attention is needed label Oct 3, 2023
@SeanTAllen SeanTAllen self-assigned this Oct 3, 2023
@SeanTAllen
Copy link
Member

SeanTAllen commented Oct 4, 2023

So the issue here is that we have

(-> thistype (nominal (id $0) (id String) x box x x))

which in viewpoint_lower hits this unfortunate block:

    case TK_THISTYPE:
      l_cap = TK_CAP_READ;
      break;

And whee! we are going to be sendable because in cap_view_lower we hit:

    case TK_CAP_READ:
    {
      switch(*right_cap)
      {
        case TK_ISO:
          *right_cap = TK_CAP_SEND;
          break;

        case TK_REF:
          *right_cap = TK_CAP_READ;
          break;

        case TK_BOX:
          *right_cap = TK_VAL;
          break;

        default: {}
      }
      break;
    }

where our box "becomes" a val.

@jemc does that sound correct to you? i'm not sure where to go to find the what is the correct thing to do (but I know this isn't correct).

@ponylang-main ponylang-main added the discuss during sync Should be discussed during an upcoming sync label Oct 4, 2023
@jemc
Copy link
Member

jemc commented Oct 4, 2023

@SeanTAllen - yes, that matches Jason's description of the problem, from above:

I know that the issue is that the current code takes the lower bound (so that lb(this->box) turns into lb({ref,val,box}->box) turns into lb({box,val,box}) into val

@SeanTAllen
Copy link
Member

This error exists all the way back on 0.13.0 so this is a long standing bug.

@jasoncarr0
Copy link
Contributor

jasoncarr0 commented Oct 4, 2023

Honestly getting the notifications and looking at this again, I think the only obviously correct solution is checking all instantiations and hence something like a for_all_instantiations function is necessary.

Possibly because sendability as a condition is invariant, not co nor contravariant.

The slightly nicer solution with infinite spare dev-hours is to replace all uses of sendability with a co-/contra-variant version. E.g. in recover blocks, we don't check sendability, we simply pick the best sendable approximation. But that doesn't quite work to replace the special casing on fields because iso->box is tag.

@SeanTAllen
Copy link
Member

I need to check with @sylvanc to see if my fix that passes all tests including regressions for this is in fact sound and correct.

@SeanTAllen
Copy link
Member

i was close, but, not quite there. i had the implementation "not quite right from a theory perspective". when i have time, i'll get the 3 regressions from this issue in place and open a PR to close then and then we can do a release.

SeanTAllen added a commit that referenced this issue Oct 5, 2023
Last November, Gordon identified that the compiler was allowing code
to recover a `val` from a `box` field. This is unsafe and very "doh".

After investigation, it was determined that this bug has existed since
Sylvan introduced viewpoint adaptation to the compiler almost a decade
ago.

I came up with a fix, but after talking with Sylvan, we changed to this
fix as it is the "proper pure theory fix".

Fixes #4244
@SeanTAllen SeanTAllen removed help wanted Extra attention is needed needs investigation This needs to be looked into before its "ready for work" labels Oct 5, 2023
SeanTAllen added a commit that referenced this issue Oct 6, 2023
Last November, Gordon identified that the compiler was allowing code
to recover a `val` from a `box` field. This is unsafe and very "doh".

After investigation, it was determined that this bug has existed since
Sylvan introduced viewpoint adaptation to the compiler almost a decade
ago.

I came up with a fix, but after talking with Sylvan, we changed to this
fix as it is the "proper pure theory fix".

Fixes #4244
@ponylang-main ponylang-main removed the discuss during sync Should be discussed during an upcoming sync label Oct 6, 2023
@SeanTAllen SeanTAllen removed the bug label Jan 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triggers release Major issue that when fixed, results in an "emergency" release
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants