Revise TypeInfo::ty usage

This commit is contained in:
Lukas Wirth 2021-08-03 17:24:43 +02:00
parent 25ff7171c4
commit 8afa2722b2
18 changed files with 30 additions and 29 deletions

View file

@ -100,11 +100,11 @@ impl TypeInfo {
self.ty self.ty
} }
pub fn coerced(self) -> Option<Type> { pub fn has_coercion(&self) -> bool {
self.coerced self.coerced.is_some()
} }
pub fn coerced_or_original(self) -> Type { pub fn coerced(self) -> Type {
self.coerced.unwrap_or(self.ty) self.coerced.unwrap_or(self.ty)
} }
} }

View file

@ -555,7 +555,7 @@ fn highlight_method_call(
if let Some(receiver_ty) = if let Some(receiver_ty) =
method_call.receiver().and_then(|it| sema.type_of_expr(&it)) method_call.receiver().and_then(|it| sema.type_of_expr(&it))
{ {
if !receiver_ty.ty.is_copy(sema.db) { if !receiver_ty.coerced().is_copy(sema.db) {
h |= HlMod::Consuming h |= HlMod::Consuming
} }
} }

View file

@ -57,7 +57,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
(ast::Pat::IdentPat(_), Some(expr)) => ctx.sema.type_of_expr(&expr)?, (ast::Pat::IdentPat(_), Some(expr)) => ctx.sema.type_of_expr(&expr)?,
(pat, _) => ctx.sema.type_of_pat(&pat)?, (pat, _) => ctx.sema.type_of_pat(&pat)?,
} }
.coerced_or_original(); .coerced();
// Unresolved or unnameable types can't be annotated // Unresolved or unnameable types can't be annotated
if ty.contains_unknown() || ty.is_closure() { if ty.contains_unknown() || ty.is_closure() {

View file

@ -86,7 +86,7 @@ fn validate_method_call_expr(
let receiver = expr.receiver()?; let receiver = expr.receiver()?;
let expr = ast::Expr::MethodCallExpr(expr); let expr = ast::Expr::MethodCallExpr(expr);
let it_type = sema.type_of_expr(&receiver)?.ty; let it_type = sema.type_of_expr(&receiver)?.coerced();
let module = sema.scope(receiver.syntax()).module()?; let module = sema.scope(receiver.syntax()).module()?;
let krate = module.krate(); let krate = module.krate();

View file

@ -345,7 +345,7 @@ impl FlowKind {
FlowKind::Return(Some(expr)) FlowKind::Return(Some(expr))
| FlowKind::Break(Some(expr)) | FlowKind::Break(Some(expr))
| FlowKind::TryReturn { expr, .. } => { | FlowKind::TryReturn { expr, .. } => {
ctx.sema.type_of_expr(expr).map(TypeInfo::coerced_or_original) ctx.sema.type_of_expr(expr).map(TypeInfo::coerced)
} }
FlowKind::Try { .. } => { FlowKind::Try { .. } => {
stdx::never!("try does not have defined expr_ty"); stdx::never!("try does not have defined expr_ty");

View file

@ -40,7 +40,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext) -> Option
.take_while(|it| it.text_range().contains_range(ctx.frange.range)) .take_while(|it| it.text_range().contains_range(ctx.frange.range))
.find_map(valid_target_expr)?; .find_map(valid_target_expr)?;
if let Some(ty_info) = ctx.sema.type_of_expr(&to_extract) { if let Some(ty_info) = ctx.sema.type_of_expr(&to_extract) {
if ty_info.ty.is_unit() { if ty_info.coerced().is_unit() {
return None; return None;
} }
} }

View file

@ -223,7 +223,7 @@ impl ExtendedEnum {
} }
fn resolve_enum_def(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<ExtendedEnum> { fn resolve_enum_def(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Option<ExtendedEnum> {
sema.type_of_expr(expr)?.ty.autoderef(sema.db).find_map(|ty| match ty.as_adt() { sema.type_of_expr(expr)?.coerced().autoderef(sema.db).find_map(|ty| match ty.as_adt() {
Some(Adt::Enum(e)) => Some(ExtendedEnum::Enum(e)), Some(Adt::Enum(e)) => Some(ExtendedEnum::Enum(e)),
_ => ty.is_bool().then(|| ExtendedEnum::Bool), _ => ty.is_bool().then(|| ExtendedEnum::Bool),
}) })
@ -234,7 +234,7 @@ fn resolve_tuple_of_enum_def(
expr: &ast::Expr, expr: &ast::Expr,
) -> Option<Vec<ExtendedEnum>> { ) -> Option<Vec<ExtendedEnum>> {
sema.type_of_expr(expr)? sema.type_of_expr(expr)?
.ty .coerced()
.tuple_fields(sema.db) .tuple_fields(sema.db)
.iter() .iter()
.map(|ty| { .map(|ty| {

View file

@ -331,7 +331,7 @@ fn fn_arg_type(
target_module: hir::Module, target_module: hir::Module,
fn_arg: &ast::Expr, fn_arg: &ast::Expr,
) -> Option<String> { ) -> Option<String> {
let ty = ctx.sema.type_of_expr(fn_arg)?.ty; let ty = ctx.sema.type_of_expr(fn_arg)?.coerced();
if ty.is_unknown() { if ty.is_unknown() {
return None; return None;
} }

View file

@ -18,7 +18,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
pub(crate) fn infer_function_return_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { pub(crate) fn infer_function_return_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let (fn_type, tail_expr, builder_edit_pos) = extract_tail(ctx)?; let (fn_type, tail_expr, builder_edit_pos) = extract_tail(ctx)?;
let module = ctx.sema.scope(tail_expr.syntax()).module()?; let module = ctx.sema.scope(tail_expr.syntax()).module()?;
let ty = ctx.sema.type_of_expr(&tail_expr)?.ty; let ty = ctx.sema.type_of_expr(&tail_expr)?.coerced();
if ty.is_unit() { if ty.is_unit() {
return None; return None;
} }

View file

@ -190,7 +190,7 @@ pub(crate) fn inline_(
let ty = ctx let ty = ctx
.sema .sema
.type_of_expr(&expr) .type_of_expr(&expr)
.and_then(TypeInfo::coerced) .filter(TypeInfo::has_coercion)
.and_then(|_| param_ty); .and_then(|_| param_ty);
body.push_front( body.push_front(
make::let_stmt(pat, ty, Some(expr)).clone_for_update().into(), make::let_stmt(pat, ty, Some(expr)).clone_for_update().into(),

View file

@ -80,7 +80,7 @@ fn is_ref_and_impls_iter_method(
}; };
let wanted_method = if ref_expr.mut_token().is_some() { known::iter_mut } else { known::iter }; let wanted_method = if ref_expr.mut_token().is_some() { known::iter_mut } else { known::iter };
let expr_behind_ref = ref_expr.expr()?; let expr_behind_ref = ref_expr.expr()?;
let ty = sema.type_of_expr(&expr_behind_ref)?.ty; let ty = sema.type_of_expr(&expr_behind_ref)?.coerced();
let scope = sema.scope(iterable.syntax()); let scope = sema.scope(iterable.syntax());
let krate = scope.module()?.krate(); let krate = scope.module()?.krate();
let traits_in_scope = scope.traits_in_scope(); let traits_in_scope = scope.traits_in_scope();
@ -110,7 +110,7 @@ fn is_ref_and_impls_iter_method(
/// Whether iterable implements core::Iterator /// Whether iterable implements core::Iterator
fn impls_core_iter(sema: &hir::Semantics<ide_db::RootDatabase>, iterable: &ast::Expr) -> bool { fn impls_core_iter(sema: &hir::Semantics<ide_db::RootDatabase>, iterable: &ast::Expr) -> bool {
let it_typ = match sema.type_of_expr(iterable) { let it_typ = match sema.type_of_expr(iterable) {
Some(it) => it.ty, Some(it) => it.coerced(),
None => return false, None => return false,
}; };

View file

@ -127,7 +127,7 @@ fn make_else_arm(
let pattern = if let [(Either::Left(pat), _)] = conditionals { let pattern = if let [(Either::Left(pat), _)] = conditionals {
ctx.sema ctx.sema
.type_of_pat(&pat) .type_of_pat(&pat)
.and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.ty)) .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.coerced()))
.zip(Some(pat)) .zip(Some(pat))
} else { } else {
None None
@ -268,7 +268,7 @@ fn binds_name(pat: &ast::Pat) -> bool {
fn is_sad_pat(sema: &hir::Semantics<RootDatabase>, pat: &ast::Pat) -> bool { fn is_sad_pat(sema: &hir::Semantics<RootDatabase>, pat: &ast::Pat) -> bool {
sema.type_of_pat(pat) sema.type_of_pat(pat)
.and_then(|ty| TryEnum::from_ty(sema, &ty.ty)) .and_then(|ty| TryEnum::from_ty(sema, &ty.coerced()))
.map_or(false, |it| does_pat_match_variant(pat, &it.sad_pattern())) .map_or(false, |it| does_pat_match_variant(pat, &it.sad_pattern()))
} }

View file

@ -49,8 +49,9 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
target, target,
|edit| { |edit| {
let ty = ctx.sema.type_of_expr(&init); let ty = ctx.sema.type_of_expr(&init);
let happy_variant = let happy_variant = ty
ty.and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.ty)).map(|it| it.happy_case()); .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.coerced()))
.map(|it| it.happy_case());
let pat = match happy_variant { let pat = match happy_variant {
None => original_pat, None => original_pat,
Some(var_name) => { Some(var_name) => {

View file

@ -270,12 +270,10 @@ fn invert_special_case(sema: &Semantics<RootDatabase>, expr: &ast::Expr) -> Opti
fn bin_impls_ord(sema: &Semantics<RootDatabase>, bin: &ast::BinExpr) -> bool { fn bin_impls_ord(sema: &Semantics<RootDatabase>, bin: &ast::BinExpr) -> bool {
match ( match (
bin.lhs().and_then(|lhs| sema.type_of_expr(&lhs)), bin.lhs().and_then(|lhs| sema.type_of_expr(&lhs)).map(hir::TypeInfo::coerced),
bin.rhs().and_then(|rhs| sema.type_of_expr(&rhs)), bin.rhs().and_then(|rhs| sema.type_of_expr(&rhs)).map(hir::TypeInfo::coerced),
) { ) {
(Some(hir::TypeInfo { ty: lhs_ty, .. }), Some(hir::TypeInfo { ty: rhs_ty, .. })) (Some(lhs_ty), Some(rhs_ty)) if lhs_ty == rhs_ty => {
if lhs_ty == rhs_ty =>
{
let krate = sema.scope(bin.syntax()).module().map(|it| it.krate()); let krate = sema.scope(bin.syntax()).module().map(|it| it.krate());
let ord_trait = FamousDefs(sema, krate).core_cmp_Ord(); let ord_trait = FamousDefs(sema, krate).core_cmp_Ord();
ord_trait.map_or(false, |ord_trait| { ord_trait.map_or(false, |ord_trait| {

View file

@ -197,7 +197,7 @@ fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<St
match args_parent { match args_parent {
ast::CallExpr(call) => { ast::CallExpr(call) => {
let func = call.expr()?; let func = call.expr()?;
let func_ty = sema.type_of_expr(&func)?.ty; let func_ty = sema.type_of_expr(&func)?.coerced();
func_ty.as_callable(sema.db)? func_ty.as_callable(sema.db)?
}, },
ast::MethodCallExpr(method) => sema.resolve_method_call_as_callable(&method)?, ast::MethodCallExpr(method) => sema.resolve_method_call_as_callable(&method)?,
@ -225,7 +225,7 @@ fn var_name_from_pat(pat: &ast::Pat) -> Option<ast::Name> {
} }
fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<String> { fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<String> {
let ty = sema.type_of_expr(expr)?.ty; let ty = sema.type_of_expr(expr)?.coerced();
let ty = ty.remove_ref().unwrap_or(ty); let ty = ty.remove_ref().unwrap_or(ty);
name_of_type(&ty, sema.db) name_of_type(&ty, sema.db)

View file

@ -118,7 +118,9 @@ fn call_info_impl(
let calling_node = FnCallNode::with_node(&token.parent()?)?; let calling_node = FnCallNode::with_node(&token.parent()?)?;
let callable = match &calling_node { let callable = match &calling_node {
FnCallNode::CallExpr(call) => sema.type_of_expr(&call.expr()?)?.ty.as_callable(sema.db)?, FnCallNode::CallExpr(call) => {
sema.type_of_expr(&call.expr()?)?.coerced().as_callable(sema.db)?
}
FnCallNode::MethodCallExpr(call) => sema.resolve_method_call_as_callable(call)?, FnCallNode::MethodCallExpr(call) => sema.resolve_method_call_as_callable(call)?,
}; };
let active_param = if let Some(arg_list) = calling_node.arg_list() { let active_param = if let Some(arg_list) = calling_node.arg_list() {

View file

@ -543,7 +543,7 @@ impl ImportCandidate {
match sema.resolve_method_call(method_call) { match sema.resolve_method_call(method_call) {
Some(_) => None, Some(_) => None,
None => Some(Self::TraitMethod(TraitImportCandidate { None => Some(Self::TraitMethod(TraitImportCandidate {
receiver_ty: sema.type_of_expr(&method_call.receiver()?)?.ty, receiver_ty: sema.type_of_expr(&method_call.receiver()?)?.coerced(),
assoc_item_name: NameToImport::Exact(method_call.name_ref()?.to_string()), assoc_item_name: NameToImport::Exact(method_call.name_ref()?.to_string()),
})), })),
} }

View file

@ -62,7 +62,7 @@ fn missing_record_expr_field_fixes(
}; };
let def_file_id = def_file_id.original_file(sema.db); let def_file_id = def_file_id.original_file(sema.db);
let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?.ty; let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?.coerced();
if new_field_type.is_unknown() { if new_field_type.is_unknown() {
return None; return None;
} }