mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Implement beginnings of generics
- add HIR for generic params - resolve generic params in type paths - add substitions for ADTs - insert type variables for substitutions
This commit is contained in:
parent
415cdc5210
commit
688a45e00b
13 changed files with 288 additions and 82 deletions
|
@ -1,3 +1,6 @@
|
|||
//! This module contains the implementation details of the HIR for ADTs, i.e.
|
||||
//! structs and enums (and unions).
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ra_syntax::{
|
||||
|
@ -62,7 +65,7 @@ fn get_def_id(
|
|||
};
|
||||
let loc = DefLoc {
|
||||
kind: expected_kind,
|
||||
source_item_id: source_item_id,
|
||||
source_item_id,
|
||||
..*same_file_loc
|
||||
};
|
||||
loc.id(db)
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::{
|
|||
expr::BodySyntaxMapping,
|
||||
ty::InferenceResult,
|
||||
adt::VariantData,
|
||||
generics::Generics,
|
||||
code_model_impl::def_id_to_ast,
|
||||
};
|
||||
|
||||
|
@ -201,6 +202,10 @@ impl Struct {
|
|||
pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
|
||||
def_id_to_ast(db, self.def_id)
|
||||
}
|
||||
|
||||
pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> {
|
||||
db.generics(self.def_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -228,6 +233,10 @@ impl Enum {
|
|||
pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) {
|
||||
def_id_to_ast(db, self.def_id)
|
||||
}
|
||||
|
||||
pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> {
|
||||
db.generics(self.def_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -339,6 +348,10 @@ impl Function {
|
|||
pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
|
||||
db.infer(self.def_id)
|
||||
}
|
||||
|
||||
pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> {
|
||||
db.generics(self.def_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -384,6 +397,10 @@ impl Trait {
|
|||
pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) {
|
||||
def_id_to_ast(db, self.def_id)
|
||||
}
|
||||
|
||||
pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> {
|
||||
db.generics(self.def_id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -399,4 +416,8 @@ impl Type {
|
|||
pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) {
|
||||
def_id_to_ast(db, self.def_id)
|
||||
}
|
||||
|
||||
pub fn generics(&self, db: &impl HirDatabase) -> Arc<Generics> {
|
||||
db.generics(self.def_id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ use crate::{
|
|||
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks},
|
||||
adt::{StructData, EnumData, EnumVariantData},
|
||||
impl_block::ModuleImplBlocks,
|
||||
generics::Generics,
|
||||
};
|
||||
|
||||
#[salsa::query_group]
|
||||
|
@ -101,6 +102,9 @@ pub trait HirDatabase:
|
|||
#[salsa::invoke(crate::expr::body_syntax_mapping)]
|
||||
fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>;
|
||||
|
||||
#[salsa::invoke(crate::generics::Generics::generics_query)]
|
||||
fn generics(&self, def_id: DefId) -> Arc<Generics>;
|
||||
|
||||
#[salsa::invoke(crate::FnSignature::fn_signature_query)]
|
||||
fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>;
|
||||
}
|
||||
|
|
48
crates/ra_hir/src/generics.rs
Normal file
48
crates/ra_hir/src/generics.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
//! Many kinds of items or constructs can have generic parameters: functions,
|
||||
//! structs, impls, traits, etc. This module provides a common HIR for these
|
||||
//! generic parameters. See also the `Generics` type and the `generics_of` query
|
||||
//! in rustc.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ra_syntax::ast::{TypeParamList, AstNode, NameOwner};
|
||||
|
||||
use crate::{db::HirDatabase, DefId, Name, AsName};
|
||||
|
||||
/// Data about a generic parameter (to a function, struct, impl, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct GenericParam {
|
||||
pub(crate) idx: u32,
|
||||
pub(crate) name: Name,
|
||||
}
|
||||
|
||||
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default)]
|
||||
pub struct Generics {
|
||||
pub(crate) params: Vec<GenericParam>,
|
||||
}
|
||||
|
||||
impl Generics {
|
||||
pub(crate) fn generics_query(db: &impl HirDatabase, def_id: DefId) -> Arc<Generics> {
|
||||
let (_file_id, node) = def_id.source(db);
|
||||
let mut generics = Generics::default();
|
||||
if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) {
|
||||
for (idx, type_param) in type_param_list.type_params().enumerate() {
|
||||
let name = type_param
|
||||
.name()
|
||||
.map(AsName::as_name)
|
||||
.unwrap_or_else(Name::missing);
|
||||
let param = GenericParam {
|
||||
idx: idx as u32,
|
||||
name,
|
||||
};
|
||||
generics.params.push(param);
|
||||
}
|
||||
}
|
||||
Arc::new(generics)
|
||||
}
|
||||
|
||||
pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
|
||||
self.params.iter().find(|p| &p.name == name)
|
||||
}
|
||||
}
|
|
@ -24,6 +24,7 @@ mod type_ref;
|
|||
mod ty;
|
||||
mod impl_block;
|
||||
mod expr;
|
||||
mod generics;
|
||||
|
||||
mod code_model_api;
|
||||
mod code_model_impl;
|
||||
|
|
|
@ -243,6 +243,7 @@ salsa::database_storage! {
|
|||
fn body_hir() for db::BodyHirQuery;
|
||||
fn body_syntax_mapping() for db::BodySyntaxMappingQuery;
|
||||
fn fn_signature() for db::FnSignatureQuery;
|
||||
fn generics() for db::GenericsQuery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ use crate::{
|
|||
type_ref::{TypeRef, Mutability},
|
||||
name::KnownName,
|
||||
expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat},
|
||||
generics::Generics,
|
||||
};
|
||||
|
||||
/// The ID of a type variable.
|
||||
|
@ -151,10 +152,14 @@ impl Expectation {
|
|||
}
|
||||
}
|
||||
|
||||
/// A list of substitutions for generic parameters.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Substs(Arc<[Ty]>);
|
||||
|
||||
/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
|
||||
///
|
||||
/// This should be cheap to clone.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Ty {
|
||||
/// The primitive boolean type. Written as `bool`.
|
||||
Bool,
|
||||
|
@ -175,7 +180,8 @@ pub enum Ty {
|
|||
def_id: DefId,
|
||||
/// The name, for displaying.
|
||||
name: Name,
|
||||
// later we'll need generic substitutions here
|
||||
/// Substitutions for the generic parameters of the type.
|
||||
substs: Substs,
|
||||
},
|
||||
|
||||
/// The pointee of a string slice. Written as `str`.
|
||||
|
@ -234,9 +240,14 @@ pub enum Ty {
|
|||
|
||||
// Opaque (`impl Trait`) type found in a return type.
|
||||
// Opaque(DefId, Substs),
|
||||
/// A type parameter; for example, `T` in `fn f<T>(x: T) {}
|
||||
Param {
|
||||
/// The index of the parameter.
|
||||
idx: u32,
|
||||
/// The name of the parameter, for displaying.
|
||||
name: Name,
|
||||
},
|
||||
|
||||
// A type parameter; for example, `T` in `fn f<T>(x: T) {}
|
||||
// Param(ParamTy),
|
||||
/// A type variable used during type checking. Not to be confused with a
|
||||
/// type parameter.
|
||||
Infer(InferTy),
|
||||
|
@ -250,7 +261,7 @@ pub enum Ty {
|
|||
}
|
||||
|
||||
/// A function signature.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct FnSig {
|
||||
input: Vec<Ty>,
|
||||
output: Ty,
|
||||
|
@ -261,6 +272,7 @@ impl Ty {
|
|||
db: &impl HirDatabase,
|
||||
module: &Module,
|
||||
impl_block: Option<&ImplBlock>,
|
||||
generics: &Generics,
|
||||
type_ref: &TypeRef,
|
||||
) -> Self {
|
||||
match type_ref {
|
||||
|
@ -268,32 +280,32 @@ impl Ty {
|
|||
TypeRef::Tuple(inner) => {
|
||||
let inner_tys = inner
|
||||
.iter()
|
||||
.map(|tr| Ty::from_hir(db, module, impl_block, tr))
|
||||
.map(|tr| Ty::from_hir(db, module, impl_block, generics, tr))
|
||||
.collect::<Vec<_>>();
|
||||
Ty::Tuple(inner_tys.into())
|
||||
}
|
||||
TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, path),
|
||||
TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, generics, path),
|
||||
TypeRef::RawPtr(inner, mutability) => {
|
||||
let inner_ty = Ty::from_hir(db, module, impl_block, inner);
|
||||
let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
|
||||
Ty::RawPtr(Arc::new(inner_ty), *mutability)
|
||||
}
|
||||
TypeRef::Array(inner) => {
|
||||
let inner_ty = Ty::from_hir(db, module, impl_block, inner);
|
||||
let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
|
||||
Ty::Array(Arc::new(inner_ty))
|
||||
}
|
||||
TypeRef::Slice(inner) => {
|
||||
let inner_ty = Ty::from_hir(db, module, impl_block, inner);
|
||||
let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
|
||||
Ty::Slice(Arc::new(inner_ty))
|
||||
}
|
||||
TypeRef::Reference(inner, mutability) => {
|
||||
let inner_ty = Ty::from_hir(db, module, impl_block, inner);
|
||||
let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner);
|
||||
Ty::Ref(Arc::new(inner_ty), *mutability)
|
||||
}
|
||||
TypeRef::Placeholder => Ty::Unknown,
|
||||
TypeRef::Fn(params) => {
|
||||
let mut inner_tys = params
|
||||
.iter()
|
||||
.map(|tr| Ty::from_hir(db, module, impl_block, tr))
|
||||
.map(|tr| Ty::from_hir(db, module, impl_block, generics, tr))
|
||||
.collect::<Vec<_>>();
|
||||
let return_ty = inner_tys
|
||||
.pop()
|
||||
|
@ -312,15 +324,19 @@ impl Ty {
|
|||
db: &impl HirDatabase,
|
||||
module: &Module,
|
||||
impl_block: Option<&ImplBlock>,
|
||||
generics: &Generics,
|
||||
type_ref: Option<&TypeRef>,
|
||||
) -> Self {
|
||||
type_ref.map_or(Ty::Unknown, |t| Ty::from_hir(db, module, impl_block, t))
|
||||
type_ref.map_or(Ty::Unknown, |t| {
|
||||
Ty::from_hir(db, module, impl_block, generics, t)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn from_hir_path(
|
||||
db: &impl HirDatabase,
|
||||
module: &Module,
|
||||
impl_block: Option<&ImplBlock>,
|
||||
generics: &Generics,
|
||||
path: &Path,
|
||||
) -> Self {
|
||||
if let Some(name) = path.as_ident() {
|
||||
|
@ -329,7 +345,15 @@ impl Ty {
|
|||
} else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) {
|
||||
return Ty::Float(float_ty);
|
||||
} else if name.as_known_name() == Some(KnownName::SelfType) {
|
||||
return Ty::from_hir_opt(db, module, None, impl_block.map(|i| i.target_type()));
|
||||
// TODO pass the impl block's generics?
|
||||
let generics = &Generics::default();
|
||||
return Ty::from_hir_opt(
|
||||
db,
|
||||
module,
|
||||
None,
|
||||
generics,
|
||||
impl_block.map(|i| i.target_type()),
|
||||
);
|
||||
} else if let Some(known) = name.as_known_name() {
|
||||
match known {
|
||||
KnownName::Bool => return Ty::Bool,
|
||||
|
@ -337,6 +361,11 @@ impl Ty {
|
|||
KnownName::Str => return Ty::Str,
|
||||
_ => {}
|
||||
}
|
||||
} else if let Some(generic_param) = generics.find_by_name(&name) {
|
||||
return Ty::Param {
|
||||
idx: generic_param.idx,
|
||||
name: generic_param.name.clone(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -374,7 +403,14 @@ impl Ty {
|
|||
}
|
||||
sig_mut.output.walk_mut(f);
|
||||
}
|
||||
Ty::Adt { .. } => {} // need to walk type parameters later
|
||||
Ty::Adt { substs, .. } => {
|
||||
// Without an Arc::make_mut_slice, we can't avoid the clone here:
|
||||
let mut v: Vec<_> = substs.0.iter().cloned().collect();
|
||||
for t in &mut v {
|
||||
t.walk_mut(f);
|
||||
}
|
||||
substs.0 = v.into();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -394,6 +430,32 @@ impl Ty {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces type parameters in this type using the given `Substs`. (So e.g.
|
||||
/// if `self` is `&[T]`, where type parameter T has index 0, and the
|
||||
/// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
|
||||
pub fn subst(self, substs: &Substs) -> Ty {
|
||||
self.fold(&mut |ty| match ty {
|
||||
Ty::Param { idx, name } => {
|
||||
if (idx as usize) < substs.0.len() {
|
||||
substs.0[idx as usize].clone()
|
||||
} else {
|
||||
// TODO it's yet unclear to me whether we need to shift the indices here
|
||||
Ty::Param { idx, name }
|
||||
}
|
||||
}
|
||||
ty => ty,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the type parameters of this type if it has some (i.e. is an ADT
|
||||
/// or function); so if `self` is `Option<u32>`, this returns the `u32`.
|
||||
fn substs(&self) -> Option<Substs> {
|
||||
match self {
|
||||
Ty::Adt { substs, .. } => Some(substs.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Ty {
|
||||
|
@ -425,7 +487,17 @@ impl fmt::Display for Ty {
|
|||
.to_fmt(f)?;
|
||||
write!(f, " -> {}", sig.output)
|
||||
}
|
||||
Ty::Adt { name, .. } => write!(f, "{}", name),
|
||||
Ty::Adt { name, substs, .. } => {
|
||||
write!(f, "{}", name)?;
|
||||
if substs.0.len() > 0 {
|
||||
join(substs.0.iter())
|
||||
.surround_with("<", ">")
|
||||
.separator(", ")
|
||||
.to_fmt(f)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Ty::Param { name, .. } => write!(f, "{}", name),
|
||||
Ty::Unknown => write!(f, "[unknown]"),
|
||||
Ty::Infer(..) => write!(f, "_"),
|
||||
}
|
||||
|
@ -440,28 +512,49 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
|
|||
let signature = f.signature(db);
|
||||
let module = f.module(db);
|
||||
let impl_block = f.impl_block(db);
|
||||
// TODO we ignore type parameters for now
|
||||
let generics = f.generics(db);
|
||||
let input = signature
|
||||
.params()
|
||||
.iter()
|
||||
.map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), tr))
|
||||
.map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr))
|
||||
.collect::<Vec<_>>();
|
||||
let output = Ty::from_hir(db, &module, impl_block.as_ref(), signature.ret_type());
|
||||
let output = Ty::from_hir(
|
||||
db,
|
||||
&module,
|
||||
impl_block.as_ref(),
|
||||
&generics,
|
||||
signature.ret_type(),
|
||||
);
|
||||
let sig = FnSig { input, output };
|
||||
Ty::FnPtr(Arc::new(sig))
|
||||
}
|
||||
|
||||
fn make_substs(generics: &Generics) -> Substs {
|
||||
Substs(
|
||||
generics
|
||||
.params
|
||||
.iter()
|
||||
.map(|_p| Ty::Unknown)
|
||||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
|
||||
let generics = s.generics(db);
|
||||
Ty::Adt {
|
||||
def_id: s.def_id(),
|
||||
name: s.name(db).unwrap_or_else(Name::missing),
|
||||
substs: make_substs(&generics),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
|
||||
let generics = s.generics(db);
|
||||
Ty::Adt {
|
||||
def_id: s.def_id(),
|
||||
name: s.name(db).unwrap_or_else(Name::missing),
|
||||
substs: make_substs(&generics),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,8 +599,15 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name)
|
|||
};
|
||||
let module = def_id.module(db);
|
||||
let impl_block = def_id.impl_block(db);
|
||||
let generics = db.generics(def_id);
|
||||
let type_ref = variant_data.get_field_type_ref(&field)?;
|
||||
Some(Ty::from_hir(db, &module, impl_block.as_ref(), &type_ref))
|
||||
Some(Ty::from_hir(
|
||||
db,
|
||||
&module,
|
||||
impl_block.as_ref(),
|
||||
&generics,
|
||||
&type_ref,
|
||||
))
|
||||
}
|
||||
|
||||
/// The result of type inference: A mapping from expressions and patterns to types.
|
||||
|
@ -684,8 +784,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
self.type_of_pat.insert(pat, ty);
|
||||
}
|
||||
|
||||
fn make_ty(&self, type_ref: &TypeRef) -> Ty {
|
||||
Ty::from_hir(self.db, &self.module, self.impl_block.as_ref(), type_ref)
|
||||
fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
|
||||
// TODO provide generics of function
|
||||
let generics = Generics::default();
|
||||
let ty = Ty::from_hir(
|
||||
self.db,
|
||||
&self.module,
|
||||
self.impl_block.as_ref(),
|
||||
&generics,
|
||||
type_ref,
|
||||
);
|
||||
let ty = self.insert_type_vars(ty);
|
||||
ty
|
||||
}
|
||||
|
||||
fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
|
||||
|
@ -848,7 +958,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
Some(ty)
|
||||
}
|
||||
|
||||
fn resolve_variant(&self, path: Option<&Path>) -> (Ty, Option<DefId>) {
|
||||
fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) {
|
||||
let path = if let Some(path) = path {
|
||||
path
|
||||
} else {
|
||||
|
@ -862,10 +972,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
match def_id.resolve(self.db) {
|
||||
Def::Struct(s) => {
|
||||
let ty = type_for_struct(self.db, s);
|
||||
let ty = self.insert_type_vars(ty);
|
||||
(ty, Some(def_id))
|
||||
}
|
||||
Def::EnumVariant(ev) => {
|
||||
let ty = type_for_enum_variant(self.db, ev);
|
||||
let ty = self.insert_type_vars(ty);
|
||||
(ty, Some(def_id))
|
||||
}
|
||||
_ => (Ty::Unknown, None),
|
||||
|
@ -1155,11 +1267,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
spread,
|
||||
} => {
|
||||
let (ty, def_id) = self.resolve_variant(path.as_ref());
|
||||
let substs = ty.substs().expect("adt should have substs");
|
||||
for field in fields {
|
||||
let field_ty = if let Some(def_id) = def_id {
|
||||
self.db
|
||||
.type_for_field(def_id, field.name.clone())
|
||||
.unwrap_or(Ty::Unknown)
|
||||
.subst(&substs)
|
||||
} else {
|
||||
Ty::Unknown
|
||||
};
|
||||
|
@ -1180,7 +1294,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
let i = name.to_string().parse::<usize>().ok();
|
||||
i.and_then(|i| fields.get(i).cloned())
|
||||
}
|
||||
Ty::Adt { def_id, .. } => self.db.type_for_field(def_id, name.clone()),
|
||||
Ty::Adt {
|
||||
def_id, ref substs, ..
|
||||
} => self
|
||||
.db
|
||||
.type_for_field(def_id, name.clone())
|
||||
.map(|ty| ty.subst(substs)),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or(Ty::Unknown);
|
||||
|
@ -1193,7 +1312,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
Expr::Cast { expr, type_ref } => {
|
||||
let _inner_ty = self.infer_expr(*expr, &Expectation::none());
|
||||
let cast_ty = self.make_ty(type_ref);
|
||||
let cast_ty = self.insert_type_vars(cast_ty);
|
||||
// TODO check the cast...
|
||||
cast_ty
|
||||
}
|
||||
|
@ -1305,12 +1423,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
type_ref,
|
||||
initializer,
|
||||
} => {
|
||||
let decl_ty = Ty::from_hir_opt(
|
||||
self.db,
|
||||
&self.module,
|
||||
self.impl_block.as_ref(),
|
||||
type_ref.as_ref(),
|
||||
);
|
||||
let decl_ty = type_ref
|
||||
.as_ref()
|
||||
.map(|tr| self.make_ty(tr))
|
||||
.unwrap_or(Ty::Unknown);
|
||||
let decl_ty = self.insert_type_vars(decl_ty);
|
||||
let ty = if let Some(expr) = initializer {
|
||||
let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty));
|
||||
|
@ -1338,13 +1454,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||
for (type_ref, pat) in signature.params().iter().zip(body.params()) {
|
||||
let ty = self.make_ty(type_ref);
|
||||
let ty = self.insert_type_vars(ty);
|
||||
|
||||
self.infer_pat(*pat, &ty);
|
||||
}
|
||||
self.return_ty = {
|
||||
let ty = self.make_ty(signature.ret_type());
|
||||
let ty = self.insert_type_vars(ty);
|
||||
ty
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,11 @@ use rustc_hash::FxHashMap;
|
|||
|
||||
use ra_db::SourceRootId;
|
||||
|
||||
use crate::{HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, impl_block::{ImplId, ImplBlock, ImplItem}};
|
||||
use crate::{
|
||||
HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function,
|
||||
impl_block::{ImplId, ImplBlock, ImplItem},
|
||||
generics::Generics
|
||||
};
|
||||
use super::Ty;
|
||||
|
||||
/// This is used as a key for indexing impls.
|
||||
|
@ -64,8 +68,15 @@ impl CrateImplBlocks {
|
|||
if let Some(_target_trait) = impl_data.target_trait() {
|
||||
// ignore for now
|
||||
} else {
|
||||
let target_ty =
|
||||
Ty::from_hir(db, &module, Some(&impl_block), impl_data.target_type());
|
||||
// TODO provide generics of impl
|
||||
let generics = Generics::default();
|
||||
let target_ty = Ty::from_hir(
|
||||
db,
|
||||
&module,
|
||||
Some(&impl_block),
|
||||
&generics,
|
||||
impl_data.target_type(),
|
||||
);
|
||||
if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
|
||||
self.impls
|
||||
.entry(target_ty_fp)
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
[21; 26) '{ t }': [unknown]
|
||||
[23; 24) 't': [unknown]
|
||||
[38; 98) '{ ...(1); }': ()
|
||||
[44; 46) 'id': fn([unknown]) -> [unknown]
|
||||
[44; 52) 'id(1u32)': [unknown]
|
||||
[47; 51) '1u32': [unknown]
|
||||
[58; 68) 'id::<i128>': fn([unknown]) -> [unknown]
|
||||
[58; 71) 'id::<i128>(1)': [unknown]
|
||||
[69; 70) '1': [unknown]
|
||||
[81; 82) 'x': u64
|
||||
[90; 92) 'id': fn([unknown]) -> u64
|
||||
[90; 95) 'id(1)': u64
|
||||
[93; 94) '1': [unknown]
|
||||
[44; 46) 'id': fn(T) -> T
|
||||
[44; 52) 'id(1u32)': T
|
||||
[47; 51) '1u32': u32
|
||||
[58; 68) 'id::<i128>': fn(T) -> T
|
||||
[58; 71) 'id::<i128>(1)': T
|
||||
[69; 70) '1': T
|
||||
[81; 82) 'x': T
|
||||
[90; 92) 'id': fn(T) -> T
|
||||
[90; 95) 'id(1)': T
|
||||
[93; 94) '1': T
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
[53; 57) 'self': A
|
||||
[53; 57) 'self': A<[unknown]>
|
||||
[65; 87) '{ ... }': [unknown]
|
||||
[75; 79) 'self': A
|
||||
[75; 79) 'self': A<[unknown]>
|
||||
[75; 81) 'self.x': [unknown]
|
||||
[99; 100) 't': [unknown]
|
||||
[110; 115) '{ t }': [unknown]
|
||||
[112; 113) 't': [unknown]
|
||||
[135; 261) '{ ....x() }': i128
|
||||
[146; 147) 'x': [unknown]
|
||||
[150; 151) '1': [unknown]
|
||||
[162; 163) 'y': [unknown]
|
||||
[166; 168) 'id': fn([unknown]) -> [unknown]
|
||||
[166; 171) 'id(x)': [unknown]
|
||||
[169; 170) 'x': [unknown]
|
||||
[182; 183) 'a': A
|
||||
[186; 200) 'A { x: id(y) }': A
|
||||
[193; 195) 'id': fn([unknown]) -> [unknown]
|
||||
[193; 198) 'id(y)': [unknown]
|
||||
[196; 197) 'y': [unknown]
|
||||
[211; 212) 'z': [unknown]
|
||||
[215; 217) 'id': fn([unknown]) -> [unknown]
|
||||
[215; 222) 'id(a.x)': [unknown]
|
||||
[218; 219) 'a': A
|
||||
[218; 221) 'a.x': [unknown]
|
||||
[233; 234) 'b': A
|
||||
[237; 247) 'A { x: z }': A
|
||||
[244; 245) 'z': [unknown]
|
||||
[254; 255) 'b': A
|
||||
[146; 147) 'x': T
|
||||
[150; 151) '1': T
|
||||
[162; 163) 'y': T
|
||||
[166; 168) 'id': fn(T) -> T
|
||||
[166; 171) 'id(x)': T
|
||||
[169; 170) 'x': T
|
||||
[182; 183) 'a': A<T>
|
||||
[186; 200) 'A { x: id(y) }': A<T>
|
||||
[193; 195) 'id': fn(T) -> T
|
||||
[193; 198) 'id(y)': T
|
||||
[196; 197) 'y': T
|
||||
[211; 212) 'z': T
|
||||
[215; 217) 'id': fn(T) -> T
|
||||
[215; 222) 'id(a.x)': T
|
||||
[218; 219) 'a': A<T>
|
||||
[218; 221) 'a.x': T
|
||||
[233; 234) 'b': A<T>
|
||||
[237; 247) 'A { x: z }': A<T>
|
||||
[244; 245) 'z': T
|
||||
[254; 255) 'b': A<T>
|
||||
[254; 259) 'b.x()': i128
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
[36; 38) 'a1': A
|
||||
[36; 38) 'a1': A<[unknown]>
|
||||
[48; 49) 'i': i32
|
||||
[56; 147) '{ ...3.x; }': ()
|
||||
[62; 64) 'a1': A
|
||||
[62; 64) 'a1': A<[unknown]>
|
||||
[62; 66) 'a1.x': [unknown]
|
||||
[76; 78) 'a2': A
|
||||
[81; 91) 'A { x: i }': A
|
||||
[76; 78) 'a2': A<i32>
|
||||
[81; 91) 'A { x: i }': A<i32>
|
||||
[88; 89) 'i': i32
|
||||
[97; 99) 'a2': A
|
||||
[97; 101) 'a2.x': [unknown]
|
||||
[111; 113) 'a3': A
|
||||
[116; 134) 'A::<i1...x: 1 }': A
|
||||
[131; 132) '1': [unknown]
|
||||
[140; 142) 'a3': A
|
||||
[140; 144) 'a3.x': [unknown]
|
||||
[97; 99) 'a2': A<i32>
|
||||
[97; 101) 'a2.x': i32
|
||||
[111; 113) 'a3': A<i32>
|
||||
[116; 134) 'A::<i1...x: 1 }': A<i32>
|
||||
[131; 132) '1': i32
|
||||
[140; 142) 'a3': A<i32>
|
||||
[140; 144) 'a3.x': i32
|
||||
|
|
|
@ -24,7 +24,9 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
|
|||
fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
|
||||
for receiver in receiver.autoderef(ctx.db) {
|
||||
match receiver {
|
||||
Ty::Adt { def_id, .. } => {
|
||||
Ty::Adt {
|
||||
def_id, ref substs, ..
|
||||
} => {
|
||||
match def_id.resolve(ctx.db) {
|
||||
Def::Struct(s) => {
|
||||
for field in s.fields(ctx.db) {
|
||||
|
@ -33,7 +35,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
|
|||
field.name().to_string(),
|
||||
)
|
||||
.kind(CompletionItemKind::Field)
|
||||
.set_detail(field.ty(ctx.db).map(|ty| ty.to_string()))
|
||||
.set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string()))
|
||||
.add_to(acc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ salsa::database_storage! {
|
|||
fn body_hir() for hir::db::BodyHirQuery;
|
||||
fn body_syntax_mapping() for hir::db::BodySyntaxMappingQuery;
|
||||
fn fn_signature() for hir::db::FnSignatureQuery;
|
||||
fn generics() for hir::db::GenericsQuery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue