mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 12:29:21 +00:00
Type field accesses
This commit is contained in:
parent
07a7285965
commit
55c941cd9f
5 changed files with 54 additions and 5 deletions
|
@ -22,6 +22,10 @@ impl Struct {
|
||||||
self.def_id
|
self.def_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn variant_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<VariantData>> {
|
||||||
|
Ok(db.struct_data(self.def_id)?.variant_data.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn struct_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<StructData>> {
|
pub fn struct_data(&self, db: &impl HirDatabase) -> Cancelable<Arc<StructData>> {
|
||||||
Ok(db.struct_data(self.def_id)?)
|
Ok(db.struct_data(self.def_id)?)
|
||||||
}
|
}
|
||||||
|
@ -162,6 +166,11 @@ impl VariantData {
|
||||||
StructFlavor::Unit => VariantData::Unit,
|
StructFlavor::Unit => VariantData::Unit,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_field_ty(&self, field_name: &str) -> Option<Ty> {
|
||||||
|
self.fields().iter().find(|f| f.name == field_name).map(|f| f.ty.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fields(&self) -> &[StructField] {
|
pub fn fields(&self) -> &[StructField] {
|
||||||
match *self {
|
match *self {
|
||||||
VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields,
|
VariantData::Struct(ref fields) | VariantData::Tuple(ref fields) => fields,
|
||||||
|
|
|
@ -384,6 +384,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn infer_expr_opt(&mut self, expr: Option<ast::Expr>) -> Cancelable<Ty> {
|
||||||
|
if let Some(e) = expr {
|
||||||
|
self.infer_expr(e)
|
||||||
|
} else {
|
||||||
|
Ok(Ty::Unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> {
|
fn infer_expr(&mut self, expr: ast::Expr) -> Cancelable<Ty> {
|
||||||
let ty = match expr {
|
let ty = match expr {
|
||||||
ast::Expr::IfExpr(e) => {
|
ast::Expr::IfExpr(e) => {
|
||||||
|
@ -559,7 +567,29 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
Ty::Unknown
|
Ty::Unknown
|
||||||
}
|
}
|
||||||
ast::Expr::IndexExpr(_e) => Ty::Unknown,
|
ast::Expr::IndexExpr(_e) => Ty::Unknown,
|
||||||
ast::Expr::FieldExpr(_e) => Ty::Unknown,
|
ast::Expr::FieldExpr(e) => {
|
||||||
|
let receiver_ty = self.infer_expr_opt(e.expr())?;
|
||||||
|
if let Some(nr) = e.name_ref() {
|
||||||
|
let text = nr.text();
|
||||||
|
match receiver_ty {
|
||||||
|
Ty::Tuple(fields) => {
|
||||||
|
let i = text.parse::<usize>().ok();
|
||||||
|
i.and_then(|i| fields.get(i).cloned()).unwrap_or(Ty::Unknown)
|
||||||
|
}
|
||||||
|
Ty::Adt { def_id, .. } => {
|
||||||
|
let field_ty = match def_id.resolve(self.db)? {
|
||||||
|
Def::Struct(s) => s.variant_data(self.db)?.get_field_ty(&text),
|
||||||
|
// TODO unions
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
field_ty.unwrap_or(Ty::Unknown)
|
||||||
|
}
|
||||||
|
_ => Ty::Unknown,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ty::Unknown
|
||||||
|
}
|
||||||
|
},
|
||||||
ast::Expr::TryExpr(e) => {
|
ast::Expr::TryExpr(e) => {
|
||||||
let _inner_ty = if let Some(e) = e.expr() {
|
let _inner_ty = if let Some(e) = e.expr() {
|
||||||
self.infer_expr(e)?
|
self.infer_expr(e)?
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
[129; 130) '1': [unknown]
|
[129; 130) '1': [unknown]
|
||||||
[107; 108) 'a': A
|
[107; 108) 'a': A
|
||||||
[127; 128) 'C': [unknown]
|
[127; 128) 'C': [unknown]
|
||||||
[139; 142) 'a.b': [unknown]
|
[139; 142) 'a.b': B
|
||||||
[114; 133) 'A { b:...C(1) }': A
|
[114; 133) 'A { b:...C(1) }': A
|
||||||
[148; 151) 'a.c': [unknown]
|
[148; 151) 'a.c': C
|
||||||
|
[148; 149) 'a': A
|
||||||
|
[139; 140) 'a': A
|
||||||
[72; 154) '{ ...a.c; }': ()
|
[72; 154) '{ ...a.c; }': ()
|
||||||
[96; 97) 'B': [unknown]
|
[96; 97) 'B': [unknown]
|
||||||
[88; 89) '1': [unknown]
|
[88; 89) '1': [unknown]
|
||||||
|
|
|
@ -1123,7 +1123,15 @@ impl<R: TreeRoot<RaTypes>> FieldExprNode<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> FieldExpr<'a> {}
|
impl<'a> FieldExpr<'a> {
|
||||||
|
pub fn expr(self) -> Option<Expr<'a>> {
|
||||||
|
super::child_opt(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name_ref(self) -> Option<NameRef<'a>> {
|
||||||
|
super::child_opt(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FieldPatList
|
// FieldPatList
|
||||||
#[derive(Debug, Clone, Copy,)]
|
#[derive(Debug, Clone, Copy,)]
|
||||||
|
|
|
@ -406,7 +406,7 @@ Grammar(
|
||||||
options: [ "Expr" ],
|
options: [ "Expr" ],
|
||||||
),
|
),
|
||||||
"IndexExpr": (),
|
"IndexExpr": (),
|
||||||
"FieldExpr": (),
|
"FieldExpr": (options: ["Expr", "NameRef"]),
|
||||||
"TryExpr": (options: ["Expr"]),
|
"TryExpr": (options: ["Expr"]),
|
||||||
"CastExpr": (options: ["Expr", "TypeRef"]),
|
"CastExpr": (options: ["Expr", "TypeRef"]),
|
||||||
"RefExpr": (options: ["Expr"]),
|
"RefExpr": (options: ["Expr"]),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue