Skip to content

Commit

Permalink
TY: Improve autocompletion for primitive types
Browse files Browse the repository at this point in the history
In Rust primitive types are only allowed a single
impl block that must be annotated with lang attribute
We do not enforce this yet an accept user defined impl blocks.

See rust-lang/rust#23104
and the error code E0390.

The primitive type bool does not have an impl block / lang attribute.

TODO:
* Clean up a lot
* Combine the 2 find methods
* Missing primitive types: slice, const_ptr, mut_ptr
* Autocompletions on u8, i8, ... do not work
  as they are implemented by a macro
* What fingerprint/string should we use for primitive types
  (to avoid overlap with user defined types)
* Incomplete tests
  • Loading branch information
kumbayo committed Feb 22, 2017
1 parent f9d0145 commit 8370cc4
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/main/kotlin/org/rust/lang/core/resolve/ResolveEngine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,8 @@ private fun lexicalDeclarations(
sequenceOf(
itemDeclarations(scope, true, context),
injectedCrates(scope),
preludeSymbols(scope.module, context)
preludeSymbols(scope.module, context),
emptySequence()//TODO inject primitive types somewhere around here maybe???
).flatten()

is RsModItem ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import org.rust.lang.core.psi.RsStructOrEnumItemElement
import org.rust.lang.core.psi.impl.mixin.isAssocFn
import org.rust.lang.core.stubs.RsFileStub
import org.rust.lang.core.stubs.RsImplItemStub
import org.rust.lang.core.types.types.RustStructOrEnumTypeBase
import org.rust.lang.core.types.RustType
import org.rust.lang.core.types.RustTypeFingerprint
import org.rust.lang.core.types.type
import org.rust.lang.core.types.types.RustPrimitiveType
import org.rust.lang.core.types.types.RustStructOrEnumTypeBase


object RsImplIndex {
Expand All @@ -32,6 +33,8 @@ object RsImplIndex {
fun findImplsFor(target: RustType, project: Project): Sequence<RsImplItem> {
val inherentImpls = if (target is RustStructOrEnumTypeBase)
InherentImpls.find(target.item)
else if (target is RustPrimitiveType)
InherentImpls.find(target, project);
else
emptySequence()

Expand Down Expand Up @@ -98,6 +101,22 @@ object RsImplIndex {
}
}

fun find(target: RustPrimitiveType, project: Project): Sequence<RsImplItem> {
val fingerprint = RustTypeFingerprint.create(target)
?: return emptySequence()

return StubIndex.getElements(
InherentImpls.KEY,
fingerprint,
project,
GlobalSearchScope.allScope(project),
RsImplItem::class.java
).asSequence().filter { impl ->
val ty = impl.typeReference?.type
ty is RustPrimitiveType && ty == target
}
}

fun index(stub: RsImplItemStub, sink: IndexSink) {
val type = stub.psi.typeReference ?: return
val key = RustTypeFingerprint.create(type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package org.rust.lang.core.types
import org.rust.lang.core.psi.RsBaseType
import org.rust.lang.core.psi.RsRefLikeType
import org.rust.lang.core.psi.RsTypeReference
import org.rust.lang.core.types.types.RustEnumType
import org.rust.lang.core.types.types.RustReferenceType
import org.rust.lang.core.types.types.RustStructType
import org.rust.lang.core.types.types.*
import java.io.DataInput
import java.io.DataOutput

Expand All @@ -23,6 +21,7 @@ data class RustTypeFingerprint private constructor(
is RustStructType -> type.item.name?.let(::RustTypeFingerprint)
is RustEnumType -> type.item.name?.let(::RustTypeFingerprint)
is RustReferenceType -> create(type.referenced)
is RustPrimitiveType -> type.toString().let(::RustTypeFingerprint)
else -> null
}
}
Expand Down
64 changes: 64 additions & 0 deletions src/test/kotlin/org/rust/lang/core/resolve/RsStdlibResolveTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,68 @@ class RsStdlibResolveTest : RsResolveTestBase() {
fn main() { use self::m::Some; }
//^ unresolved
""")

fun testChar() = stubOnlyResolve("""
//- main.rs
fn main() { 'Z'.is_lowercase(); }
//^ ...libstd_unicode/char.rs
""")

fun testCharUFCS() = expect<IllegalStateException> { stubOnlyResolve ("""
//- main.rs
fn main() { char.is_lowercase('Z'); }
//^ ...libstd_unicode/char.rs
""")
}

fun testStr() = stubOnlyResolve("""
//- main.rs
fn main() { "Z".to_uppercase(); }
//^ ...libcollections/str.rs
""")

fun testStrUFCS() = expect<IllegalStateException> { stubOnlyResolve ("""
//- main.rs
fn main() { str::to_uppercase("Z"); }
//^ ...libcollections/str.rs
""")
}

fun testF32() = stubOnlyResolve("""
//- main.rs
fn main() { 0.0f32.sqrt(); }
//^ ...libstd/f32.rs
""")

fun testF32UFCS() = expect<IllegalStateException> { stubOnlyResolve ("""
//- main.rs
fn main() { f32::sqrt(0.0f32); }
//^ ...libstd/f32.rs
""")
}

fun testF32UFCS2() = expect<IllegalStateException> { stubOnlyResolve ("""
//- main.rs
fn main() { <f32>::sqrt(0.0f32); }
//^ ...libstd/f32.rs
""")
}

fun testF64() = stubOnlyResolve("""
//- main.rs
fn main() { 0.0f64.sqrt(); }
//^ ...libstd/f64.rs
""")

fun testF64UFCS() = expect<IllegalStateException> { stubOnlyResolve ("""
//- main.rs
fn main() { f64::sqrt(0.0f64); }
//^ ...libstd/f64.rs
""")
}

//TODO add tests for:
// slice, const_ptr, mut_ptr
// u8, u16, u32, u64, u128, usize
// i8, i16, i32, i64, i128, isize
}

0 comments on commit 8370cc4

Please sign in to comment.