-
Notifications
You must be signed in to change notification settings - Fork 1
Closed
Labels
releasedIncluded in a releaseIncluded in a releasevalidation ✔️Improved or new static checksImproved or new static checks
Milestone
Description
Show a warning if we detect that a statement has no effect. For assignment statements, the assignee list must contain only wildcards, and the RHS must have no effect:
package tests.validation.other.statements.assignments.hasNoEffect
step myFunction() -> a: Int {
// $TEST$ warning "This statement does nothing."
»_ = 1 + 2;«
// $TEST$ no warning "This statement does nothing."
»val a = 1;«
// $TEST$ no warning "This statement does nothing."
»yield a = 1;«
() {
// $TEST$ warning "This statement does nothing."
»_ = 1 + 2;«
// $TEST$ no warning "This statement does nothing."
»val a = 1;«
// $TEST$ no warning "This statement does nothing."
»yield a = 1;«
};
}
For expression statements, the expression must have no effect:
package tests.validation.other.statements.expressionStatements.hasNoEffect
fun impureFunction()
@Pure fun pureFunction() -> a: Int
class MyClass() {
fun impureFunction()
@Pure fun pureFunction()
}
segment pureStep() {
val a = pureFunction();
}
segment impureStep() {
impureFunction();
}
segment recursiveA() {
recursiveB();
}
segment recursiveB() {
recursiveA();
}
segment myStep() {
// $TEST$ warning "This statement does nothing."
»1 + 2;«
// $TEST$ warning "This statement does nothing."
»pureFunction();«
// $TEST$ warning "This statement does nothing."
»MyClass().pureFunction();«
// $TEST$ no warning "This statement does nothing."
»impureFunction();«
// $TEST$ no warning "This statement does nothing."
»MyClass().impureFunction();«
() {
// $TEST$ warning "This statement does nothing."
»1 + 2;«
// $TEST$ warning "This statement does nothing."
»pureFunction();«
// $TEST$ warning "This statement does nothing."
»MyClass().pureFunction();«
// $TEST$ no warning "This statement does nothing."
»impureFunction();«
// $TEST$ no warning "This statement does nothing."
»MyClass().impureFunction();«
};
// $TEST$ warning "This statement does nothing."
»(() {
pureFunction();
MyClass().pureFunction();
})();«
// $TEST$ warning "This statement does nothing."
»pureStep();«
// $TEST$ no warning "This statement does nothing."
»(() {
impureFunction();
})();«
// $TEST$ no warning "This statement does nothing."
»(() {
MyClass().impureFunction();
})();«
// $TEST$ no warning "This statement does nothing."
»impureStep();«
// $TEST$ no warning "This statement does nothing."
»recursiveA();«
}
For side-effect inference:
package tests.staticAnalysis.sideEffects
// Positive examples -----------------------------------------------------------
annotation ShouldHaveNoSideEffects
// Call to class constructor
class C()
@ShouldHaveNoSideEffects
step callOfClassConstructor() {
C();
}
// Call to enum variant constructor
enum MyEnum {
Variant
}
@ShouldHaveNoSideEffects
step callOfEnumVariantConstructor() {
MyEnum.Variant();
}
// Function without side effects
@Pure
fun pureFunction()
@NoSideEffects
fun functionWithoutSideEffects()
@ShouldHaveNoSideEffects
step callToPureFunction() {
pureFunction();
functionWithoutSideEffects();
}
// Lambdas without side effects
@ShouldHaveNoSideEffects
step callToPureLambdas() {
(() {})();
(() -> null)();
() {
(() {})();
};
() -> (() -> null)();
}
// Steps without side effects
step pureStep() {}
@ShouldHaveNoSideEffects
step callToPureSteps() {
pureStep();
}
// Uncalled lambdas
step pureStepWithUncalledLambdas() {
() -> impureFunction();
}
@ShouldHaveNoSideEffects
step uncalledLambdas() {
pureStepWithUncalledLambdas();
}
// Function as result
@ShouldHaveNoSideEffects
step pureFunctionAsResult() {
(() -> pureFunction)()();
}
// Negative examples -----------------------------------------------------------
annotation ShouldHaveSideEffects
// Callable type
@ShouldHaveSideEffects
step callToCallableType(f: () -> ()) {
f();
}
// Function with side effects
fun impureFunction()
@ShouldHaveSideEffects
step callToImpureFunction() {
impureFunction();
}
// Lambdas with side effects
@ShouldHaveSideEffects
step callToImpureLambdas() {
(() { impureFunction(); })();
(() -> impureFunction())();
() {
(() { impureFunction(); })();
};
() -> (() -> impureFunction())();
}
// Steps with side effects
step impureStep() {
impureFunction();
}
@ShouldHaveSideEffects
step callToImpureSteps() {
impureStep();
}
// Recursion
@ShouldHaveSideEffects
step recursion() {
recursion();
}
// Unresolved callable
@ShouldHaveSideEffects
step unresolvedCallable() {
unresolved();
}
// Function as parameter
@ShouldHaveSideEffects
step impureFunctionAsParameter() {
((f) -> f())(pureFunction); // This is actually pure, but we match in a conservative manner. Can be improved later.
((f) -> f())(impureFunction);
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
releasedIncluded in a releaseIncluded in a releasevalidation ✔️Improved or new static checksImproved or new static checks
Type
Projects
Status
✔️ Done