Check noinline annotation on non-local return processing

This commit is contained in:
Michael Bogdanov
2014-09-16 15:33:14 +04:00
parent b763aa9995
commit a735d67e86
3 changed files with 43 additions and 18 deletions
@@ -46,24 +46,7 @@ public class InlineDescriptorUtils {
while (containingFunction instanceof JetFunctionLiteral && fromFunction != containingFunctionDescriptor) {
//JetFunctionLiteralExpression
containingFunction = containingFunction.getParent();
boolean allowsNonLocalReturns = false;
JetExpression call = JetPsiUtil.getParentCallIfPresent((JetFunctionLiteralExpression) containingFunction);
if (call != null) {
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(call, bindingContext);
CallableDescriptor resultingDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
if (resultingDescriptor instanceof SimpleFunctionDescriptor &&
((SimpleFunctionDescriptor) resultingDescriptor).getInlineStrategy().isInline()) {
ValueArgument argument = CallUtilPackage.getValueArgumentForExpression(
resolvedCall.getCall(), (JetFunctionLiteralExpression) containingFunction);
if (argument != null) {
ArgumentMapping mapping = resolvedCall.getArgumentMapping(argument);
if (mapping instanceof ArgumentMatch) {
allowsNonLocalReturns = allowsNonLocalReturns(((ArgumentMatch) mapping).getValueParameter());
}
}
}
}
if (!allowsNonLocalReturns) {
if (!isInlineLambda((JetFunctionLiteralExpression) containingFunction, bindingContext, true)) {
return false;
}
@@ -77,6 +60,32 @@ public class InlineDescriptorUtils {
return fromFunction == containingFunctionDescriptor;
}
public static boolean isInlineLambda(
@NotNull JetFunctionLiteralExpression lambdaExpression,
@NotNull BindingContext bindingContext,
boolean checkNonLocalReturn
) {
JetExpression call = JetPsiUtil.getParentCallIfPresent(lambdaExpression);
if (call != null) {
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(call, bindingContext);
CallableDescriptor resultingDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
if (resultingDescriptor instanceof SimpleFunctionDescriptor &&
((SimpleFunctionDescriptor) resultingDescriptor).getInlineStrategy().isInline()) {
ValueArgument argument = CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), lambdaExpression);
if (argument != null) {
ArgumentMapping mapping = resolvedCall.getArgumentMapping(argument);
if (mapping instanceof ArgumentMatch) {
ValueParameterDescriptor parameter = ((ArgumentMatch) mapping).getValueParameter();
if (!InlineUtil.hasNoinlineAnnotation(parameter)) {
return !checkNonLocalReturn || allowsNonLocalReturns(parameter);
}
}
}
}
}
return false;
}
@Nullable
public static DeclarationDescriptor getContainingClassOrFunctionDescriptor(@NotNull DeclarationDescriptor descriptor, boolean strict) {
DeclarationDescriptor currentDescriptor = strict ? descriptor.getContainingDeclaration() : descriptor;
@@ -0,0 +1,10 @@
// !DIAGNOSTICS: -NOTHING_TO_INLINE
fun main(args: Array<String>) {
test {
<!RETURN_NOT_ALLOWED!>return<!>
}
}
inline fun test(noinline lambda: () -> Unit) {
lambda()
}
@@ -5667,6 +5667,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("noInlineAnnotation.kt")
public void testNoInlineAnnotation() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/nonLocalReturns/noInlineAnnotation.kt");
doTest(fileName);
}
@TestMetadata("noInlineLambda.kt")
public void testNoInlineLambda() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inline/nonLocalReturns/noInlineLambda.kt");