mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
Introduce TypeInfo
This commit is contained in:
parent
29506b5a26
commit
25ff7171c4
32 changed files with 127 additions and 124 deletions
|
@ -89,7 +89,7 @@ pub use crate::{
|
|||
UnresolvedModule, UnresolvedProcMacro,
|
||||
},
|
||||
has_source::HasSource,
|
||||
semantics::{PathResolution, Semantics, SemanticsScope},
|
||||
semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo},
|
||||
};
|
||||
|
||||
// Be careful with these re-exports.
|
||||
|
|
|
@ -87,6 +87,28 @@ impl PathResolution {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TypeInfo {
|
||||
/// The original type of the expression or pattern.
|
||||
pub ty: Type,
|
||||
/// The coerced type, if a coercion happened.
|
||||
pub coerced: Option<Type>,
|
||||
}
|
||||
|
||||
impl TypeInfo {
|
||||
pub fn ty(self) -> Type {
|
||||
self.ty
|
||||
}
|
||||
|
||||
pub fn coerced(self) -> Option<Type> {
|
||||
self.coerced
|
||||
}
|
||||
|
||||
pub fn coerced_or_original(self) -> Type {
|
||||
self.coerced.unwrap_or(self.ty)
|
||||
}
|
||||
}
|
||||
|
||||
/// Primary API to get semantic information, like types, from syntax trees.
|
||||
pub struct Semantics<'db, DB> {
|
||||
pub db: &'db DB,
|
||||
|
@ -212,23 +234,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
|||
self.imp.resolve_type(ty)
|
||||
}
|
||||
|
||||
pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
|
||||
pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo> {
|
||||
self.imp.type_of_expr(expr)
|
||||
}
|
||||
|
||||
/// Returns true in case a coercion happened.
|
||||
pub fn type_of_expr_with_coercion(&self, expr: &ast::Expr) -> Option<(Type, bool)> {
|
||||
self.imp.type_of_expr_with_coercion(expr)
|
||||
}
|
||||
|
||||
pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
|
||||
pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<TypeInfo> {
|
||||
self.imp.type_of_pat(pat)
|
||||
}
|
||||
|
||||
pub fn type_of_pat_with_coercion(&self, expr: &ast::Pat) -> Option<(Type, bool)> {
|
||||
self.imp.type_of_pat_with_coercion(expr)
|
||||
}
|
||||
|
||||
pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
|
||||
self.imp.type_of_self(param)
|
||||
}
|
||||
|
@ -565,20 +578,16 @@ impl<'db> SemanticsImpl<'db> {
|
|||
Type::new_with_resolver(self.db, &scope.resolver, ty)
|
||||
}
|
||||
|
||||
fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
|
||||
self.analyze(expr.syntax()).type_of_expr(self.db, expr)
|
||||
fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo> {
|
||||
self.analyze(expr.syntax())
|
||||
.type_of_expr(self.db, expr)
|
||||
.map(|(ty, coerced)| TypeInfo { ty, coerced })
|
||||
}
|
||||
|
||||
fn type_of_expr_with_coercion(&self, expr: &ast::Expr) -> Option<(Type, bool)> {
|
||||
self.analyze(expr.syntax()).type_of_expr_with_coercion(self.db, expr)
|
||||
}
|
||||
|
||||
fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
|
||||
self.analyze(pat.syntax()).type_of_pat(self.db, pat)
|
||||
}
|
||||
|
||||
fn type_of_pat_with_coercion(&self, pat: &ast::Pat) -> Option<(Type, bool)> {
|
||||
self.analyze(pat.syntax()).type_of_pat_with_coercion(self.db, pat)
|
||||
fn type_of_pat(&self, pat: &ast::Pat) -> Option<TypeInfo> {
|
||||
self.analyze(pat.syntax())
|
||||
.type_of_pat(self.db, pat)
|
||||
.map(|(ty, coerced)| TypeInfo { ty, coerced })
|
||||
}
|
||||
|
||||
fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
|
||||
|
@ -757,7 +766,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
ast::Expr::FieldExpr(field_expr) => field_expr,
|
||||
_ => return None,
|
||||
};
|
||||
let ty = self.type_of_expr(&field_expr.expr()?)?;
|
||||
let ty = self.type_of_expr(&field_expr.expr()?)?.ty;
|
||||
if !ty.is_packed(self.db) {
|
||||
return None;
|
||||
}
|
||||
|
@ -784,7 +793,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
self.type_of_expr(&expr)
|
||||
})
|
||||
// Binding a reference to a packed type is possibly unsafe.
|
||||
.map(|ty| ty.is_packed(self.db))
|
||||
.map(|ty| ty.ty.is_packed(self.db))
|
||||
.unwrap_or(false)
|
||||
|
||||
// FIXME This needs layout computation to be correct. It will highlight
|
||||
|
@ -830,7 +839,7 @@ impl<'db> SemanticsImpl<'db> {
|
|||
}
|
||||
})
|
||||
// Binding a reference to a packed type is possibly unsafe.
|
||||
.map(|ty| ty.is_packed(self.db))
|
||||
.map(|ty| ty.ty.is_packed(self.db))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,46 +116,36 @@ impl SourceAnalyzer {
|
|||
Some(res)
|
||||
}
|
||||
|
||||
pub(crate) fn type_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<Type> {
|
||||
let expr_id = self.expr_id(db, expr)?;
|
||||
let ty = self.infer.as_ref()?[expr_id].clone();
|
||||
Type::new_with_resolver(db, &self.resolver, ty)
|
||||
}
|
||||
|
||||
pub(crate) fn type_of_expr_with_coercion(
|
||||
pub(crate) fn type_of_expr(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
expr: &ast::Expr,
|
||||
) -> Option<(Type, bool)> {
|
||||
) -> Option<(Type, Option<Type>)> {
|
||||
let expr_id = self.expr_id(db, expr)?;
|
||||
let infer = self.infer.as_ref()?;
|
||||
let (ty, coerced) = infer
|
||||
let coerced = infer
|
||||
.expr_adjustments
|
||||
.get(&expr_id)
|
||||
.and_then(|adjusts| adjusts.last().map(|adjust| (&adjust.target, true)))
|
||||
.unwrap_or_else(|| (&infer[expr_id], false));
|
||||
Type::new_with_resolver(db, &self.resolver, ty.clone()).zip(Some(coerced))
|
||||
.and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
|
||||
let ty = infer[expr_id].clone();
|
||||
let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
|
||||
mk_ty(ty.clone()).zip(Some(coerced.and_then(mk_ty)))
|
||||
}
|
||||
|
||||
pub(crate) fn type_of_pat(&self, db: &dyn HirDatabase, pat: &ast::Pat) -> Option<Type> {
|
||||
let pat_id = self.pat_id(pat)?;
|
||||
let ty = self.infer.as_ref()?[pat_id].clone();
|
||||
Type::new_with_resolver(db, &self.resolver, ty)
|
||||
}
|
||||
|
||||
pub(crate) fn type_of_pat_with_coercion(
|
||||
pub(crate) fn type_of_pat(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
pat: &ast::Pat,
|
||||
) -> Option<(Type, bool)> {
|
||||
) -> Option<(Type, Option<Type>)> {
|
||||
let pat_id = self.pat_id(pat)?;
|
||||
let infer = self.infer.as_ref()?;
|
||||
let (ty, coerced) = infer
|
||||
let coerced = infer
|
||||
.pat_adjustments
|
||||
.get(&pat_id)
|
||||
.and_then(|adjusts| adjusts.last().map(|adjust| (&adjust.target, true)))
|
||||
.unwrap_or_else(|| (&infer[pat_id], false));
|
||||
Type::new_with_resolver(db, &self.resolver, ty.clone()).zip(Some(coerced))
|
||||
.and_then(|adjusts| adjusts.last().map(|adjust| adjust.target.clone()));
|
||||
let ty = infer[pat_id].clone();
|
||||
let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
|
||||
mk_ty(ty.clone()).zip(Some(coerced.and_then(mk_ty)))
|
||||
}
|
||||
|
||||
pub(crate) fn type_of_self(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue