fix Bugzilla 24353 - add mutability check for foreach with opApply

Signed-off-by: royalpinto007 <royalpinto007@gmail.com>
This commit is contained in:
royalpinto007 2024-11-17 03:19:39 +05:30 committed by Nicholas Wilson
parent f485dbfee1
commit f5f7baeb19
2 changed files with 56 additions and 6 deletions

View file

@ -779,14 +779,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
Dsymbol sapplyOld = sapply; // 'sapply' will be NULL if and after 'inferApplyArgTypes' errors
/* Check for inference errors
*/
/* Check for inference errors and apply mutability checks inline */
if (!inferApplyArgTypes(fs, sc, sapply))
{
/**
Try and extract the parameter count of the opApply callback function, e.g.:
int opApply(int delegate(int, float)) => 2 args
*/
bool foundMismatch = false;
size_t foreachParamCount = 0;
if (sapplyOld)
@ -806,6 +801,19 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
auto tf = fparam.type.nextOf().isTypeFunction();
foreachParamCount = tf.parameterList.length;
foundMismatch = true;
// Mutability check
if (fs.aggr && fs.aggr.type && fd.type && fs.aggr.type.isConst() && !fd.type.isConst())
{
// First error: The call site
error(fs.loc, "mutable method `%s.%s` is not callable using a `const` object",
fd.parent ? fd.parent.toPrettyChars() : "unknown", fd.toChars());
// Second error: Suggest how to fix
errorSupplemental(fd.loc, "Consider adding `const` or `inout` here");
return setError();
}
}
}
}
@ -824,6 +832,24 @@ Statement statementSemanticVisit(Statement s, Scope* sc)
return setError();
}
// If inference succeeds, proceed with post-checks
if (sapply && sapply.isFuncDeclaration())
{
FuncDeclaration fd = sapply.isFuncDeclaration();
if (fs.aggr && fs.aggr.type && fd.type && fs.aggr.type.isConst() && !fd.type.isConst())
{
// First error: The call site
error(fs.loc, "mutable method `%s.%s` is not callable using a `const` object",
fd.parent ? fd.parent.toPrettyChars() : "unknown", fd.toChars());
// Second error: Suggest how to fix
errorSupplemental(fd.loc, "Consider adding `const` or `inout` here");
return setError();
}
}
Type tab = fs.aggr.type.toBasetype();
if (tab.ty == Ttuple) // don't generate new scope for tuple loops

View file

@ -0,0 +1,24 @@
// https://issues.dlang.org/show_bug.cgi?id=24353
/**
TEST_OUTPUT:
---
fail_compilation/test24353.d(23): Error: mutable method `test24353.S.opApply` is not callable using a `const` object
fail_compilation/test24353.d(14): Consider adding `const` or `inout` here
---
*/
struct S
{
int opApply(int delegate(int) dg)
{
return 0;
}
}
void example()
{
const S s;
foreach (e; s) {} // Error expected here
}