about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-01-21 18:47:37 +0100
committerLukas Wirth <lukastw97@gmail.com>2023-01-21 19:03:36 +0100
commitf8ed4d7ae44e7a730f597f1f6618fb3b4aead01b (patch)
tree32f3397e5a9cfaa3d88af26f94a12d4764abe381
parent15358818363f66fc8b99e3711e6eb99a5e8684b9 (diff)
downloadrust-f8ed4d7ae44e7a730f597f1f6618fb3b4aead01b.tar.gz
rust-f8ed4d7ae44e7a730f597f1f6618fb3b4aead01b.zip
Use lang item resolution instead of known paths
-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 9e4e0dcc96c..8eae2e92f42 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 c8df4c796ef..3286dcb5afd 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 d06b22fff9a..4402c75947c 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 4c560702a1b..88670364bde 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 a63ef006875..0b485eb776d 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 3ca63fcab90..dff60914409 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;