Type field accesses
This commit is contained in:
parent
07a7285965
commit
55c941cd9f
@ -22,6 +22,10 @@ impl Struct {
|
||||
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>> {
|
||||
Ok(db.struct_data(self.def_id)?)
|
||||
}
|
||||
@ -162,6 +166,11 @@ impl VariantData {
|
||||
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] {
|
||||
match *self {
|
||||
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> {
|
||||
let ty = match expr {
|
||||
ast::Expr::IfExpr(e) => {
|
||||
@ -559,7 +567,29 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
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) => {
|
||||
let _inner_ty = if let Some(e) = e.expr() {
|
||||
self.infer_expr(e)?
|
||||
|
@ -4,9 +4,11 @@
|
||||
[129; 130) '1': [unknown]
|
||||
[107; 108) 'a': A
|
||||
[127; 128) 'C': [unknown]
|
||||
[139; 142) 'a.b': [unknown]
|
||||
[139; 142) 'a.b': B
|
||||
[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; }': ()
|
||||
[96; 97) 'B': [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
|
||||
#[derive(Debug, Clone, Copy,)]
|
||||
|
@ -406,7 +406,7 @@ Grammar(
|
||||
options: [ "Expr" ],
|
||||
),
|
||||
"IndexExpr": (),
|
||||
"FieldExpr": (),
|
||||
"FieldExpr": (options: ["Expr", "NameRef"]),
|
||||
"TryExpr": (options: ["Expr"]),
|
||||
"CastExpr": (options: ["Expr", "TypeRef"]),
|
||||
"RefExpr": (options: ["Expr"]),
|
||||
|
Loading…
x
Reference in New Issue
Block a user