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:
bors[bot] 2019-12-29 16:58:29 +00:00 committed by GitHub
commit b30de4ed49
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 14 deletions

View file

@ -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>,

View file

@ -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")
};

View file

@ -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])
}
}

View file

@ -20,6 +20,7 @@ fn test() {
mod prelude {}
mod boxed {
#[lang = "owned_box"]
pub struct Box<T: ?Sized> {
inner: *mut T,
}

View file

@ -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;
}