Skip to content

Commit

Permalink
Allow casting borrowed to unmanaged (chapel-lang#24356)
Browse files Browse the repository at this point in the history
This PR partially reverts the 1.31 deprecation of casting to
`unmanaged`. Prior to the deprecation, any managed class object could be
casted to an `unmanaged` instance without affecting the lifetime of the
original object. The cast was only allowed for `borrowed` to
`unmanaged`, but implicit conversion allowed casting `owned` or `shared`
to `unmanaged`. After this PR, users can only cast explicit `borrowed`
objects to `unmanaged`. This allows users to escape the lifetime
checker.

This PR also reverts some of the changes chapel-lang#22404 made to the packaged
modules and tests.

Testing
- [x] paratest w/wo comm
- [x] built and checked docs

Note to reviewer: since the cast to `unmanaged` has been deprecated for
3 releases, this PR adding a new error message moved straight to making
it an error rather than a deprecation warning that will become an error
in the future.

[Reviewed by @lydia-duncan]

closes chapel-lang#23731
  • Loading branch information
jabraham17 authored Feb 8, 2024
2 parents 8f952fa + b1ffd58 commit 96d7c26
Show file tree
Hide file tree
Showing 53 changed files with 688 additions and 199 deletions.
2 changes: 1 addition & 1 deletion modules/dists/BlockDist.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ override proc BlockImpl.dsiNewRectangularDom(param rank: int, type idxType,
delete dummyLBD;

var dom = new unmanaged BlockDom(rank, idxType, strides, sparseLayoutType,
_to_unmanaged(this), locDomsTemp, whole);
this:unmanaged, locDomsTemp, whole);

if debugBlockDist {
writeln("Creating new Block domain:");
Expand Down
2 changes: 1 addition & 1 deletion modules/dists/CyclicDist.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ override proc CyclicImpl.dsiNewRectangularDom(param rank: int, type idxType, par
delete dummyLCD;

var dom = new unmanaged CyclicDom(rank, idxType, strides,
_to_unmanaged(this), locDomsTemp, whole);
this:unmanaged, locDomsTemp, whole);
return dom;
}

Expand Down
92 changes: 31 additions & 61 deletions modules/internal/ChapelBase.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -2220,46 +2220,59 @@ module ChapelBase {
compilerError("cannot cast nil to " + t:string);
}

proc chpl_castUnmanagedError(param typeStr: string) param do
compilerError("cannot cast to a '" + typeStr +
"' with an implicit borrow; try adding an explicit '.borrow()'");


pragma "last resort"
operator :(x:owned class, type t:unmanaged class)
do chpl_castUnmanagedError(t:string);
pragma "last resort"
operator :(x:owned class?, type t:unmanaged class)
do chpl_castUnmanagedError(t:string);
pragma "last resort"
operator :(x:owned class, type t:unmanaged class?)
do chpl_castUnmanagedError(t:string);
pragma "last resort"
operator :(x:owned class?, type t:unmanaged class?)
do chpl_castUnmanagedError(t:string);

pragma "last resort"
operator :(x:shared class, type t:unmanaged class)
do chpl_castUnmanagedError(t:string);
pragma "last resort"
operator :(x:shared class?, type t:unmanaged class)
do chpl_castUnmanagedError(t:string);
pragma "last resort"
operator :(x:shared class, type t:unmanaged class?)
do chpl_castUnmanagedError(t:string);
pragma "last resort"
operator :(x:shared class?, type t:unmanaged class?)
do chpl_castUnmanagedError(t:string);

// casting to unmanaged?, no class downcast
pragma "last resort"
@deprecated("casting from a managed class to an 'unmanaged?' is deprecated")
inline operator :(x:borrowed class?, type t:unmanaged class?)
where isSubtype(_to_unmanaged(x.type),t)
{
return __primitive("cast", t, x);
}
inline operator :(x:unmanaged class?, type t:unmanaged class?)
where isSubtype(_to_unmanaged(x.type),t)
{
return __primitive("cast", t, x);
}

pragma "last resort"
@deprecated("casting from a managed class to an 'unmanaged?' is deprecated")
inline operator :(x:borrowed class, type t:unmanaged class?)
where isSubtype(_to_nonnil(_to_unmanaged(x.type)),t)
{
return __primitive("cast", t, x);
}
inline operator :(x:unmanaged class, type t:unmanaged class?)
where isSubtype(_to_nonnil(_to_unmanaged(x.type)),t)
{
return __primitive("cast", t, x);
}

// casting to unmanaged, no class downcast
pragma "last resort"
@deprecated("casting from a managed class to an 'unmanaged' is deprecated")
inline operator :(x:borrowed class, type t:unmanaged class)
where isSubtype(_to_unmanaged(x.type),t)
{
return __primitive("cast", t, x);
}
inline operator :(x:unmanaged class, type t:unmanaged class)
where isSubtype(_to_unmanaged(x.type),t)
{
return __primitive("cast", t, x);
}

// casting away nilability, no class downcast
inline operator :(x:unmanaged class?, type t:borrowed class) throws
Expand All @@ -2284,7 +2297,6 @@ module ChapelBase {

// casting away nilability, no class downcast
pragma "last resort"
@deprecated("casting from a managed class to an 'unmanaged' is deprecated")
inline operator :(x:borrowed class?, type t:unmanaged class) throws
where isSubtype(_to_nonnil(_to_unmanaged(x.type)),t)
{
Expand All @@ -2293,14 +2305,6 @@ module ChapelBase {
}
return __primitive("cast", t, x);
}
inline operator :(x:unmanaged class?, type t:unmanaged class) throws
where isSubtype(_to_nonnil(_to_unmanaged(x.type)),t)
{
if x == nil {
throw new owned NilClassError();
}
return __primitive("cast", t, x);
}

// this version handles downcast to non-nil borrowed
inline operator :(x:borrowed class?, type t:borrowed class) throws
Expand Down Expand Up @@ -2331,7 +2335,6 @@ module ChapelBase {

// this version handles downcast to non-nil unmanaged
pragma "last resort"
@deprecated("casting from a managed class to an 'unmanaged' is deprecated")
inline operator :(x:borrowed class?, type t:unmanaged class) throws
where isProperSubtype(t,_to_nonnil(_to_unmanaged(x.type)))
{
Expand All @@ -2345,23 +2348,9 @@ module ChapelBase {

return _to_nonnil(_to_unmanaged(tmp));
}
inline operator :(x:unmanaged class?, type t:unmanaged class) throws
where isProperSubtype(t,_to_nonnil(_to_unmanaged(x.type)))
{
if x == nil {
throw new owned NilClassError();
}
var tmp = __primitive("dynamic_cast", t, x);
if tmp == nil {
throw new owned ClassCastError();
}

return _to_nonnil(_to_unmanaged(tmp));
}

// this version handles downcast to nilable unmanaged
pragma "last resort"
@deprecated("casting from a managed class to an 'unmanaged?' is deprecated")
inline operator :(x:borrowed class?, type t:unmanaged class?)
where isProperSubtype(t,_to_unmanaged(x.type))
{
Expand All @@ -2371,19 +2360,9 @@ module ChapelBase {
var tmp = __primitive("dynamic_cast", t, x);
return _to_nilable(_to_unmanaged(tmp));
}
inline operator :(x:unmanaged class?, type t:unmanaged class?)
where isProperSubtype(t,_to_unmanaged(x.type))
{
if x == nil {
return nil;
}
var tmp = __primitive("dynamic_cast", t, x);
return _to_nilable(_to_unmanaged(tmp));
}

// this version handles downcast to nilable unmanaged
pragma "last resort"
@deprecated("casting from a managed class to an 'unmanaged?' is deprecated")
inline operator :(x:borrowed class, type t:unmanaged class?)
where isProperSubtype(_to_nonnil(_to_borrowed(t)),x.type)
{
Expand All @@ -2393,15 +2372,6 @@ module ChapelBase {
var tmp = __primitive("dynamic_cast", t, x);
return _to_nilable(_to_unmanaged(tmp));
}
inline operator :(x:unmanaged class, type t:unmanaged class?)
where isProperSubtype(_to_nonnil(_to_borrowed(t)),x.type)
{
if x == nil {
return nil;
}
var tmp = __primitive("dynamic_cast", t, x);
return _to_nilable(_to_unmanaged(tmp));
}



Expand Down
6 changes: 3 additions & 3 deletions modules/internal/DefaultAssociative.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ module DefaultAssociative {

// set the rehash helpers
this.table.rehashHelpers =
new DefaultAssociativeDomRehashHelper(_to_unmanaged(this));
new DefaultAssociativeDomRehashHelper(this:unmanaged);
}
proc deinit() {
// chpl__hashtable.deinit does all we need here
Expand All @@ -111,7 +111,7 @@ module DefaultAssociative {
return new unmanaged DefaultAssociativeArr(eltType=eltType,
idxType=idxType,
parSafeDom=parSafe,
dom=_to_unmanaged(this),
dom=this:unmanaged,
initElts=initElts);
}

Expand Down Expand Up @@ -448,7 +448,7 @@ module DefaultAssociative {

proc dsiLocalSubdomain(loc: locale) {
if this.locale == loc {
return _getDomain(_to_unmanaged(this));
return _getDomain(this:unmanaged);
} else {
var a: domain(idxType, parSafe=parSafe);
return a;
Expand Down
16 changes: 8 additions & 8 deletions modules/internal/OwnedObject.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ module OwnedObject {
@chpldoc.nodoc
inline operator :(pragma "nil from arg" in x:owned class, type t:owned class?) where isSubtype(x.chpl_t,_to_nonnil(t.chpl_t))
{
var castPtr = _to_unmanaged(x.chpl_p):_to_nilable(_to_unmanaged(t.chpl_t));
var castPtr = x.chpl_p:_to_nilable(_to_unmanaged(t.chpl_t));
x.chpl_p = nil;
// t stores a nilable type
return new _owned(castPtr);
Expand All @@ -422,7 +422,7 @@ module OwnedObject {
inline operator :(pragma "nil from arg" in x:owned class?, type t:owned class?)
where isSubtype(x.chpl_t,t.chpl_t)
{
var castPtr = _to_unmanaged(x.chpl_p):_to_nilable(_to_unmanaged(t.chpl_t));
var castPtr = x.chpl_p:_to_nilable(_to_unmanaged(t.chpl_t));
x.chpl_p = nil;
// t stores a nilable type
return new _owned(castPtr);
Expand All @@ -433,7 +433,7 @@ module OwnedObject {
inline operator :(pragma "nil from arg" in x:owned class, type t:owned class)
where isSubtype(x.chpl_t,t.chpl_t)
{
var castPtr = _to_unmanaged(x.chpl_p):_to_nilable(_to_unmanaged(t.chpl_t));
var castPtr = x.chpl_p:_to_nilable(_to_unmanaged(t.chpl_t));
x.chpl_p = nil;
// t stores a non-nilable type
return new _owned(castPtr!);
Expand All @@ -444,7 +444,7 @@ module OwnedObject {
inline operator :(in x:owned class?, type t:owned class) throws
where isSubtype(_to_nonnil(x.chpl_t),t.chpl_t)
{
var castPtr = _to_unmanaged(x.chpl_p):_to_nilable(_to_unmanaged(t.chpl_t));
var castPtr = x.chpl_p:_to_nilable(_to_unmanaged(t.chpl_t));
if castPtr == nil {
throw new owned NilClassError();
}
Expand All @@ -462,7 +462,7 @@ module OwnedObject {
throw new owned NilClassError();
}
// the following line can throw ClassCastError
var castPtr = try _to_unmanaged(x.chpl_p):_to_nonnil(_to_unmanaged(t.chpl_t));
var castPtr = try x.chpl_p:_to_nonnil(_to_unmanaged(t.chpl_t));
x.chpl_p = nil;
return new _owned(castPtr);
}
Expand All @@ -471,7 +471,7 @@ module OwnedObject {
where isProperSubtype(t.chpl_t,x.chpl_t)
{
// the following line can throw ClassCastError
var castPtr = try _to_unmanaged(x.chpl_p):_to_nonnil(_to_unmanaged(t.chpl_t));
var castPtr = try x.chpl_p:_to_nonnil(_to_unmanaged(t.chpl_t));
x.chpl_p = nil;
return new _owned(castPtr);
}
Expand All @@ -483,7 +483,7 @@ module OwnedObject {
where isProperSubtype(t.chpl_t,x.chpl_t)
{
// this cast returns nil if the dynamic type is not compatible
var castPtr = _to_unmanaged(x.chpl_p):_to_nilable(_to_unmanaged(t.chpl_t));
var castPtr = x.chpl_p:_to_nilable(_to_unmanaged(t.chpl_t));
if castPtr != nil {
x.chpl_p = nil;
}
Expand All @@ -495,7 +495,7 @@ module OwnedObject {
where isProperSubtype(_to_nonnil(t.chpl_t),x.chpl_t)
{
// this cast returns nil if the dynamic type is not compatible
var castPtr = _to_unmanaged(x.chpl_p):_to_nilable(_to_unmanaged(t.chpl_t));
var castPtr = x.chpl_p:_to_nilable(_to_unmanaged(t.chpl_t));
if castPtr != nil {
x.chpl_p = nil;
}
Expand Down
8 changes: 4 additions & 4 deletions modules/internal/SharedObject.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ module SharedObject {
throw new owned NilClassError();
}
// the following line can throw ClassCastError
var p = try _to_unmanaged(x.chpl_p):_to_nonnil(_to_unmanaged(t.chpl_t));
var p = try x.chpl_p:_to_nonnil(_to_unmanaged(t.chpl_t));

return new _shared(true, _to_borrowed(p.type), p, x.chpl_pn);
}
Expand All @@ -644,7 +644,7 @@ module SharedObject {
where isProperSubtype(t.chpl_t, x.chpl_t)
{
// the following line can throw ClassCastError
var p = try _to_unmanaged(x.chpl_p):_to_nonnil(_to_unmanaged(t.chpl_t));
var p = try x.chpl_p:_to_nonnil(_to_unmanaged(t.chpl_t));

return new _shared(true, _to_borrowed(p.type), p, x.chpl_pn);
}
Expand All @@ -656,15 +656,15 @@ module SharedObject {
where isProperSubtype(t.chpl_t, x.chpl_t)
{
// this cast returns nil if the dynamic type is not compatible
var p = _to_unmanaged(x.chpl_p):_to_nilable(_to_unmanaged(t.chpl_t));
var p = x.chpl_p:_to_nilable(_to_unmanaged(t.chpl_t));
return new _shared(true, _to_borrowed(p.type), p, x.chpl_pn);
}
@chpldoc.nodoc
inline operator :(const ref x:shared class, type t:shared class?)
where isProperSubtype(t.chpl_t, x.chpl_t:class?)
{
// this cast returns nil if the dynamic type is not compatible
var p = _to_unmanaged(x.chpl_p):_to_nilable(_to_unmanaged(t.chpl_t));
var p = x.chpl_p:_to_nilable(_to_unmanaged(t.chpl_t));
return new _shared(true, _to_borrowed(p.type), p, x.chpl_pn);
}

Expand Down
2 changes: 1 addition & 1 deletion modules/packages/Curl.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ module Curl {
end:int(64),
qioChannelPtr:qio_channel_ptr_t):errorCode {
var curlch = new unmanaged CurlChannel();
curlch.curlf = _to_unmanaged(this);
curlch.curlf = this:unmanaged;
curlch.qio_ch = qioChannelPtr;
pluginChannel = curlch;
return start_channel(curlch, start, end);
Expand Down
4 changes: 2 additions & 2 deletions modules/packages/EpochManager.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ module EpochManager {
}
tok!.is_registered.write(true);
// return tok;
return new owned TokenWrapper(tok!, _to_unmanaged(this));
return new owned TokenWrapper(tok!, this:unmanaged);
}

@chpldoc.nodoc
Expand Down Expand Up @@ -936,7 +936,7 @@ module EpochManager {
}
tok!.is_registered.write(true);
// return tok;
return new owned DistTokenWrapper(tok!, _to_unmanaged(this));
return new owned DistTokenWrapper(tok!, this:unmanaged);
}

@chpldoc.nodoc
Expand Down
4 changes: 2 additions & 2 deletions modules/packages/HDFS.chpl
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ module HDFS {

// Create an HDFSFile and return the QIO file containing it
// this initializer bumps the reference count to this
var fl = new unmanaged HDFSFile(_to_unmanaged(this), hfile, path);
var fl = new unmanaged HDFSFile(this:unmanaged, hfile, path);

var ret: file;
try {
Expand Down Expand Up @@ -387,7 +387,7 @@ module HDFS {
if verbose then
writeln("HDFSFile.setupChannel");

var hdfsch = new unmanaged HDFSChannel(_to_unmanaged(this), qioChannelPtr);
var hdfsch = new unmanaged HDFSChannel(this:unmanaged, qioChannelPtr);
pluginChannel = hdfsch;
return 0;
}
Expand Down
Loading

0 comments on commit 96d7c26

Please sign in to comment.