Merge #2679
2679: Resolve traits for infer using lang item infrastructure r=matklad a=kiljacken As we already have the infrastructure for collecting lang items, use it to find the right traits when doing type-inference. Co-authored-by: Emil Lauridsen <mine809@gmail.com>
This commit is contained in:
commit
b30de4ed49
5 changed files with 63 additions and 14 deletions
|
|
@ -22,6 +22,50 @@ pub enum LangItemTarget {
|
|||
TraitId(TraitId),
|
||||
}
|
||||
|
||||
impl LangItemTarget {
|
||||
pub fn as_enum(self) -> Option<EnumId> {
|
||||
match self {
|
||||
LangItemTarget::EnumId(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_function(self) -> Option<FunctionId> {
|
||||
match self {
|
||||
LangItemTarget::FunctionId(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_impl_block(self) -> Option<ImplId> {
|
||||
match self {
|
||||
LangItemTarget::ImplBlockId(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_static(self) -> Option<StaticId> {
|
||||
match self {
|
||||
LangItemTarget::StaticId(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_struct(self) -> Option<StructId> {
|
||||
match self {
|
||||
LangItemTarget::StructId(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_trait(self) -> Option<TraitId> {
|
||||
match self {
|
||||
LangItemTarget::TraitId(id) => Some(id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct LangItems {
|
||||
items: FxHashMap<SmolStr, LangItemTarget>,
|
||||
|
|
|
|||
|
|
@ -260,12 +260,8 @@ macro_rules! __known_path {
|
|||
(std::ops::RangeTo) => {};
|
||||
(std::ops::RangeToInclusive) => {};
|
||||
(std::ops::RangeInclusive) => {};
|
||||
(std::boxed::Box) => {};
|
||||
(std::future::Future) => {};
|
||||
(std::ops::Try) => {};
|
||||
(std::ops::Neg) => {};
|
||||
(std::ops::Not) => {};
|
||||
(std::ops::Index) => {};
|
||||
($path:path) => {
|
||||
compile_error!("Please register your known path in the path module")
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ use hir_def::{
|
|||
body::Body,
|
||||
data::{ConstData, FunctionData},
|
||||
expr::{BindingAnnotation, ExprId, PatId},
|
||||
lang_item::LangItemTarget,
|
||||
path::{path, Path},
|
||||
resolver::{HasResolver, Resolver, TypeNs},
|
||||
type_ref::{Mutability, TypeRef},
|
||||
|
|
@ -32,6 +33,7 @@ use hir_def::{
|
|||
use hir_expand::{diagnostics::DiagnosticSink, name::name};
|
||||
use ra_arena::map::ArenaMap;
|
||||
use ra_prof::profile;
|
||||
use ra_syntax::SmolStr;
|
||||
use test_utils::tested_by;
|
||||
|
||||
use super::{
|
||||
|
|
@ -482,6 +484,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
self.infer_expr_coerce(self.body.body_expr, &Expectation::has_type(self.return_ty.clone()));
|
||||
}
|
||||
|
||||
fn resolve_lang_item(&self, name: &str) -> Option<LangItemTarget> {
|
||||
let krate = self.resolver.krate()?;
|
||||
let name = SmolStr::new_inline_from_ascii(name.len(), name.as_bytes());
|
||||
self.db.lang_item(krate, name)
|
||||
}
|
||||
|
||||
fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
|
||||
let path = path![std::iter::IntoIterator];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
|
|
@ -495,26 +503,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
}
|
||||
|
||||
fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
|
||||
let path = path![std::ops::Neg];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
let trait_ = self.resolve_lang_item("neg")?.as_trait()?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
}
|
||||
|
||||
fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
|
||||
let path = path![std::ops::Not];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
let trait_ = self.resolve_lang_item("not")?.as_trait()?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
}
|
||||
|
||||
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
|
||||
let path = path![std::future::Future];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
let trait_ = self.resolve_lang_item("future_trait")?.as_trait()?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
}
|
||||
|
||||
fn resolve_boxed_box(&self) -> Option<AdtId> {
|
||||
let path = path![std::boxed::Box];
|
||||
let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
|
||||
let struct_ = self.resolve_lang_item("owned_box")?.as_struct()?;
|
||||
Some(struct_.into())
|
||||
}
|
||||
|
||||
|
|
@ -555,8 +559,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
}
|
||||
|
||||
fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
|
||||
let path = path![std::ops::Index];
|
||||
let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
|
||||
let trait_ = self.resolve_lang_item("index")?.as_trait()?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ fn test() {
|
|||
mod prelude {}
|
||||
|
||||
mod boxed {
|
||||
#[lang = "owned_box"]
|
||||
pub struct Box<T: ?Sized> {
|
||||
inner: *mut T,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ fn test() {
|
|||
//- /std.rs crate:std
|
||||
#[prelude_import] use future::*;
|
||||
mod future {
|
||||
#[lang = "future_trait"]
|
||||
trait Future {
|
||||
type Output;
|
||||
}
|
||||
|
|
@ -56,6 +57,7 @@ fn test() {
|
|||
//- /std.rs crate:std
|
||||
#[prelude_import] use future::*;
|
||||
mod future {
|
||||
#[lang = "future_trait"]
|
||||
trait Future {
|
||||
type Output;
|
||||
}
|
||||
|
|
@ -198,6 +200,7 @@ fn test() {
|
|||
|
||||
#[prelude_import] use ops::*;
|
||||
mod ops {
|
||||
#[lang = "neg"]
|
||||
pub trait Neg {
|
||||
type Output;
|
||||
}
|
||||
|
|
@ -230,6 +233,7 @@ fn test() {
|
|||
|
||||
#[prelude_import] use ops::*;
|
||||
mod ops {
|
||||
#[lang = "not"]
|
||||
pub trait Not {
|
||||
type Output;
|
||||
}
|
||||
|
|
@ -506,6 +510,7 @@ fn test() {
|
|||
|
||||
#[prelude_import] use ops::*;
|
||||
mod ops {
|
||||
#[lang = "index"]
|
||||
pub trait Index<Idx> {
|
||||
type Output;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue