mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
Record method resolution for try expressions
This commit is contained in:
parent
a7f81e3cdc
commit
4b4eabad3c
2 changed files with 29 additions and 17 deletions
|
@ -938,19 +938,24 @@ impl<'a> InferenceContext<'a> {
|
|||
self.db.trait_data(trait_).associated_type_by_name(&name![Item])
|
||||
}
|
||||
|
||||
fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
|
||||
let trait_ = self.resolve_lang_item(LangItem::Try)?.as_trait()?;
|
||||
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
}
|
||||
|
||||
fn resolve_lang_trait(&self, lang: LangItem) -> Option<TraitId> {
|
||||
self.resolve_lang_item(lang)?.as_trait()
|
||||
}
|
||||
|
||||
fn resolve_ops_try_output(&self) -> Option<TypeAliasId> {
|
||||
self.resolve_output_on(self.resolve_lang_trait(LangItem::Try)?)
|
||||
}
|
||||
|
||||
fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
|
||||
let trait_ = self.resolve_lang_item(LangItem::Neg)?.as_trait()?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
self.resolve_output_on(self.resolve_lang_trait(LangItem::Neg)?)
|
||||
}
|
||||
|
||||
fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
|
||||
let trait_ = self.resolve_lang_item(LangItem::Not)?.as_trait()?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
self.resolve_output_on(self.resolve_lang_trait(LangItem::Not)?)
|
||||
}
|
||||
|
||||
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
|
||||
|
@ -960,7 +965,7 @@ impl<'a> InferenceContext<'a> {
|
|||
.lookup(self.db.upcast())
|
||||
.container
|
||||
else { return None };
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
self.resolve_output_on(trait_)
|
||||
}
|
||||
|
||||
fn resolve_boxed_box(&self) -> Option<AdtId> {
|
||||
|
@ -998,13 +1003,8 @@ impl<'a> InferenceContext<'a> {
|
|||
Some(struct_.into())
|
||||
}
|
||||
|
||||
fn resolve_ops_index(&self) -> Option<TraitId> {
|
||||
self.resolve_lang_item(LangItem::Index)?.as_trait()
|
||||
}
|
||||
|
||||
fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
|
||||
let trait_ = self.resolve_ops_index()?;
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
self.resolve_output_on(self.resolve_lang_trait(LangItem::Index)?)
|
||||
}
|
||||
|
||||
fn resolve_va_list(&self) -> Option<AdtId> {
|
||||
|
|
|
@ -13,6 +13,7 @@ use hir_def::{
|
|||
ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
|
||||
},
|
||||
generics::TypeOrConstParamData,
|
||||
lang_item::LangItem,
|
||||
path::{GenericArg, GenericArgs},
|
||||
resolver::resolver_for_expr,
|
||||
ConstParamId, FieldId, ItemContainerId, Lookup,
|
||||
|
@ -157,7 +158,8 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
|
||||
// The ok-ish type that is expected from the last expression
|
||||
let ok_ty = self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_ok());
|
||||
let ok_ty =
|
||||
self.resolve_associated_type(try_ty.clone(), self.resolve_ops_try_output());
|
||||
|
||||
self.with_breakable_ctx(BreakableKind::Block, ok_ty.clone(), None, |this| {
|
||||
this.infer_expr(*body, &Expectation::has_type(ok_ty));
|
||||
|
@ -593,9 +595,19 @@ impl<'a> InferenceContext<'a> {
|
|||
self.resolve_associated_type(inner_ty, self.resolve_future_future_output())
|
||||
}
|
||||
Expr::Try { expr } => {
|
||||
// FIXME: Note down method resolution her
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok())
|
||||
if let Some(trait_) = self.resolve_lang_trait(LangItem::Try) {
|
||||
if let Some(func) = self.db.trait_data(trait_).method_by_name(&name!(branch)) {
|
||||
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
|
||||
.push(inner_ty.clone())
|
||||
.build();
|
||||
self.write_method_resolution(tgt_expr, func, subst.clone());
|
||||
}
|
||||
let try_output = self.resolve_output_on(trait_);
|
||||
self.resolve_associated_type(inner_ty, try_output)
|
||||
} else {
|
||||
self.err_ty()
|
||||
}
|
||||
}
|
||||
Expr::Cast { expr, type_ref } => {
|
||||
// FIXME: propagate the "castable to" expectation (and find a test case that shows this is necessary)
|
||||
|
@ -744,7 +756,7 @@ impl<'a> InferenceContext<'a> {
|
|||
let base_ty = self.infer_expr_inner(*base, &Expectation::none());
|
||||
let index_ty = self.infer_expr(*index, &Expectation::none());
|
||||
|
||||
if let Some(index_trait) = self.resolve_ops_index() {
|
||||
if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) {
|
||||
let canonicalized = self.canonicalize(base_ty.clone());
|
||||
let receiver_adjustments = method_resolution::resolve_indexing_op(
|
||||
self.db,
|
||||
|
|
Loading…
Reference in a new issue