diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index c94c7923c9..f9cb043a7b 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -100,11 +100,11 @@ impl TypeInfo { self.ty } - pub fn coerced(self) -> Option { - self.coerced + pub fn has_coercion(&self) -> bool { + self.coerced.is_some() } - pub fn coerced_or_original(self) -> Type { + pub fn coerced(self) -> Type { self.coerced.unwrap_or(self.ty) } } diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 9d028c2901..9eab563fff 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -555,7 +555,7 @@ fn highlight_method_call( if let Some(receiver_ty) = 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 } } diff --git a/crates/ide_assists/src/handlers/add_explicit_type.rs b/crates/ide_assists/src/handlers/add_explicit_type.rs index 9b5bb71b1b..275ef53861 100644 --- a/crates/ide_assists/src/handlers/add_explicit_type.rs +++ b/crates/ide_assists/src/handlers/add_explicit_type.rs @@ -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)?, (pat, _) => ctx.sema.type_of_pat(&pat)?, } - .coerced_or_original(); + .coerced(); // Unresolved or unnameable types can't be annotated if ty.contains_unknown() || ty.is_closure() { diff --git a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs index b6457da362..a24c9359cb 100644 --- a/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs +++ b/crates/ide_assists/src/handlers/convert_iter_for_each_to_for.rs @@ -86,7 +86,7 @@ fn validate_method_call_expr( let receiver = expr.receiver()?; 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 krate = module.krate(); diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs index 3ac794f45e..a861755cbb 100644 --- a/crates/ide_assists/src/handlers/extract_function.rs +++ b/crates/ide_assists/src/handlers/extract_function.rs @@ -345,7 +345,7 @@ impl FlowKind { FlowKind::Return(Some(expr)) | FlowKind::Break(Some(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 { .. } => { stdx::never!("try does not have defined expr_ty"); diff --git a/crates/ide_assists/src/handlers/extract_variable.rs b/crates/ide_assists/src/handlers/extract_variable.rs index 6d457f3191..c94fa12712 100644 --- a/crates/ide_assists/src/handlers/extract_variable.rs +++ b/crates/ide_assists/src/handlers/extract_variable.rs @@ -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)) .find_map(valid_target_expr)?; 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; } } diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs index 4e060529a9..52f0851295 100644 --- a/crates/ide_assists/src/handlers/fill_match_arms.rs +++ b/crates/ide_assists/src/handlers/fill_match_arms.rs @@ -223,7 +223,7 @@ impl ExtendedEnum { } fn resolve_enum_def(sema: &Semantics, expr: &ast::Expr) -> Option { - 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)), _ => ty.is_bool().then(|| ExtendedEnum::Bool), }) @@ -234,7 +234,7 @@ fn resolve_tuple_of_enum_def( expr: &ast::Expr, ) -> Option> { sema.type_of_expr(expr)? - .ty + .coerced() .tuple_fields(sema.db) .iter() .map(|ty| { diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs index 365f26a02a..d22929206b 100644 --- a/crates/ide_assists/src/handlers/generate_function.rs +++ b/crates/ide_assists/src/handlers/generate_function.rs @@ -331,7 +331,7 @@ fn fn_arg_type( target_module: hir::Module, fn_arg: &ast::Expr, ) -> Option { - let ty = ctx.sema.type_of_expr(fn_arg)?.ty; + let ty = ctx.sema.type_of_expr(fn_arg)?.coerced(); if ty.is_unknown() { return None; } diff --git a/crates/ide_assists/src/handlers/infer_function_return_type.rs b/crates/ide_assists/src/handlers/infer_function_return_type.rs index 0dfce46466..c4bb716071 100644 --- a/crates/ide_assists/src/handlers/infer_function_return_type.rs +++ b/crates/ide_assists/src/handlers/infer_function_return_type.rs @@ -18,7 +18,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; 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 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() { return None; } diff --git a/crates/ide_assists/src/handlers/inline_call.rs b/crates/ide_assists/src/handlers/inline_call.rs index fd098bcaf9..8bafae93f9 100644 --- a/crates/ide_assists/src/handlers/inline_call.rs +++ b/crates/ide_assists/src/handlers/inline_call.rs @@ -190,7 +190,7 @@ pub(crate) fn inline_( let ty = ctx .sema .type_of_expr(&expr) - .and_then(TypeInfo::coerced) + .filter(TypeInfo::has_coercion) .and_then(|_| param_ty); body.push_front( make::let_stmt(pat, ty, Some(expr)).clone_for_update().into(), diff --git a/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs b/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs index b67ec8b14c..54c3f4a2a2 100644 --- a/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs +++ b/crates/ide_assists/src/handlers/replace_for_loop_with_for_each.rs @@ -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 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 krate = scope.module()?.krate(); let traits_in_scope = scope.traits_in_scope(); @@ -110,7 +110,7 @@ fn is_ref_and_impls_iter_method( /// Whether iterable implements core::Iterator fn impls_core_iter(sema: &hir::Semantics, iterable: &ast::Expr) -> bool { let it_typ = match sema.type_of_expr(iterable) { - Some(it) => it.ty, + Some(it) => it.coerced(), None => return false, }; diff --git a/crates/ide_assists/src/handlers/replace_if_let_with_match.rs b/crates/ide_assists/src/handlers/replace_if_let_with_match.rs index a458bced0c..45b3ce2990 100644 --- a/crates/ide_assists/src/handlers/replace_if_let_with_match.rs +++ b/crates/ide_assists/src/handlers/replace_if_let_with_match.rs @@ -127,7 +127,7 @@ fn make_else_arm( let pattern = if let [(Either::Left(pat), _)] = conditionals { ctx.sema .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)) } else { None @@ -268,7 +268,7 @@ fn binds_name(pat: &ast::Pat) -> bool { fn is_sad_pat(sema: &hir::Semantics, pat: &ast::Pat) -> bool { 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())) } diff --git a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs index 2f95af8ef2..190f302d5c 100644 --- a/crates/ide_assists/src/handlers/replace_let_with_if_let.rs +++ b/crates/ide_assists/src/handlers/replace_let_with_if_let.rs @@ -49,8 +49,9 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) -> target, |edit| { let ty = ctx.sema.type_of_expr(&init); - let happy_variant = - ty.and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.ty)).map(|it| it.happy_case()); + let happy_variant = ty + .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.coerced())) + .map(|it| it.happy_case()); let pat = match happy_variant { None => original_pat, Some(var_name) => { diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs index 2e58c58c19..1efac04db9 100644 --- a/crates/ide_assists/src/utils.rs +++ b/crates/ide_assists/src/utils.rs @@ -270,12 +270,10 @@ fn invert_special_case(sema: &Semantics, expr: &ast::Expr) -> Opti fn bin_impls_ord(sema: &Semantics, bin: &ast::BinExpr) -> bool { match ( - bin.lhs().and_then(|lhs| sema.type_of_expr(&lhs)), - bin.rhs().and_then(|rhs| sema.type_of_expr(&rhs)), + bin.lhs().and_then(|lhs| sema.type_of_expr(&lhs)).map(hir::TypeInfo::coerced), + 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, .. })) - if lhs_ty == rhs_ty => - { + (Some(lhs_ty), Some(rhs_ty)) if lhs_ty == rhs_ty => { let krate = sema.scope(bin.syntax()).module().map(|it| it.krate()); let ord_trait = FamousDefs(sema, krate).core_cmp_Ord(); ord_trait.map_or(false, |ord_trait| { diff --git a/crates/ide_assists/src/utils/suggest_name.rs b/crates/ide_assists/src/utils/suggest_name.rs index da5370a6d0..6a2f086382 100644 --- a/crates/ide_assists/src/utils/suggest_name.rs +++ b/crates/ide_assists/src/utils/suggest_name.rs @@ -197,7 +197,7 @@ fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option { 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)? }, ast::MethodCallExpr(method) => sema.resolve_method_call_as_callable(&method)?, @@ -225,7 +225,7 @@ fn var_name_from_pat(pat: &ast::Pat) -> Option { } fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option { - let ty = sema.type_of_expr(expr)?.ty; + let ty = sema.type_of_expr(expr)?.coerced(); let ty = ty.remove_ref().unwrap_or(ty); name_of_type(&ty, sema.db) diff --git a/crates/ide_db/src/call_info.rs b/crates/ide_db/src/call_info.rs index ea2662185f..a406e0d6f5 100644 --- a/crates/ide_db/src/call_info.rs +++ b/crates/ide_db/src/call_info.rs @@ -118,7 +118,9 @@ fn call_info_impl( let calling_node = FnCallNode::with_node(&token.parent()?)?; 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)?, }; let active_param = if let Some(arg_list) = calling_node.arg_list() { diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs index 6e174ffb84..52cd99ec91 100644 --- a/crates/ide_db/src/helpers/import_assets.rs +++ b/crates/ide_db/src/helpers/import_assets.rs @@ -543,7 +543,7 @@ impl ImportCandidate { match sema.resolve_method_call(method_call) { Some(_) => None, 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()), })), } diff --git a/crates/ide_diagnostics/src/handlers/no_such_field.rs b/crates/ide_diagnostics/src/handlers/no_such_field.rs index cf0d5f9b25..2518dd8bb6 100644 --- a/crates/ide_diagnostics/src/handlers/no_such_field.rs +++ b/crates/ide_diagnostics/src/handlers/no_such_field.rs @@ -62,7 +62,7 @@ fn missing_record_expr_field_fixes( }; 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() { return None; }