@@ -216,6 +216,16 @@ class CastLogicHelper
216216
217217 if (auto resFuncType = dyn_cast<mlir_ts::FunctionType>(resType))
218218 {
219+ // dropping a bound/hybrid value to a plain FunctionType only loses the
220+ // receiver when the target has no `this` slot of its own. A target
221+ // whose first input is opaque/object-typed (method-member convention,
222+ // see isBoundReference) keeps the this param in the funcptr signature
223+ // and the receiver is re-bound from the base object at every property
224+ // access - nothing is lost, so no warning.
225+ auto resKeepsThisParam = resFuncType.getNumInputs () > 0 &&
226+ (isa<mlir_ts::OpaqueType>(resFuncType.getInput (0 )) ||
227+ isa<mlir_ts::ObjectType>(resFuncType.getInput (0 )));
228+
219229 if (auto inBoundFunc = dyn_cast<mlir_ts::BoundFunctionType>(inType))
220230 {
221231 // somehow llvm.trampoline accepts only direct method symbol
@@ -224,7 +234,10 @@ class CastLogicHelper
224234 auto methodVal = rewriter.create<mlir_ts::GetMethodOp>(loc, resFuncType, in);
225235 return rewriter.create<mlir_ts::TrampolineOp>(loc, resFuncType, methodVal, thisVal);
226236 */
227- op->emitWarning (" losing this reference" );
237+ if (!resKeepsThisParam)
238+ {
239+ op->emitWarning (" losing this reference" );
240+ }
228241 /*
229242 // you can wrap into () => {} lambda call to capture vars
230243 const user = {
@@ -249,7 +262,10 @@ class CastLogicHelper
249262 // and re-supplied by the caller (e.g. an interface vtable call passes its own
250263 // thisVal) - this is the vtable-method-pointer path for a cross-module tuple
251264 // value cast to a method-bearing interface.
252- op->emitWarning (" losing this reference" );
265+ if (!resKeepsThisParam)
266+ {
267+ op->emitWarning (" losing this reference" );
268+ }
253269 return rewriter.create <mlir_ts::GetMethodOp>(loc, resFuncType, in);
254270 }
255271 }
0 commit comments