Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/inlay_hints.rs')
-rw-r--r--crates/ide/src/inlay_hints.rs95
1 files changed, 75 insertions, 20 deletions
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 6babdff52a..82704af647 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -5,21 +5,21 @@ use std::{
use either::Either;
use hir::{
- sym, ClosureStyle, DisplayTarget, HasVisibility, HirDisplay, HirDisplayError, HirWrite,
- ModuleDef, ModuleDefId, Semantics,
+ ClosureStyle, DisplayTarget, EditionedFileId, HasVisibility, HirDisplay, HirDisplayError,
+ HirWrite, ModuleDef, ModuleDefId, Semantics, sym,
};
-use ide_db::{famous_defs::FamousDefs, FileRange, RootDatabase};
-use ide_db::{text_edit::TextEdit, FxHashSet};
+use ide_db::{FileRange, RootDatabase, famous_defs::FamousDefs, text_edit::TextEditBuilder};
+use ide_db::{FxHashSet, text_edit::TextEdit};
use itertools::Itertools;
-use smallvec::{smallvec, SmallVec};
-use span::EditionedFileId;
+use smallvec::{SmallVec, smallvec};
use stdx::never;
use syntax::{
+ SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent,
ast::{self, AstNode, HasGenericParams},
- format_smolstr, match_ast, SmolStr, SyntaxNode, TextRange, TextSize, WalkEvent,
+ format_smolstr, match_ast,
};
-use crate::{navigation_target::TryToNav, FileId};
+use crate::{FileId, navigation_target::TryToNav};
mod adjustment;
mod bind_pat;
@@ -85,7 +85,7 @@ pub(crate) fn inlay_hints(
let sema = Semantics::new(db);
let file_id = sema
.attach_first_edition(file_id)
- .unwrap_or_else(|| EditionedFileId::current_edition(file_id));
+ .unwrap_or_else(|| EditionedFileId::current_edition(db, file_id));
let file = sema.parse(file_id);
let file = file.syntax();
@@ -136,7 +136,7 @@ pub(crate) fn inlay_hints_resolve(
let sema = Semantics::new(db);
let file_id = sema
.attach_first_edition(file_id)
- .unwrap_or_else(|| EditionedFileId::current_edition(file_id));
+ .unwrap_or_else(|| EditionedFileId::current_edition(db, file_id));
let file = sema.parse(file_id);
let file = file.syntax();
@@ -207,7 +207,11 @@ fn hints(
file_id: EditionedFileId,
node: SyntaxNode,
) {
- let display_target = sema.first_crate_or_default(file_id.file_id()).to_display_target(sema.db);
+ let file_id = file_id.editioned_file_id(sema.db);
+ let Some(krate) = sema.first_crate(file_id.file_id()) else {
+ return;
+ };
+ let display_target = krate.to_display_target(sema.db);
closing_brace::hints(hints, sema, config, file_id, display_target, node.clone());
if let Some(any_has_generic_args) = ast::AnyHasGenericArgs::cast(node.clone()) {
generic_param::hints(hints, famous_defs, config, any_has_generic_args);
@@ -219,12 +223,12 @@ fn hints(
chaining::hints(hints, famous_defs, config, display_target, &expr);
adjustment::hints(hints, famous_defs, config, display_target, &expr);
match expr {
- ast::Expr::CallExpr(it) => param_name::hints(hints, famous_defs, config, file_id, ast::Expr::from(it)),
+ ast::Expr::CallExpr(it) => param_name::hints(hints, famous_defs, config, ast::Expr::from(it)),
ast::Expr::MethodCallExpr(it) => {
- param_name::hints(hints, famous_defs, config, file_id, ast::Expr::from(it))
+ param_name::hints(hints, famous_defs, config, ast::Expr::from(it))
}
ast::Expr::ClosureExpr(it) => {
- closure_captures::hints(hints, famous_defs, config, file_id, it.clone());
+ closure_captures::hints(hints, famous_defs, config, it.clone());
closure_ret::hints(hints, famous_defs, config, display_target, it)
},
ast::Expr::RangeExpr(it) => range_exclusive::hints(hints, famous_defs, config, file_id, it),
@@ -793,7 +797,7 @@ fn hint_iterator(
if ty.impls_trait(db, iter_trait, &[]) {
let assoc_type_item = iter_trait.items(db).into_iter().find_map(|item| match item {
- hir::AssocItem::TypeAlias(alias) if alias.name(db) == sym::Item.clone() => Some(alias),
+ hir::AssocItem::TypeAlias(alias) if alias.name(db) == sym::Item => Some(alias),
_ => None,
})?;
if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) {
@@ -809,7 +813,8 @@ fn ty_to_text_edit(
config: &InlayHintsConfig,
node_for_hint: &SyntaxNode,
ty: &hir::Type,
- offset_to_insert: TextSize,
+ offset_to_insert_ty: TextSize,
+ additional_edits: &dyn Fn(&mut TextEditBuilder),
prefix: impl Into<String>,
) -> Option<LazyProperty<TextEdit>> {
// FIXME: Limit the length and bail out on excess somehow?
@@ -818,8 +823,11 @@ fn ty_to_text_edit(
.and_then(|scope| ty.display_source_code(scope.db, scope.module().into(), false).ok())?;
Some(config.lazy_text_edit(|| {
let mut builder = TextEdit::builder();
- builder.insert(offset_to_insert, prefix.into());
- builder.insert(offset_to_insert, rendered);
+ builder.insert(offset_to_insert_ty, prefix.into());
+ builder.insert(offset_to_insert_ty, rendered);
+
+ additional_edits(&mut builder);
+
builder.finish()
}))
}
@@ -836,9 +844,9 @@ mod tests {
use itertools::Itertools;
use test_utils::extract_annotations;
- use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode};
use crate::DiscriminantHints;
- use crate::{fixture, inlay_hints::InlayHintsConfig, LifetimeElisionHints};
+ use crate::inlay_hints::{AdjustmentHints, AdjustmentHintsMode};
+ use crate::{LifetimeElisionHints, fixture, inlay_hints::InlayHintsConfig};
use super::{ClosureReturnTypeHints, GenericParameterHints, InlayFieldsToResolve};
@@ -996,4 +1004,51 @@ fn foo() {
"#,
);
}
+
+ #[test]
+ fn closure_dependency_cycle_no_panic() {
+ check(
+ r#"
+fn foo() {
+ let closure;
+ // ^^^^^^^ impl Fn()
+ closure = || {
+ closure();
+ };
+}
+
+fn bar() {
+ let closure1;
+ // ^^^^^^^^ impl Fn()
+ let closure2;
+ // ^^^^^^^^ impl Fn()
+ closure1 = || {
+ closure2();
+ };
+ closure2 = || {
+ closure1();
+ };
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn regression_19610() {
+ check(
+ r#"
+trait Trait {
+ type Assoc;
+}
+struct Foo<A>(A);
+impl<A: Trait<Assoc = impl Trait>> Foo<A> {
+ fn foo<'a, 'b>(_: &'a [i32], _: &'b [i32]) {}
+}
+
+fn bar() {
+ Foo::foo(&[1], &[2]);
+}
+"#,
+ );
+ }
}