KT-1175 Mark unused literals

This commit is contained in:
svtk
2012-01-27 18:28:54 +04:00
parent ca1abed3a9
commit 11ad28812d
27 changed files with 183 additions and 89 deletions
@@ -82,7 +82,7 @@ public class JetControlFlowProcessor {
} }
@Override @Override
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) { public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
JetExpressionPattern pattern = condition.getPattern(); JetExpressionPattern pattern = condition.getPattern();
if (pattern != null) { if (pattern != null) {
pattern.accept(patternVisitor); pattern.accept(patternVisitor);
@@ -641,6 +641,39 @@ public class JetFlowInformationProvider {
} }
} }
////////////////////////////////////////////////////////////////////////////////
// "Unused literals" in block
public void markUnusedLiteralsInBlock(@NotNull JetElement subroutine) {
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
JetControlFlowGraphTraverser<Void> traverser = JetControlFlowGraphTraverser.create(pseudocode, true, true);
traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
@Override
public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) {
if (!(instruction instanceof ReadValueInstruction)) return;
JetElement element = ((ReadValueInstruction) instruction).getElement();
if (!(element instanceof JetFunctionLiteralExpression
|| element instanceof JetConstantExpression
|| element instanceof JetStringTemplateExpression
|| element instanceof JetSimpleNameExpression)) {
return;
}
PsiElement parent = element.getParent();
if (parent instanceof JetBlockExpression) {
if (!JetPsiUtil.isImplicitlyUsed(element)) {
if (element instanceof JetFunctionLiteralExpression) {
trace.report(Errors.UNUSED_FUNCTION_LITERAL.on((JetFunctionLiteralExpression) element));
}
else {
trace.report(Errors.UNUSED_EXPRESSION.on(element));
}
}
}
}
});
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Util methods 7 // Util methods 7
@@ -167,6 +167,8 @@ public interface Errors {
return argument.getText(); return argument.getText();
} }
}; };
SimpleDiagnosticFactory UNUSED_EXPRESSION = SimpleDiagnosticFactory.create(WARNING, "The expression is unused");
SimplePsiElementOnlyDiagnosticFactory<JetFunctionLiteralExpression> UNUSED_FUNCTION_LITERAL = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "The function literal is unused. If you mean block, you can use 'run { ... }'");
PsiElementOnlyDiagnosticFactory1<JetExpression, DeclarationDescriptor> VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME); PsiElementOnlyDiagnosticFactory1<JetExpression, DeclarationDescriptor> VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME);
PsiElementOnlyDiagnosticFactory1<JetExpression, DeclarationDescriptor> INITIALIZATION_BEFORE_DECLARATION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable cannot be initialized before declaration", NAME); PsiElementOnlyDiagnosticFactory1<JetExpression, DeclarationDescriptor> INITIALIZATION_BEFORE_DECLARATION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable cannot be initialized before declaration", NAME);
@@ -1,12 +1,14 @@
package org.jetbrains.jet.lang.psi; package org.jetbrains.jet.lang.psi;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
@@ -85,11 +87,12 @@ public class JetPsiUtil {
if (quoted.startsWith("`") && quoted.endsWith("`") && quoted.length() >= 2) { if (quoted.startsWith("`") && quoted.endsWith("`") && quoted.length() >= 2) {
return quoted.substring(1, quoted.length() - 1); return quoted.substring(1, quoted.length() - 1);
} else { }
else {
return quoted; return quoted;
} }
} }
@NotNull @NotNull
public static String unquoteIdentifierOrFieldReference(@NotNull String quoted) { public static String unquoteIdentifierOrFieldReference(@NotNull String quoted) {
if (quoted.indexOf('`') < 0) { if (quoted.indexOf('`') < 0) {
@@ -98,7 +101,8 @@ public class JetPsiUtil {
if (quoted.startsWith("$")) { if (quoted.startsWith("$")) {
return "$" + unquoteIdentifier(quoted.substring(1)); return "$" + unquoteIdentifier(quoted.substring(1));
} else { }
else {
return unquoteIdentifier(quoted); return unquoteIdentifier(quoted);
} }
} }
@@ -167,4 +171,51 @@ public class JetPsiUtil {
} }
return false; return false;
} }
@Nullable
public static <T extends PsiElement> T getDirectParentOfTypeForBlock(@NotNull JetBlockExpression block, @NotNull Class<T> aClass) {
T parent = PsiTreeUtil.getParentOfType(block, aClass);
if (parent instanceof JetIfExpression) {
JetIfExpression ifExpression = (JetIfExpression) parent;
if (ifExpression.getElse() == block || ifExpression.getThen() == block) {
return parent;
}
}
if (parent instanceof JetWhenExpression) {
JetWhenExpression whenExpression = (JetWhenExpression) parent;
for (JetWhenEntry whenEntry : whenExpression.getEntries()) {
if (whenEntry.getExpression() == block) {
return parent;
}
}
}
if (parent instanceof JetFunctionLiteral) {
JetFunctionLiteral functionLiteral = (JetFunctionLiteral) parent;
if (functionLiteral.getBodyExpression() == block) {
return parent;
}
}
return null;
}
public static boolean isImplicitlyUsed(@NotNull JetElement element) {
PsiElement parent = element.getParent();
if (!(parent instanceof JetBlockExpression)) return true;
JetBlockExpression block = (JetBlockExpression) parent;
List<JetElement> statements = block.getStatements();
if (statements.get(statements.size() - 1) == element) {
JetExpression expression = getDirectParentOfTypeForBlock(block, JetIfExpression.class);
if (expression == null) {
expression = getDirectParentOfTypeForBlock(block, JetWhenExpression.class);
}
if (expression == null) {
expression = getDirectParentOfTypeForBlock(block, JetFunctionLiteral.class);
}
if (expression != null) {
return isImplicitlyUsed(expression);
}
}
return false;
}
} }
@@ -358,7 +358,7 @@ public class JetVisitorVoid extends PsiElementVisitor {
visitJetElement(condition); visitJetElement(condition);
} }
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) { public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
visitJetElement(condition); visitJetElement(condition);
} }
@@ -20,7 +20,7 @@ public class JetWhenConditionWithExpression extends JetWhenCondition {
@Override @Override
public void accept(@NotNull JetVisitorVoid visitor) { public void accept(@NotNull JetVisitorVoid visitor) {
visitor.visitWhenConditionExpression(this); visitor.visitWhenConditionWithExpression(this);
} }
@Override @Override
@@ -81,5 +81,7 @@ public class ControlFlowAnalyzer {
flowInformationProvider.markUninitializedVariables(function.asElement(), context.isDeclaredLocally()); flowInformationProvider.markUninitializedVariables(function.asElement(), context.isDeclaredLocally());
flowInformationProvider.markUnusedVariables(function.asElement()); flowInformationProvider.markUnusedVariables(function.asElement());
flowInformationProvider.markUnusedLiteralsInBlock(function.asElement());
} }
} }
@@ -143,7 +143,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
} }
@Override @Override
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) { public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
JetPattern pattern = condition.getPattern(); JetPattern pattern = condition.getPattern();
if (pattern != null) { if (pattern != null) {
newDataFlowInfo[0] = checkPatternType(pattern, subjectType, subjectExpression == null, scopeToExtend, context, subjectVariables); newDataFlowInfo[0] = checkPatternType(pattern, subjectType, subjectExpression == null, scopeToExtend, context, subjectVariables);
@@ -36,7 +36,7 @@ fun intShortInfer() = 1
fun intShort() : Int = 1 fun intShort() : Int = 1
//fun intBlockInfer() {1} //fun intBlockInfer() {1}
fun intBlock() : Int {return 1} fun intBlock() : Int {return 1}
fun intBlock1() : Int {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>1<!>} fun intBlock1() : Int {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY, UNUSED_EXPRESSION!>1<!>}
fun intString(): Int = <!TYPE_MISMATCH!>"s"<!> fun intString(): Int = <!TYPE_MISMATCH!>"s"<!>
fun intFunctionLiteral(): Int = <!TYPE_MISMATCH!>{ 10 }<!> fun intFunctionLiteral(): Int = <!TYPE_MISMATCH!>{ 10 }<!>
@@ -10,28 +10,28 @@ fun ff() {
} }
fun test() { fun test() {
'a' <!UNUSED_EXPRESSION!>'a'<!>
'\n' <!UNUSED_EXPRESSION!>'\n'<!>
'\t' <!UNUSED_EXPRESSION!>'\t'<!>
'\b' <!UNUSED_EXPRESSION!>'\b'<!>
'\r' <!UNUSED_EXPRESSION!>'\r'<!>
'\"' <!UNUSED_EXPRESSION!>'\"'<!>
'\'' <!UNUSED_EXPRESSION!>'\''<!>
'\\' <!UNUSED_EXPRESSION!>'\\'<!>
'\$' <!UNUSED_EXPRESSION!>'\$'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\x'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\x'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\123'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\123'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\ra'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\ra'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\000'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\000'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\000'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\000'<!>
'\u0000' <!UNUSED_EXPRESSION!>'\u0000'<!>
'\u000a' <!UNUSED_EXPRESSION!>'\u000a'<!>
'\u000A' <!UNUSED_EXPRESSION!>'\u000A'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\u'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u0'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\u0'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u00'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\u00'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u000'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\u000'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\u000z'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\u000z'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\\u000'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\\u000'<!>
<!ERROR_COMPILE_TIME_VALUE!>'\'<!> <!ERROR_COMPILE_TIME_VALUE, UNUSED_EXPRESSION!>'\'<!>
} }
@@ -7,16 +7,16 @@ fun demo() {
fun buzz(f : () -> Any?) : Int = 1 fun buzz(f : () -> Any?) : Int = 1
val sdf = 1 val sdf = 1
val foo = 3; val foo = 3;
"$abc" <!UNUSED_EXPRESSION!>"$abc"<!>
"$" <!UNUSED_EXPRESSION!>"$"<!>
"$.$.asdf$\t" <!UNUSED_EXPRESSION!>"$.$.asdf$\t"<!>
"asd\$" <!UNUSED_EXPRESSION!>"asd\$"<!>
"asd$a<!ILLEGAL_ESCAPE_SEQUENCE!>\x<!>" <!UNUSED_EXPRESSION!>"asd$a<!ILLEGAL_ESCAPE_SEQUENCE!>\x<!>"<!>
"asd$a$asd$ $<!UNRESOLVED_REFERENCE!>xxx<!>" <!UNUSED_EXPRESSION!>"asd$a$asd$ $<!UNRESOLVED_REFERENCE!>xxx<!>"<!>
"fosdfasdo${1 + bar + 100}}sdsdfgdsfsdf" <!UNUSED_EXPRESSION!>"fosdfasdo${1 + bar + 100}}sdsdfgdsfsdf"<!>
"foo${bar + map {foo}}sdfsdf" <!UNUSED_EXPRESSION!>"foo${bar + map {foo}}sdfsdf"<!>
"foo${bar + map { "foo" }}sdfsdf" <!UNUSED_EXPRESSION!>"foo${bar + map { "foo" }}sdfsdf"<!>
"foo${bar + map { <!UNUSED_EXPRESSION!>"foo${bar + map {
"foo$sdf${ buzz{}}" }}sdfsdf" "foo$sdf${ buzz{}}" }}sdfsdf"<!>
"a<!ILLEGAL_ESCAPE_SEQUENCE!>\u<!> <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>0 <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>00 <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>000 \u0000 \u0AaA <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>0AAz.length( ) + \u0022b" <!UNUSED_EXPRESSION!>"a<!ILLEGAL_ESCAPE_SEQUENCE!>\u<!> <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>0 <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>00 <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>000 \u0000 \u0AaA <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>0AAz.length( ) + \u0022b"<!>
} }
@@ -110,7 +110,7 @@ fun t7() : Int {
<!UNREACHABLE_CODE!>2<!> <!UNREACHABLE_CODE!>2<!>
} }
catch (e : Any) { catch (e : Any) {
2 <!UNUSED_EXPRESSION!>2<!>
} }
return 1 // this is OK, like in Java return 1 // this is OK, like in Java
} }
@@ -145,8 +145,8 @@ fun failtest(<!UNUSED_PARAMETER!>a<!> : Int) : Int {
} }
fun foo(a : Nothing) : Unit { fun foo(a : Nothing) : Unit {
1 <!UNUSED_EXPRESSION!>1<!>
a <!UNUSED_EXPRESSION!>a<!>
<!UNREACHABLE_CODE!>2<!> <!UNREACHABLE_CODE!>2<!>
} }
@@ -62,7 +62,7 @@ fun testCoercionToUnit() {
when(i) { when(i) {
is 1 -> { is 1 -> {
val d = 34 val d = 34
"1" <!UNUSED_EXPRESSION!>"1"<!>
doSmth(d) doSmth(d)
} }
@@ -22,11 +22,11 @@ fun A.plus(<!UNUSED_PARAMETER!>a<!> : Any) {
1.foo() 1.foo()
true.<!NONE_APPLICABLE!>foo<!>() true.<!NONE_APPLICABLE!>foo<!>()
1 <!UNUSED_EXPRESSION!>1<!>
} }
fun A.plus(<!UNUSED_PARAMETER!>a<!> : Int) { fun A.plus(<!UNUSED_PARAMETER!>a<!> : Int) {
1 <!UNUSED_EXPRESSION!>1<!>
} }
fun <T> T.minus(<!UNUSED_PARAMETER!>t<!> : T) : Int = 1 fun <T> T.minus(<!UNUSED_PARAMETER!>t<!> : T) : Int = 1
@@ -73,4 +73,4 @@ import outer.*
c<!UNNECESSARY_SAFE_CALL!>?.<!>equals2(null) c<!UNNECESSARY_SAFE_CALL!>?.<!>equals2(null)
if (command == null) 1 if (command == null) 1
} }
@@ -116,12 +116,12 @@ fun f13(a : A?) {
} }
if (!(a is val c is B) || !(a is val x is C)) { if (!(a is val c is B) || !(a is val x is C)) {
<!UNRESOLVED_REFERENCE!>x<!> <!UNRESOLVED_REFERENCE, UNUSED_EXPRESSION!>x<!>
<!UNRESOLVED_REFERENCE!>c<!> <!UNRESOLVED_REFERENCE, UNUSED_EXPRESSION!>c<!>
} }
else { else {
<!UNRESOLVED_REFERENCE!>x<!> <!UNRESOLVED_REFERENCE, UNUSED_EXPRESSION!>x<!>
<!UNRESOLVED_REFERENCE!>c<!> <!UNRESOLVED_REFERENCE, UNUSED_EXPRESSION!>c<!>
} }
if (!(a is val c is B) || !(a is val c is C)) { if (!(a is val c is B) || !(a is val c is C)) {
@@ -1,16 +1,16 @@
// KT-306 Ambiguity when different this's have same-looking functions // KT-306 Ambiguity when different this's have same-looking functions
fun test() { fun test() {
{Foo.() -> <!UNUSED_FUNCTION_LITERAL!>{Foo.() ->
bar(); bar();
{Barr.() -> {Barr.() ->
this.bar() this.bar()
bar() bar()
} }
} }<!>
{Barr.() -> <!UNUSED_FUNCTION_LITERAL!>{Barr.() ->
bar() bar()
} }<!>
} }
class Foo { class Foo {
@@ -19,4 +19,4 @@ class Foo {
class Barr { class Barr {
fun bar() {} fun bar() {}
} }
@@ -1,7 +1,7 @@
package kt402 package kt402
fun getTypeChecker() : (Any)->Boolean { fun getTypeChecker() : (Any)->Boolean {
<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>{ (a : Any) -> a is <!UNRESOLVED_REFERENCE!>T<!> }<!> // reports unsupported <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY, UNUSED_FUNCTION_LITERAL!>{ (a : Any) -> a is <!UNRESOLVED_REFERENCE!>T<!> }<!> // reports unsupported
} }
fun f() : (Any) -> Boolean { fun f() : (Any) -> Boolean {
return { (a : Any) -> a is String } return { (a : Any) -> a is String }
@@ -7,5 +7,5 @@ fun aaa() =
fun bbb() { fun bbb() {
aaa() aaa()
1 // Stupid error: unreachable code <!UNUSED_EXPRESSION!>1<!> // Stupid error: unreachable code
} }
@@ -1,3 +1,3 @@
fun <T> T.mustBe(t : T) { fun <T> T.mustBe(t : T) {
"$this must be$<!SYNTAX!>as<!>$t" <!UNUSED_EXPRESSION!>"$this must be$<!SYNTAX!>as<!>$t"<!>
} }
@@ -1,7 +1,7 @@
fun f(<!UNUSED_PARAMETER!>i<!>: Int) { fun f(<!UNUSED_PARAMETER!>i<!>: Int) {
for (j in 1..100) { for (j in 1..100) {
{ <!UNUSED_FUNCTION_LITERAL!>{
var <!NAME_SHADOWING!>i<!> = 12 var <!NAME_SHADOWING!>i<!> = 12
} }<!>
} }
} }
@@ -1,7 +1,7 @@
fun ff(): Int { fun ff(): Int {
var i = 1 var i = 1
{ <!UNUSED_FUNCTION_LITERAL!>{
val <!NAME_SHADOWING!>i<!> = 2 val <!NAME_SHADOWING!>i<!> = 2
} }<!>
return i return i
} }
@@ -1,5 +1,5 @@
fun f(): Int { fun f(): Int {
var i = 17 var i = 17
{ (): Unit -> var <!NAME_SHADOWING!>i<!> = 18 } <!UNUSED_FUNCTION_LITERAL!>{ (): Unit -> var <!NAME_SHADOWING!>i<!> = 18 }<!>
return i return i
} }
@@ -1,5 +1,5 @@
fun ff(): Int { fun ff(): Int {
var i = 1 var i = 1
{ (i: Int) -> i } <!UNUSED_FUNCTION_LITERAL!>{ (i: Int) -> i }<!>
return i return i
} }
+2 -2
View File
@@ -18,11 +18,11 @@ fun A.plus(<warning>a</warning> : Any) {
1.foo() 1.foo()
true.<error>foo</error>() true.<error>foo</error>()
1 <warning>1</warning>
} }
fun A.plus(<warning>a</warning> : Int) { fun A.plus(<warning>a</warning> : Int) {
1 <warning>1</warning>
} }
fun <T> T.minus(<warning>t</warning> : T) : Int = 1 fun <T> T.minus(<warning>t</warning> : T) : Int = 1
+14 -12
View File
@@ -7,15 +7,17 @@ fun demo() {
fun buzz(f : () -> Any?) : Int = 1 fun buzz(f : () -> Any?) : Int = 1
val sdf = 1 val sdf = 1
val foo = 3; val foo = 3;
"$abc" use("$abc")
"$" use("$")
"$.$.asdf$\t" use("$.$.asdf$\t")
"asd\$" use("asd\$")
"asd$a<error>\x</error>" use("asd$a<error>\x</error>")
"asd$a$asd$ $<error>xxx</error>" use("asd$a$asd$ $<error>xxx</error>")
"fosdfasdo${1 + bar + 100}}sdsdfgdsfsdf" use("fosdfasdo${1 + bar + 100}}sdsdfgdsfsdf")
"foo${bar + map {foo}}sdfsdf" use("foo${bar + map {foo}}sdfsdf")
"foo${bar + map { "foo" }}sdfsdf" use("foo${bar + map { "foo" }}sdfsdf")
"foo${bar + map { use("foo${bar + map {
"foo$sdf${ buzz{}}" }}sdfsdf" "foo$sdf${ buzz{}}" }}sdfsdf")
} }
fun use(<warning>s</warning>: String) {}
+3 -3
View File
@@ -108,7 +108,7 @@ fun t7() : Int {
<error>2</error> <error>2</error>
} }
catch (e : Any) { catch (e : Any) {
2 <warning>2</warning>
} }
return 1 // this is OK, like in Java return 1 // this is OK, like in Java
} }
@@ -143,8 +143,8 @@ fun failtest(<warning>a</warning> : Int) : Int {
} }
fun foo(a : Nothing) : Unit { fun foo(a : Nothing) : Unit {
1 <warning>1</warning>
a <warning>a</warning>
<error>2</error> <error>2</error>
} }
+4
View File
@@ -65,3 +65,7 @@ Add iterated elements to java.util.TreeSet
*/ */
inline fun <T> Iterator<T>.toTreeSet() = to(TreeSet<T>()) inline fun <T> Iterator<T>.toTreeSet() = to(TreeSet<T>())
/*
Run function f
*/
inline fun <T> run(f: () -> T) = f()