about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-ty/src/display.rs40
-rw-r--r--crates/hir-ty/src/tests.rs4
-rw-r--r--crates/ide-assists/src/handlers/add_explicit_type.rs2
-rw-r--r--crates/ide-assists/src/handlers/add_return_type.rs2
-rw-r--r--crates/ide-assists/src/handlers/extract_function.rs2
-rw-r--r--crates/ide-assists/src/handlers/generate_constant.rs3
-rw-r--r--crates/ide-assists/src/handlers/generate_enum_variant.rs2
-rw-r--r--crates/ide-assists/src/handlers/generate_function.rs6
-rw-r--r--crates/ide-assists/src/handlers/promote_local_to_const.rs14
-rw-r--r--crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs2
-rw-r--r--crates/ide-completion/src/completions/fn_param.rs2
-rw-r--r--crates/ide-completion/src/completions/type.rs2
-rw-r--r--crates/ide-db/src/path_transform.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/missing_fields.rs4
-rw-r--r--crates/ide-diagnostics/src/handlers/no_such_field.rs2
15 files changed, 62 insertions, 29 deletions
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index f892a815197..0eef25102e8 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -150,6 +150,7 @@ pub trait HirDisplay {
         &'a self,
         db: &'a dyn HirDatabase,
         module_id: ModuleId,
+        allow_opaque: bool,
     ) -> Result<String, DisplaySourceCodeError> {
         let mut result = String::new();
         match self.hir_fmt(&mut HirFormatter {
@@ -160,7 +161,7 @@ pub trait HirDisplay {
             max_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
-            display_target: DisplayTarget::SourceCode { module_id },
+            display_target: DisplayTarget::SourceCode { module_id, allow_opaque },
         }) {
             Ok(()) => {}
             Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
@@ -249,18 +250,26 @@ pub enum DisplayTarget {
     Diagnostics,
     /// Display types for inserting them in source files.
     /// The generated code should compile, so paths need to be qualified.
-    SourceCode { module_id: ModuleId },
+    SourceCode { module_id: ModuleId, allow_opaque: bool },
     /// Only for test purpose to keep real types
     Test,
 }
 
 impl DisplayTarget {
-    fn is_source_code(&self) -> bool {
+    fn is_source_code(self) -> bool {
         matches!(self, Self::SourceCode { .. })
     }
-    fn is_test(&self) -> bool {
+
+    fn is_test(self) -> bool {
         matches!(self, Self::Test)
     }
+
+    fn allows_opaque(self) -> bool {
+        match self {
+            Self::SourceCode { allow_opaque, .. } => allow_opaque,
+            _ => true,
+        }
+    }
 }
 
 #[derive(Debug)]
@@ -268,6 +277,7 @@ pub enum DisplaySourceCodeError {
     PathNotFound,
     UnknownType,
     Generator,
+    OpaqueType,
 }
 
 pub enum HirDisplayError {
@@ -768,7 +778,7 @@ impl HirDisplay for Ty {
                         };
                         write!(f, "{name}")?;
                     }
-                    DisplayTarget::SourceCode { module_id } => {
+                    DisplayTarget::SourceCode { module_id, allow_opaque: _ } => {
                         if let Some(path) = find_path::find_path(
                             db.upcast(),
                             ItemInNs::Types((*def_id).into()),
@@ -906,6 +916,11 @@ impl HirDisplay for Ty {
                 f.end_location_link();
             }
             TyKind::OpaqueType(opaque_ty_id, parameters) => {
+                if !f.display_target.allows_opaque() {
+                    return Err(HirDisplayError::DisplaySourceCodeError(
+                        DisplaySourceCodeError::OpaqueType,
+                    ));
+                }
                 let impl_trait_id = db.lookup_intern_impl_trait_id((*opaque_ty_id).into());
                 match impl_trait_id {
                     ImplTraitId::ReturnTypeImplTrait(func, idx) => {
@@ -953,8 +968,14 @@ impl HirDisplay for Ty {
                 }
             }
             TyKind::Closure(id, substs) => {
-                if f.display_target.is_source_code() && f.closure_style != ClosureStyle::ImplFn {
-                    never!("Only `impl Fn` is valid for displaying closures in source code");
+                if f.display_target.is_source_code() {
+                    if !f.display_target.allows_opaque() {
+                        return Err(HirDisplayError::DisplaySourceCodeError(
+                            DisplaySourceCodeError::OpaqueType,
+                        ));
+                    } else if f.closure_style != ClosureStyle::ImplFn {
+                        never!("Only `impl Fn` is valid for displaying closures in source code");
+                    }
                 }
                 match f.closure_style {
                     ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
@@ -1053,6 +1074,11 @@ impl HirDisplay for Ty {
             }
             TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
             TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
+                if !f.display_target.allows_opaque() {
+                    return Err(HirDisplayError::DisplaySourceCodeError(
+                        DisplaySourceCodeError::OpaqueType,
+                    ));
+                }
                 let impl_trait_id = db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into());
                 match impl_trait_id {
                     ImplTraitId::ReturnTypeImplTrait(func, idx) => {
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 1e46bb1d040..245617ab82e 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -159,7 +159,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
             let range = node.as_ref().original_file_range(&db);
             if let Some(expected) = types.remove(&range) {
                 let actual = if display_source {
-                    ty.display_source_code(&db, def.module(&db)).unwrap()
+                    ty.display_source_code(&db, def.module(&db), true).unwrap()
                 } else {
                     ty.display_test(&db).to_string()
                 };
@@ -175,7 +175,7 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
             let range = node.as_ref().original_file_range(&db);
             if let Some(expected) = types.remove(&range) {
                 let actual = if display_source {
-                    ty.display_source_code(&db, def.module(&db)).unwrap()
+                    ty.display_source_code(&db, def.module(&db), true).unwrap()
                 } else {
                     ty.display_test(&db).to_string()
                 };
diff --git a/crates/ide-assists/src/handlers/add_explicit_type.rs b/crates/ide-assists/src/handlers/add_explicit_type.rs
index 785ae3d09c6..8bc285614e0 100644
--- a/crates/ide-assists/src/handlers/add_explicit_type.rs
+++ b/crates/ide-assists/src/handlers/add_explicit_type.rs
@@ -69,7 +69,7 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
         return None;
     }
 
-    let inferred_type = ty.display_source_code(ctx.db(), module.into()).ok()?;
+    let inferred_type = ty.display_source_code(ctx.db(), module.into(), false).ok()?;
     acc.add(
         AssistId("add_explicit_type", AssistKind::RefactorRewrite),
         format!("Insert explicit type `{inferred_type}`"),
diff --git a/crates/ide-assists/src/handlers/add_return_type.rs b/crates/ide-assists/src/handlers/add_return_type.rs
index 879c478acf8..9e1022d809d 100644
--- a/crates/ide-assists/src/handlers/add_return_type.rs
+++ b/crates/ide-assists/src/handlers/add_return_type.rs
@@ -22,7 +22,7 @@ pub(crate) fn add_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
     if ty.is_unit() {
         return None;
     }
-    let ty = ty.display_source_code(ctx.db(), module.into()).ok()?;
+    let ty = ty.display_source_code(ctx.db(), module.into(), true).ok()?;
 
     acc.add(
         AssistId("add_return_type", AssistKind::RefactorRewrite),
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs
index bfa2890676b..728018506d1 100644
--- a/crates/ide-assists/src/handlers/extract_function.rs
+++ b/crates/ide-assists/src/handlers/extract_function.rs
@@ -1884,7 +1884,7 @@ fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr
 }
 
 fn format_type(ty: &hir::Type, ctx: &AssistContext<'_>, module: hir::Module) -> String {
-    ty.display_source_code(ctx.db(), module.into()).ok().unwrap_or_else(|| "_".to_string())
+    ty.display_source_code(ctx.db(), module.into(), true).ok().unwrap_or_else(|| "_".to_string())
 }
 
 fn make_ty(ty: &hir::Type, ctx: &AssistContext<'_>, module: hir::Module) -> ast::Type {
diff --git a/crates/ide-assists/src/handlers/generate_constant.rs b/crates/ide-assists/src/handlers/generate_constant.rs
index 57bb679729f..eccd7675fba 100644
--- a/crates/ide-assists/src/handlers/generate_constant.rs
+++ b/crates/ide-assists/src/handlers/generate_constant.rs
@@ -46,7 +46,8 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
     let ty = ctx.sema.type_of_expr(&expr)?;
     let scope = ctx.sema.scope(statement.syntax())?;
     let constant_module = scope.module();
-    let type_name = ty.original().display_source_code(ctx.db(), constant_module.into()).ok()?;
+    let type_name =
+        ty.original().display_source_code(ctx.db(), constant_module.into(), false).ok()?;
     let target = statement.syntax().parent()?.text_range();
     let path = constant_token.syntax().ancestors().find_map(ast::Path::cast)?;
 
diff --git a/crates/ide-assists/src/handlers/generate_enum_variant.rs b/crates/ide-assists/src/handlers/generate_enum_variant.rs
index cd037f7492c..184f523e01b 100644
--- a/crates/ide-assists/src/handlers/generate_enum_variant.rs
+++ b/crates/ide-assists/src/handlers/generate_enum_variant.rs
@@ -192,7 +192,7 @@ fn expr_ty(
     scope: &hir::SemanticsScope<'_>,
 ) -> Option<ast::Type> {
     let ty = ctx.sema.type_of_expr(&arg).map(|it| it.adjusted())?;
-    let text = ty.display_source_code(ctx.db(), scope.module().into()).ok()?;
+    let text = ty.display_source_code(ctx.db(), scope.module().into(), false).ok()?;
     Some(make::ty(&text))
 }
 
diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs
index 2372fe28e19..a5556878be6 100644
--- a/crates/ide-assists/src/handlers/generate_function.rs
+++ b/crates/ide-assists/src/handlers/generate_function.rs
@@ -438,7 +438,7 @@ fn make_return_type(
             Some(ty) if ty.is_unit() => (None, false),
             Some(ty) => {
                 necessary_generic_params.extend(ty.generic_params(ctx.db()));
-                let rendered = ty.display_source_code(ctx.db(), target_module.into());
+                let rendered = ty.display_source_code(ctx.db(), target_module.into(), true);
                 match rendered {
                     Ok(rendered) => (Some(make::ty(&rendered)), false),
                     Err(_) => (Some(make::ty_placeholder()), true),
@@ -992,9 +992,9 @@ fn fn_arg_type(
             let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate());
             convert_reference_type(ty.strip_references(), ctx.db(), famous_defs)
                 .map(|conversion| conversion.convert_type(ctx.db()))
-                .or_else(|| ty.display_source_code(ctx.db(), target_module.into()).ok())
+                .or_else(|| ty.display_source_code(ctx.db(), target_module.into(), true).ok())
         } else {
-            ty.display_source_code(ctx.db(), target_module.into()).ok()
+            ty.display_source_code(ctx.db(), target_module.into(), true).ok()
         }
     }
 
diff --git a/crates/ide-assists/src/handlers/promote_local_to_const.rs b/crates/ide-assists/src/handlers/promote_local_to_const.rs
index cbbea6c1e63..23153b4c566 100644
--- a/crates/ide-assists/src/handlers/promote_local_to_const.rs
+++ b/crates/ide-assists/src/handlers/promote_local_to_const.rs
@@ -57,11 +57,13 @@ pub(crate) fn promote_local_to_const(acc: &mut Assists, ctx: &AssistContext<'_>)
     let local = ctx.sema.to_def(&pat)?;
     let ty = ctx.sema.type_of_pat(&pat.into())?.original;
 
-    if ty.contains_unknown() || ty.is_closure() {
-        cov_mark::hit!(promote_lcoal_not_applicable_if_ty_not_inferred);
-        return None;
-    }
-    let ty = ty.display_source_code(ctx.db(), module.into()).ok()?;
+    let ty = match ty.display_source_code(ctx.db(), module.into(), false) {
+        Ok(ty) => ty,
+        Err(_) => {
+            cov_mark::hit!(promote_local_not_applicable_if_ty_not_inferred);
+            return None;
+        }
+    };
 
     let initializer = let_stmt.initializer()?;
     if !is_body_const(&ctx.sema, &initializer) {
@@ -187,7 +189,7 @@ fn foo() {
 
     #[test]
     fn not_applicable_unknown_ty() {
-        cov_mark::check!(promote_lcoal_not_applicable_if_ty_not_inferred);
+        cov_mark::check!(promote_local_not_applicable_if_ty_not_inferred);
         check_assist_not_applicable(
             promote_local_to_const,
             r"
diff --git a/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs b/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs
index 6626ce07959..43a97d7d3a5 100644
--- a/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs
+++ b/crates/ide-assists/src/handlers/replace_turbofish_with_explicit_type.rs
@@ -55,7 +55,7 @@ pub(crate) fn replace_turbofish_with_explicit_type(
     let returned_type = match ctx.sema.type_of_expr(&initializer) {
         Some(returned_type) if !returned_type.original.contains_unknown() => {
             let module = ctx.sema.scope(let_stmt.syntax())?.module();
-            returned_type.original.display_source_code(ctx.db(), module.into()).ok()?
+            returned_type.original.display_source_code(ctx.db(), module.into(), false).ok()?
         }
         _ => {
             cov_mark::hit!(fallback_to_turbofish_type_if_type_info_not_available);
diff --git a/crates/ide-completion/src/completions/fn_param.rs b/crates/ide-completion/src/completions/fn_param.rs
index d8b8a190eb8..734e1bed8df 100644
--- a/crates/ide-completion/src/completions/fn_param.rs
+++ b/crates/ide-completion/src/completions/fn_param.rs
@@ -127,7 +127,7 @@ fn params_from_stmt_list_scope(
         let module = scope.module().into();
         scope.process_all_names(&mut |name, def| {
             if let hir::ScopeDef::Local(local) = def {
-                if let Ok(ty) = local.ty(ctx.db).display_source_code(ctx.db, module) {
+                if let Ok(ty) = local.ty(ctx.db).display_source_code(ctx.db, module, true) {
                     cb(name, ty);
                 }
             }
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs
index 2ad9520cd6e..e4705475638 100644
--- a/crates/ide-completion/src/completions/type.rs
+++ b/crates/ide-completion/src/completions/type.rs
@@ -242,7 +242,7 @@ pub(crate) fn complete_ascribed_type(
         }
     }?
     .adjusted();
-    let ty_string = x.display_source_code(ctx.db, ctx.module.into()).ok()?;
+    let ty_string = x.display_source_code(ctx.db, ctx.module.into(), true).ok()?;
     acc.add(render_type_inference(ty_string, ctx));
     None
 }
diff --git a/crates/ide-db/src/path_transform.rs b/crates/ide-db/src/path_transform.rs
index 6402a84a68b..0ee627a44c6 100644
--- a/crates/ide-db/src/path_transform.rs
+++ b/crates/ide-db/src/path_transform.rs
@@ -116,7 +116,9 @@ impl<'a> PathTransform<'a> {
                         Some((
                             k,
                             ast::make::ty(
-                                &default.display_source_code(db, source_module.into()).ok()?,
+                                &default
+                                    .display_source_code(db, source_module.into(), false)
+                                    .ok()?,
                             ),
                         ))
                     }
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index 5c4327ff934..a33a2cd85e2 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -176,7 +176,9 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
 fn make_ty(ty: &hir::Type, db: &dyn HirDatabase, module: hir::Module) -> ast::Type {
     let ty_str = match ty.as_adt() {
         Some(adt) => adt.name(db).to_string(),
-        None => ty.display_source_code(db, module.into()).ok().unwrap_or_else(|| "_".to_string()),
+        None => {
+            ty.display_source_code(db, module.into(), false).ok().unwrap_or_else(|| "_".to_string())
+        }
     };
 
     make::ty(&ty_str)
diff --git a/crates/ide-diagnostics/src/handlers/no_such_field.rs b/crates/ide-diagnostics/src/handlers/no_such_field.rs
index 24c521ed1a8..625c95ce201 100644
--- a/crates/ide-diagnostics/src/handlers/no_such_field.rs
+++ b/crates/ide-diagnostics/src/handlers/no_such_field.rs
@@ -69,7 +69,7 @@ fn missing_record_expr_field_fixes(
     let new_field = make::record_field(
         None,
         make::name(record_expr_field.field_name()?.ident_token()?.text()),
-        make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
+        make::ty(&new_field_type.display_source_code(sema.db, module.into(), true).ok()?),
     );
 
     let last_field = record_fields.fields().last()?;