Unnamed repository; edit this file 'description' to name the repository.
Use lang item resolution instead of known paths
Lukas Wirth 2023-01-22
parent 1535881 · commit f8ed4d7
-rw-r--r--crates/hir-def/src/lib.rs1
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs41
-rw-r--r--crates/hir-ty/src/infer.rs52
-rw-r--r--crates/hir-ty/src/tests/traits.rs138
-rw-r--r--crates/ide-completion/src/tests/flyimport.rs6
-rw-r--r--crates/test-utils/src/minicore.rs8
6 files changed, 66 insertions, 180 deletions
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 9e4e0dcc96..8eae2e92f4 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -634,6 +634,7 @@ pub trait Lookup {
pub trait HasModule {
fn module(&self, db: &dyn db::DefDatabase) -> ModuleId;
}
+
impl HasModule for ItemContainerId {
fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
match *self {
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index c8df4c796e..3286dcb5af 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -5,7 +5,9 @@
use std::fmt;
use std::sync::Arc;
-use hir_def::{path::path, resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule};
+use hir_def::lang_item::LangItem;
+use hir_def::{resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule};
+use hir_def::{ItemContainerId, Lookup};
use hir_expand::name;
use itertools::Either;
use itertools::Itertools;
@@ -245,26 +247,25 @@ struct FilterMapNextChecker {
impl FilterMapNextChecker {
fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self {
// Find and store the FunctionIds for Iterator::filter_map and Iterator::next
- let iterator_path = path![core::iter::Iterator];
- let mut filter_map_function_id = None;
- let mut next_function_id = None;
-
- if let Some(iterator_trait_id) = resolver.resolve_known_trait(db.upcast(), &iterator_path) {
- let iterator_trait_items = &db.trait_data(iterator_trait_id).items;
- for item in iterator_trait_items.iter() {
- if let (name, AssocItemId::FunctionId(id)) = item {
- if *name == name![filter_map] {
- filter_map_function_id = Some(*id);
+ let (next_function_id, filter_map_function_id) = match db
+ .lang_item(resolver.krate(), LangItem::IteratorNext)
+ .and_then(|it| it.as_function())
+ {
+ Some(next_function_id) => (
+ Some(next_function_id),
+ match next_function_id.lookup(db.upcast()).container {
+ ItemContainerId::TraitId(iterator_trait_id) => {
+ let iterator_trait_items = &db.trait_data(iterator_trait_id).items;
+ iterator_trait_items.iter().find_map(|(name, it)| match it {
+ &AssocItemId::FunctionId(id) if *name == name![filter_map] => Some(id),
+ _ => None,
+ })
}
- if *name == name![next] {
- next_function_id = Some(*id);
- }
- }
- if filter_map_function_id.is_some() && next_function_id.is_some() {
- break;
- }
- }
- }
+ _ => None,
+ },
+ ),
+ None => (None, None),
+ };
Self { filter_map_function_id, next_function_id, prev_filter_map_expr_id: None }
}
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index d06b22fff9..4402c75947 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -24,7 +24,7 @@ use hir_def::{
expr::{BindingAnnotation, ExprId, ExprOrPatId, PatId},
lang_item::{LangItem, LangItemTarget},
layout::Integer,
- path::{path, Path},
+ path::Path,
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
type_ref::TypeRef,
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule,
@@ -923,26 +923,24 @@ impl<'a> InferenceContext<'a> {
}
fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
- let path = path![core::iter::IntoIterator];
- let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
+ let ItemContainerId::TraitId(trait_) = self.resolve_lang_item(LangItem::IntoIterIntoIter)?
+ .as_function()?
+ .lookup(self.db.upcast()).container
+ else { return None };
self.db.trait_data(trait_).associated_type_by_name(&name![IntoIter])
}
fn resolve_iterator_item(&self) -> Option<TypeAliasId> {
- let path = path![core::iter::Iterator];
- let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
+ let ItemContainerId::TraitId(trait_) = self.resolve_lang_item(LangItem::IteratorNext)?
+ .as_function()?
+ .lookup(self.db.upcast()).container
+ else { return None };
self.db.trait_data(trait_).associated_type_by_name(&name![Item])
}
fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
- // FIXME resolve via lang_item once try v2 is stable
- let path = path![core::ops::Try];
- let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
- let trait_data = self.db.trait_data(trait_);
- trait_data
- // FIXME remove once try v2 is stable
- .associated_type_by_name(&name![Ok])
- .or_else(|| trait_data.associated_type_by_name(&name![Output]))
+ let trait_ = self.resolve_lang_item(LangItem::Try)?.as_trait()?;
+ self.db.trait_data(trait_).associated_type_by_name(&name![Output])
}
fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
@@ -956,10 +954,12 @@ impl<'a> InferenceContext<'a> {
}
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
- let trait_ = self
- .resolver
- .resolve_known_trait(self.db.upcast(), &path![core::future::IntoFuture])
- .or_else(|| self.resolve_lang_item(LangItem::Future)?.as_trait())?;
+ let ItemContainerId::TraitId(trait_) = self
+ .resolve_lang_item(LangItem::IntoFutureIntoFuture)?
+ .as_function()?
+ .lookup(self.db.upcast())
+ .container
+ else { return None };
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
}
@@ -969,38 +969,32 @@ impl<'a> InferenceContext<'a> {
}
fn resolve_range_full(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeFull];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeFull)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range(&self) -> Option<AdtId> {
- let path = path![core::ops::Range];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::Range)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_inclusive(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeInclusive];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeInclusiveStruct)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_from(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeFrom];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeFrom)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_to(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeTo];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeTo)?.as_struct()?;
Some(struct_.into())
}
fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
- let path = path![core::ops::RangeToInclusive];
- let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
+ let struct_ = self.resolve_lang_item(LangItem::RangeToInclusive)?.as_struct()?;
Some(struct_.into())
}
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 4c560702a1..88670364bd 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -163,98 +163,22 @@ fn test() {
}
#[test]
-fn infer_try() {
+fn infer_try_trait() {
check_types(
r#"
-//- /main.rs crate:main deps:core
+//- minicore: try, result
fn test() {
let r: Result<i32, u64> = Result::Ok(1);
let v = r?;
v;
} //^ i32
-//- /core.rs crate:core
-pub mod ops {
- pub trait Try {
- type Ok;
- type Error;
- }
+impl<O, E> core::ops::Try for Result<O, E> {
+ type Output = O;
+ type Error = Result<core::convert::Infallible, E>;
}
-pub mod result {
- pub enum Result<O, E> {
- Ok(O),
- Err(E)
- }
-
- impl<O, E> crate::ops::Try for Result<O, E> {
- type Ok = O;
- type Error = E;
- }
-}
-
-pub mod prelude {
- pub mod rust_2018 {
- pub use crate::{result::*, ops::*};
- }
-}
-"#,
- );
-}
-
-#[test]
-fn infer_try_trait_v2() {
- check_types(
- r#"
-//- /main.rs crate:main deps:core
-fn test() {
- let r: Result<i32, u64> = Result::Ok(1);
- let v = r?;
- v;
-} //^ i32
-
-//- /core.rs crate:core
-mod ops {
- mod try_trait {
- pub trait Try: FromResidual {
- type Output;
- type Residual;
- }
- pub trait FromResidual<R = <Self as Try>::Residual> {}
- }
-
- pub use self::try_trait::FromResidual;
- pub use self::try_trait::Try;
-}
-
-mod convert {
- pub trait From<T> {}
- impl<T> From<T> for T {}
-}
-
-pub mod result {
- use crate::convert::From;
- use crate::ops::{Try, FromResidual};
-
- pub enum Infallible {}
- pub enum Result<O, E> {
- Ok(O),
- Err(E)
- }
-
- impl<O, E> Try for Result<O, E> {
- type Output = O;
- type Error = Result<Infallible, E>;
- }
-
- impl<T, E, F: From<E>> FromResidual<Result<Infallible, E>> for Result<T, F> {}
-}
-
-pub mod prelude {
- pub mod rust_2018 {
- pub use crate::result::*;
- }
-}
+impl<T, E, F: From<E>> core::ops::FromResidual<Result<core::convert::Infallible, E>> for Result<T, F> {}
"#,
);
}
@@ -263,7 +187,8 @@ pub mod prelude {
fn infer_for_loop() {
check_types(
r#"
-//- /main.rs crate:main deps:core,alloc
+//- minicore: iterator
+//- /main.rs crate:main deps:alloc
#![no_std]
use alloc::collections::Vec;
@@ -275,23 +200,7 @@ fn test() {
} //^ &str
}
-//- /core.rs crate:core
-pub mod iter {
- pub trait IntoIterator {
- type Item;
- type IntoIter: Iterator<Item = Self::Item>;
- }
- pub trait Iterator {
- type Item;
- }
-}
-pub mod prelude {
- pub mod rust_2018 {
- pub use crate::iter::*;
- }
-}
-
-//- /alloc.rs crate:alloc deps:core
+//- /alloc.rs crate:alloc
#![no_std]
pub mod collections {
pub struct Vec<T> {}
@@ -2999,40 +2908,17 @@ fn test() {
fn integer_range_iterate() {
check_types(
r#"
-//- /main.rs crate:main deps:core
+//- minicore: range, iterator
+//- /main.rs crate:main
fn test() {
for x in 0..100 { x; }
} //^ i32
-//- /core.rs crate:core
-pub mod ops {
- pub struct Range<Idx> {
- pub start: Idx,
- pub end: Idx,
- }
-}
-
-pub mod iter {
- pub trait Iterator {
- type Item;
- }
-
- pub trait IntoIterator {
- type Item;
- type IntoIter: Iterator<Item = Self::Item>;
- }
-
- impl<T> IntoIterator for T where T: Iterator {
- type Item = <T as Iterator>::Item;
- type IntoIter = Self;
- }
-}
-
trait Step {}
impl Step for i32 {}
impl Step for i64 {}
-impl<A: Step> iter::Iterator for ops::Range<A> {
+impl<A: Step> core::iter::Iterator for core::ops::Range<A> {
type Item = A;
}
"#,
diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs
index a63ef00687..0b485eb776 100644
--- a/crates/ide-completion/src/tests/flyimport.rs
+++ b/crates/ide-completion/src/tests/flyimport.rs
@@ -541,9 +541,9 @@ fn main() {
}
"#,
expect![[r#"
- fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
- ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED
- "#]],
+ ct SPECIAL_CONST (use dep::test_mod::TestTrait) DEPRECATED
+ fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
+ "#]],
);
}
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index 3ca63fcab9..dff6091440 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -28,6 +28,7 @@
//! generator: pin
//! hash:
//! index: sized
+//! infallible:
//! iterator: option
//! iterators: iterator, fn
//! non_zero:
@@ -40,7 +41,7 @@
//! sized:
//! slice:
//! sync: sized
-//! try:
+//! try: infallible
//! unsize: sized
pub mod marker {
@@ -172,6 +173,9 @@ pub mod convert {
fn as_ref(&self) -> &T;
}
// endregion:as_ref
+ // region:infallible
+ pub enum Infallibe {}
+ // endregion:infallible
}
pub mod ops {
@@ -352,7 +356,7 @@ pub mod ops {
#[lang = "from_residual"]
fn from_residual(residual: R) -> Self;
}
- #[lang = "try"]
+ #[lang = "Try"]
pub trait Try: FromResidual<Self::Residual> {
type Output;
type Residual;