Skip to content

Commit

Permalink
INSP: add support for trait refs in RsWrongTypeArgumentsNumberInspection
Browse files Browse the repository at this point in the history
  • Loading branch information
Kobzol committed Jul 28, 2020
1 parent d55eb53 commit 391fc33
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,29 @@ class RsWrongTypeArgumentsNumberInspection : RsLocalInspectionTool() {
override fun buildVisitor(holder: RsProblemsHolder, isOnTheFly: Boolean) =
object : RsVisitor() {
override fun visitBaseType(type: RsBaseType) {
// Don't apply generic declaration checks to Fn-traits and `Self`
if (type.path?.valueParameterList != null) return
if (type.path?.cself != null) return
checkMethod(holder, type)
if (!isPathValid(type.path)) return
checkTypeArguments(holder, type)
}

override fun visitCallExpr(o: RsCallExpr) = checkMethod(holder, o)
override fun visitMethodCall(o: RsMethodCall) = checkMethod(holder, o)
override fun visitTraitRef(trait: RsTraitRef) {
if (!isPathValid(trait.path)) return
checkTypeArguments(holder, trait)
}

override fun visitCallExpr(o: RsCallExpr) = checkTypeArguments(holder, o)
override fun visitMethodCall(o: RsMethodCall) = checkTypeArguments(holder, o)
}

private fun checkMethod(holder: RsProblemsHolder, o: RsElement) {
// Don't apply generic declaration checks to Fn-traits and `Self`
private fun isPathValid(path: RsPath?): Boolean = path?.valueParameterList == null && path?.cself == null

private fun checkTypeArguments(holder: RsProblemsHolder, o: RsElement) {
val (actualArguments, declaration) = when (o) {
is RsMethodCall -> o.typeArgumentList to o.reference.resolve()
is RsCallExpr ->
(o.expr as? RsPathExpr)?.path?.typeArgumentList to (o.expr as? RsPathExpr)?.path?.reference?.resolve()
is RsBaseType -> o.path?.typeArgumentList to o.path?.reference?.resolve()
is RsTraitRef -> o.path.typeArgumentList to o.path.reference?.resolve()
else -> return
}
if (declaration !is RsGenericDeclaration) return
Expand All @@ -48,7 +55,7 @@ class RsWrongTypeArgumentsNumberInspection : RsLocalInspectionTool() {
if (actualArgs == expectedTotalParams) return

val errorText = when (o) {
is RsBaseType -> checkBaseType(actualArgs, expectedRequiredParams, expectedTotalParams)
is RsBaseType, is RsTraitRef -> checkTypeReference(actualArgs, expectedRequiredParams, expectedTotalParams)
is RsMethodCall, is RsCallExpr -> checkFunctionCall(actualArgs, expectedRequiredParams, expectedTotalParams)
else -> null
} ?: return
Expand All @@ -60,7 +67,7 @@ class RsWrongTypeArgumentsNumberInspection : RsLocalInspectionTool() {
}
}

private fun checkBaseType(actualArgs: Int, expectedRequiredParams: Int, expectedTotalParams: Int): String? {
private fun checkTypeReference(actualArgs: Int, expectedRequiredParams: Int, expectedTotalParams: Int): String? {
return when {
actualArgs > expectedTotalParams ->
if (expectedRequiredParams != expectedTotalParams) "at most $expectedTotalParams" else "$expectedTotalParams"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@

package org.rust.ide.inspections

import org.rust.ProjectDescriptor
import org.rust.WithStdlibRustProjectDescriptor

class RsWrongTypeArgumentsNumberInspectionTest : RsInspectionsTestBase(RsWrongTypeArgumentsNumberInspection::class) {
@ProjectDescriptor(WithStdlibRustProjectDescriptor::class)
fun `test ignores Fn-traits`() = checkByText("""
fn foo(f: &mut FnOnce(u32) -> bool) {} // No annotation despite the fact that FnOnce has a type parameter
""")

@ProjectDescriptor(WithStdlibRustProjectDescriptor::class)
fun `test ignores Fn-traits in type bounds`() = checkByText("""
fn foo<F: Fn(&str) -> u32>() {}
""")

fun `test ignores Self type`() = checkByText("""
struct Foo<T> { t: T }
impl<T> Foo<T> {
Expand Down Expand Up @@ -188,4 +197,16 @@ class RsWrongTypeArgumentsNumberInspectionTest : RsInspectionsTestBase(RsWrongTy
err1: Foo<u32, i32>,
}
""")

fun `test dyn trait`() = checkByText("""
trait Trait<A> {}
fn foo() {
let x: &dyn <error descr="Wrong number of type arguments: expected 1, found 0 [E0107]">Trait<></error>;
}
""")

fun `test impl trait`() = checkByText("""
trait Trait<A> {}
fn foo(_: impl <error descr="Wrong number of type arguments: expected 1, found 0 [E0107]">Trait<></error>) {}
""")
}

0 comments on commit 391fc33

Please sign in to comment.