Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ANN: Update inspections for Type Aliases #7976

Merged
merged 1 commit into from
Nov 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 31 additions & 4 deletions src/main/kotlin/org/rust/ide/annotator/RsErrorAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ class RsErrorAnnotator : AnnotatorBase(), HighlightRangeExtension {
if (parent is RsImplItem ||
parent is RsForeignModItem ||
parent is RsEnumVariant ||
isInTrait(vis) ||
isInTraitImpl(vis) ||
isInEnumVariantField(vis)
) {
Expand Down Expand Up @@ -948,6 +949,31 @@ class RsErrorAnnotator : AnnotatorBase(), HighlightRangeExtension {
}

private fun checkTypeAlias(holder: RsAnnotationHolder, ta: RsTypeAlias) {
when (val owner = ta.owner) {
is RsAbstractableOwner.Trait -> {
ta.typeReference?.let { ASSOCIATED_TYPE_DEFAULTS.check(holder, it, "associated type defaults") }
val typeParameterList = ta.typeParameterList
if (typeParameterList != null && typeParameterList.genericParameterList.isNotEmpty()) {
GENERIC_ASSOCIATED_TYPES.check(holder, typeParameterList, "generic associated types")
}
ta.whereClause?.let { GENERIC_ASSOCIATED_TYPES.check(holder, it, "where clauses on associated types") }
}
is RsAbstractableOwner.Impl -> {
if (owner.isInherent) {
INHERENT_ASSOCIATED_TYPES.check(holder, ta, "inherent associated types")
}
val typeParameterList = ta.typeParameterList
if (typeParameterList != null && typeParameterList.genericParameterList.isNotEmpty()) {
GENERIC_ASSOCIATED_TYPES.check(holder, typeParameterList, "generic associated types")
}
ta.whereClause?.let { GENERIC_ASSOCIATED_TYPES.check(holder, it, "where clauses on associated types") }
}
is RsAbstractableOwner.Foreign -> {
EXTERN_TYPES.check(holder, ta, "extern types")
}
else -> {}
}

checkDuplicates(holder, ta)
}

Expand Down Expand Up @@ -1329,10 +1355,11 @@ class RsErrorAnnotator : AnnotatorBase(), HighlightRangeExtension {
}
}

private fun isInTraitImpl(o: RsVis): Boolean {
val impl = o.parent?.parent?.parent
return impl is RsImplItem && impl.traitRef != null
}
private fun isInTrait(o: RsVis): Boolean =
(o.parent as? RsAbstractable)?.owner is RsAbstractableOwner.Trait

private fun isInTraitImpl(o: RsVis): Boolean =
(o.parent as? RsAbstractable)?.owner?.isTraitImpl == true

private fun isInEnumVariantField(o: RsVis): Boolean {
val field = o.parent as? RsNamedFieldDecl
Expand Down
26 changes: 13 additions & 13 deletions src/main/kotlin/org/rust/ide/annotator/RsSyntaxErrorsAnnotator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -123,26 +123,26 @@ private fun checkTypeAlias(holder: AnnotationHolder, ta: RsTypeAlias) {
when (val owner = ta.owner) {
is RsAbstractableOwner.Free -> {
deny(ta.default, holder, "$title cannot have the `default` qualifier")
deny(ta.typeParamBounds, holder, "$title cannot have type parameter bounds")
require(ta.typeReference, holder, "Aliased type must be provided for type `${ta.identifier.text}`", ta)
deny(ta.typeParamBounds, holder, "Bounds on $title have no effect")
require(ta.typeReference, holder, "$title should have a body`", ta)
}
is RsAbstractableOwner.Trait -> {
deny(ta.default, holder, "$title cannot have the `default` qualifier")
deny(ta.vis, holder, "$title cannot have the `pub` qualifier")
deny(ta.typeParameterList, holder, "$title cannot have generic parameters")
deny(ta.whereClause, holder, "$title cannot have `where` clause")
}
is RsAbstractableOwner.Impl -> {
if (owner.impl.`for` == null) {
RsDiagnostic.AssociatedTypeInInherentImplError(ta).addToHolder(holder)
} else {
deny(ta.typeParameterList, holder, "$title cannot have generic parameters")
deny(ta.whereClause, holder, "$title cannot have `where` clause")
deny(ta.typeParamBounds, holder, "$title cannot have type parameter bounds")
require(ta.typeReference, holder, "Aliased type must be provided for type `${ta.identifier.text}`", ta)
if (owner.isInherent) {
deny(ta.default, holder, "$title cannot have the `default` qualifier")
}
deny(ta.typeParamBounds, holder, "Bounds on $title have no effect")
require(ta.typeReference, holder, "$title should have a body", ta)
}
RsAbstractableOwner.Foreign -> {
deny(ta.default, holder, "$title cannot have the `default` qualifier")
deny(ta.typeParameterList, holder, "$title cannot have generic parameters")
deny(ta.whereClause, holder, "$title cannot have `where` clause")
deny(ta.typeParamBounds, holder, "Bounds on $title have no effect")
deny(ta.typeReference, holder, "$title cannot have a body", ta)
}
RsAbstractableOwner.Foreign -> Unit
}
}

Expand Down
77 changes: 77 additions & 0 deletions src/test/kotlin/org/rust/ide/annotator/RsErrorAnnotatorTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4456,4 +4456,81 @@ class RsErrorAnnotatorTest : RsAnnotatorTestBase(RsErrorAnnotator::class) {
}
}
""")

@MockRustcVersion("1.23.0")
fun `test extern types E0658 1`() = checkErrors("""
extern { <error descr="extern types is experimental [E0658]">type ItemForeign;</error> }
""")

@MockRustcVersion("1.23.0-nightly")
fun `test extern types E0658 2`() = checkErrors("""
#![feature(extern_types)]
extern { type ItemForeign; }
""")

@MockRustcVersion("1.23.0")
fun `test generic associated types E0658 1`() = checkErrors("""
struct S;
type ItemFree<'a> where 'a : 'static = S;
impl S { <error>type Item<error descr="generic associated types is experimental [E0658]"><'a></error> <error descr="where clauses on associated types is experimental [E0658]">where 'a : 'static</error> = S;</error> }
trait T { type Item<error descr="generic associated types is experimental [E0658]"><'a></error> <error descr="where clauses on associated types is experimental [E0658]">where 'a : 'static</error>; }
impl T for S { type Item<error descr="generic associated types is experimental [E0658]"><'a></error> <error descr="where clauses on associated types is experimental [E0658]">where 'a : 'static</error> = S; }
""")

@MockRustcVersion("1.23.0-nightly")
fun `test generic associated types E0658 2`() = checkErrors("""
#![feature(generic_associated_types)]
struct S;
type ItemFree<'a> where 'a : 'static = S;
impl S { <error>type Item<'a> where 'a : 'static = S;</error> }
trait T { type Item<'a> where 'a : 'static; }
impl T for S { type Item<'a> where 'a : 'static = S; }
""")

fun `test generic associated types E0658 3`() = checkErrors("""
struct S;
type ItemFree<>;
impl S { type Item<>; }
trait T { type Item<>; }
impl T for S { type Item<>; }
""")

@MockRustcVersion("1.52.0")
fun `test inherent associated types E0658 1`() = checkErrors("""
impl S { <error descr="inherent associated types is experimental [E0658]">type Item;</error> }
""")

@MockRustcVersion("1.52.0-nightly")
fun `test inherent associated types E0658 2`() = checkErrors("""
#![feature(inherent_associated_types)]
impl S { type Item; }
""")

@MockRustcVersion("1.2.0")
fun `test associated type defaults E0658 1`() = checkErrors("""
struct S;
type ItemFree = S;
impl S { <error>type Item = S;</error> }
trait T { type Item = <error descr="associated type defaults is experimental [E0658]">S</error>; }
impl T for S { type Item = S; }
""")

@MockRustcVersion("1.2.0-nightly")
fun `test associated type defaults E0658 2`() = checkErrors("""
#![feature(associated_type_defaults)]
struct S;
type ItemFree = S;
impl S { <error>type Item = S;</error> }
trait T { type Item = S; }
impl T for S { type Item = S; }
""")

fun `test unnecessary visibility qualifier E0449`() = checkErrors("""
struct S;
pub type ItemFree = S;
impl S { pub type Item = S; }
trait T { <error descr="Unnecessary visibility qualifier [E0449]">pub</error> type Item; }
impl T for S { <error descr="Unnecessary visibility qualifier [E0449]">pub</error> type Item = S; }
extern { pub type ItemForeign; }
""")
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ class RsSyntaxErrorsAnnotatorTest : RsAnnotatorTestBase(RsSyntaxErrorsAnnotator:
type SizedMaybe<T> where T: Sized = Option<T>;

<error descr="Type `DefBool` cannot have the `default` qualifier">default</error> type DefBool = bool;
<error descr="Aliased type must be provided for type `Unknown`">type Unknown;</error>
type Show<error descr="Type `Show` cannot have type parameter bounds">: Display</error> = u32;
<error descr="Type `Unknown` should have a body`">type Unknown;</error>
type Show<error descr="Bounds on Type `Show` have no effect">: Display</error> = u32;
""")

fun `test type alias in trait`() = checkErrors("""
Expand All @@ -119,14 +119,15 @@ class RsSyntaxErrorsAnnotatorTest : RsAnnotatorTestBase(RsSyntaxErrorsAnnotator:
type Show: Display;

<error descr="Type `DefSize` cannot have the `default` qualifier">default</error> type DefSize = isize;
<error descr="Type `PubType` cannot have the `pub` qualifier">pub</error> type PubType;
type GenType<error descr="Type `GenType` cannot have generic parameters"><T></error> = Option<T>;
type WhereType <error descr="Type `WhereType` cannot have `where` clause">where T: Sized</error> = f64;
pub type PubType;
type GenType<T> = Option<T>;
type WhereType where T: Sized = f64;
}
""")

fun `test type alias in trait impl`() = checkErrors("""
trait Vehicle {
type Unknown;
type Engine;
type Control;
type Lock;
Expand All @@ -136,15 +137,42 @@ class RsSyntaxErrorsAnnotatorTest : RsAnnotatorTestBase(RsSyntaxErrorsAnnotator:
}
struct NumericVehicle<T> { foo: T }
impl<T> Vehicle for NumericVehicle<T> {
<error descr="Type `Unknown` should have a body">type Unknown;</error>
type Engine = u32;
default type Control = isize;
type Lock<error descr="Type `Lock` cannot have generic parameters"><T></error> = Option<T>;
type Cage<error descr="Type `Cage` cannot have type parameter bounds">: Sized</error> = f64;
type Insurance <error descr="Type `Insurance` cannot have `where` clause">where T: Sized</error> = i8;
<error descr="Aliased type must be provided for type `Driver`">type Driver;</error>
type Lock<T> = Option<T>;
type Cage<error descr="Bounds on Type `Cage` have no effect">: Sized</error> = f64;
type Insurance where T: Sized = i8;
<error descr="Type `Driver` should have a body">type Driver;</error>
}
""")

fun `test type alias in inheret impl`() = checkErrors("""
struct S;
impl S {
<error descr="Type `Unknown` should have a body">type Unknown;</error>
type Engine = u32;
<error descr="Type `Control` cannot have the `default` qualifier">default</error> type Control = isize;
type Lock<T> = Option<T>;
type Cage<error descr="Bounds on Type `Cage` have no effect">: Sized</error> = f64;
type Insurance where T: Sized = i8;
<error descr="Type `Driver` should have a body">type Driver;</error>
}
""")

fun `test type alias in extern block`() = checkErrors("""
extern {
<error descr="Type `Int` cannot have a body">type Int = i32;</error>
<error descr="Type `UInt` cannot have a body">pub type UInt = u32;</error>
<error descr="Type `Maybe` cannot have a body">type Maybe<error descr="Type `Maybe` cannot have generic parameters"><T></error> = Option<T>;</error>
<error descr="Type `SizedMaybe` cannot have a body">type SizedMaybe<error descr="Type `SizedMaybe` cannot have generic parameters"><T></error> <error descr="Type `SizedMaybe` cannot have `where` clause">where T: Sized</error> = Option<T>;</error>

<error descr="Type `DefBool` cannot have a body"><error descr="Type `DefBool` cannot have the `default` qualifier">default</error> type DefBool = bool;</error>
type Unknown;
<error descr="Type `Show` cannot have a body">type Show<error descr="Bounds on Type `Show` have no effect">: Display</error> = u32;</error>
}
""")

fun `test const free`() = checkErrors("""
const FOO: u32 = 42;
pub const PUB_FOO: u32 = 41;
Expand Down Expand Up @@ -208,13 +236,6 @@ class RsSyntaxErrorsAnnotatorTest : RsAnnotatorTestBase(RsSyntaxErrorsAnnotator:
<error>default</error> fn two_errors(<error>u8</error>, a: i16) {}
""")

fun `test E0202 type alias in inherent impl`() = checkErrors("""
struct Foo;
impl Foo {
<error descr="Associated types are not allowed in inherent impls [E0202]">type Long = i64;</error>
}
""")

fun `test add parameter_name fix`() = checkFixByText("Add dummy parameter name", """
trait Display {
fn fmt(&self, <warning>F/*caret*/</warning>);
Expand Down