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

Should type t:someType arguments allow coercion? #7779

Closed
mppf opened this issue Nov 11, 2017 · 4 comments
Closed

Should type t:someType arguments allow coercion? #7779

mppf opened this issue Nov 11, 2017 · 4 comments

Comments

@mppf
Copy link
Member

mppf commented Nov 11, 2017

Consider this example program:

proc foo(type t:int) {
  writeln("int version");
}
foo(int(8));

Currently this program compiles and resolves. But that reflects the fact that int(8) can coerce to int(64). Should this be allowed?

@bradcray
Copy link
Member

Intuitively, I'd think "no", but at the same time, I'm not sure what saying type t: int ought to mean in this context. "You can pass in any type 't' as long as it's int" doesn't seem very interesting.

I would expect type t: int(?t) to support passing in any int type...

@mppf
Copy link
Member Author

mppf commented Nov 17, 2017

"You can pass in any type 't' as long as it's int" doesn't seem very interesting.

It is interesting for things like casts, where you want to override a generic function that takes in a type argument to apply to a specific type.

E.g. in ChapelBase.chpl right now, we have

  inline proc chpl_typeSupportsPrimitiveCast(type t) param
    return isBoolType(t) ||
           isIntegralType(t) ||
           isRealType(t);

  inline proc _cast(type t, x: int(?w)) where chpl_typeSupportsPrimitiveCast(t)
    return __primitive("cast", t, x);

We might contemplate rewriting that like this:

  inline proc _cast(type t:bool(?a), x: int(?b))
    return __primitive("cast", t, x);

  inline proc _cast(type t:int(?a), x: int(?b))
    return __primitive("cast", t, x);

  inline proc _cast(type t:uint(?a), x: int(?b))
    return __primitive("cast", t, x);

  inline proc _cast(type t:real(?a), x: int(?b))
    return __primitive("cast", t, x);

If we did, AFAIK the compiler would actually create overloads for all of the ?a / ?b combinations directly (instead of leaving them generic). And then we'd have (at some point) a function like

  inline proc _cast(type t:int(32), x: int(8))
    return __primitive("cast", t, x);

which is exactly the "Doesn't seem very interesting" case in that it only accepts a single type for the type argument.

@bradcray
Copy link
Member

I see, thanks for the additional context. I think I still believe that the int(8) type shouldn't coerce to a type argument expecting an int(64).

@mppf
Copy link
Member Author

mppf commented Dec 21, 2017

I'm currently thinking that disallowing coercion for type arguments makes them behave more naturally, since the common case for a type argument probably is to create a generic function - and in that setting, the generic will be instantiated with the actual type (i.e. there won't be any coercions). Additionally I recently saw _new candidates for parent class types being considered in disambiguation, which is probably not intended.

It's still the case though that you can have something like this (from the test type-colon-generic-record.chpl):

record R {
  var x;
}

proc foo(type t:R) {
  writeln("generic ", t:string);
}
proc foo(type t:R(real)) {
  writeln("real ", t:string);
}


var r1=new R(1);
var rs=new R("test");
var rr=new R(1.0);

foo(r1.type);
foo(rs.type);
foo(rr.type);

which compiles and runs; the 3rd call to foo runs the "real" version.

I think that makes sense because it matches how generic instantiation works / how a generic function with a where clause would work.

mppf added a commit that referenced this issue Jan 18, 2018
Don't allow coercions for type variable arguments

Before this PR, the following program would compile and run. After, it will not.

``` chapel
proc foo(type t:int) {
  writeln("int version");
}
foo(int(8));
```

This PR disables implicit coercions for type arguments with a type specifier (such as `type t:int` in the example) - unless those coercions are implementing class subtyping. The idea here is to make `type t:SomeType` behave similarly to `where t:SomeType` for a generic `type t` argument. See issue #7779 for discussion.

Fixes #7779 

- [x] passed full local testing

Reviewed by @bradcray - thanks!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants