Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
547c53a
add span_parent method in ProcMacroClientInterface
Shourya742 Feb 18, 2026
fc97d7e
update span_parent implementation to call span_parent in callback
Shourya742 Feb 18, 2026
93e0d9e
add span_parent in MockCallback
Shourya742 Feb 18, 2026
3efdde1
update ProcMacroClientHandle implementation
Shourya742 Feb 18, 2026
6cb5858
add SpanParentResult and SpanParent
Shourya742 Feb 18, 2026
2116aaa
add SpanParent implementation in bidirectional variant
Shourya742 Feb 18, 2026
4eaf448
fix: Fix scrutinee expr indent for replace_if_let_with_match
A4-Tacks Feb 24, 2026
87e4a3d
fix: detect E0804 when casting raw ptr-to-dyn adds auto traits
Albab-Hasan Feb 24, 2026
81bcf97
internal: Skip rustfmt test if nightly toolchain is missing
Wilfred Feb 19, 2026
70bf845
Merge pull request #21681 from Wilfred/skip_test_on_nightly
lnicola Feb 24, 2026
ff62e9a
fix: no complete enum variant qualifier in pat
A4-Tacks Feb 24, 2026
d173db9
Don't panic on invalid notifications
lnicola Feb 25, 2026
6c2ec54
Merge pull request #21708 from lnicola/no-invalid-notification-panic
Veykril Feb 26, 2026
4a2f9eb
Merge pull request #21699 from Albab-Hasan/fix/ptr-cast-add-auto-trai…
ShoyuVanilla Feb 27, 2026
f7e81f5
Merge pull request #21698 from A4-Tacks/indent-iflet-with-match
ShoyuVanilla Feb 27, 2026
17c945f
Merge pull request #21706 from A4-Tacks/redundant-enum-variant-pat
ShoyuVanilla Feb 27, 2026
148f0b1
Use -Zlockfile-path on every 1.95 nightly
lnicola Feb 27, 2026
1a365c5
Merge pull request #21716 from lnicola/lockfile-path-nightly
ShoyuVanilla Feb 27, 2026
171dae6
feat: migrate fix_visibility assist to SyntaxEditor
SpiZeak Feb 25, 2026
720020d
Merge pull request #21710 from SpiZeak/migrate-fix-visibility
ShoyuVanilla Feb 27, 2026
2879033
fix: migrate to SyntaxEditor in generate_derive assist
SpiZeak Feb 27, 2026
448f9d8
Merge pull request #21720 from SpiZeak/migrate-generate-derive
A4-Tacks Feb 28, 2026
7a22108
Merge pull request #21669 from Shourya742/2026-02-18-add-span-parent
Veykril Feb 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,11 +328,7 @@ impl<'db> CastCheck<'db> {
//
// Note that trait upcasting goes through a different mechanism (`coerce_unsized`)
// and is unaffected by this check.
(Some(src_principal), Some(dst_principal)) => {
if src_principal == dst_principal {
return Ok(());
}

(Some(src_principal), Some(_)) => {
// We need to reconstruct trait object types.
// `m_src` and `m_dst` won't work for us here because they will potentially
// contain wrappers, which we do not care about.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use hir::{HasSource, HasVisibility, ModuleDef, PathResolution, ScopeDef, db::Hir
use ide_db::FileId;
use syntax::{
AstNode, TextRange,
ast::{self, HasVisibility as _, edit_in_place::HasVisibilityEdit, make},
ast::{self, HasVisibility as _, syntax_factory::SyntaxFactory},
};

use crate::{AssistContext, AssistId, Assists};
Expand Down Expand Up @@ -59,10 +59,12 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)

let (vis_owner, target, target_file, target_name) = target_data_for_def(ctx.db(), def)?;

let make = SyntaxFactory::without_mappings();

let missing_visibility = if current_module.krate(ctx.db()) == target_module.krate(ctx.db()) {
make::visibility_pub_crate()
make.visibility_pub_crate()
} else {
make::visibility_pub()
make.visibility_pub()
};

let assist_label = match target_name {
Expand All @@ -75,15 +77,36 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
}
};

acc.add(AssistId::quick_fix("fix_visibility"), assist_label, target, |edit| {
edit.edit_file(target_file);

let vis_owner = edit.make_mut(vis_owner);
vis_owner.set_visibility(Some(missing_visibility.clone_for_update()));
acc.add(AssistId::quick_fix("fix_visibility"), assist_label, target, |builder| {
let mut editor = builder.make_editor(vis_owner.syntax());

if let Some(current_visibility) = vis_owner.visibility() {
editor.replace(current_visibility.syntax(), missing_visibility.syntax());
} else {
let vis_before = vis_owner
.syntax()
.children_with_tokens()
.find(|it| {
!matches!(
it.kind(),
syntax::SyntaxKind::WHITESPACE
| syntax::SyntaxKind::COMMENT
| syntax::SyntaxKind::ATTR
)
})
.unwrap_or_else(|| vis_owner.syntax().first_child_or_token().unwrap());

editor.insert_all(
syntax::syntax_editor::Position::before(vis_before),
vec![missing_visibility.syntax().clone().into(), make.whitespace(" ").into()],
);
}

if let Some((cap, vis)) = ctx.config.snippet_cap.zip(vis_owner.visibility()) {
edit.add_tabstop_before(cap, vis);
if let Some(cap) = ctx.config.snippet_cap {
editor.add_annotation(missing_visibility.syntax(), builder.make_tabstop_before(cap));
}

builder.add_file_edits(target_file, editor);
})
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use syntax::{
SyntaxKind::{ATTR, COMMENT, WHITESPACE},
T,
ast::{self, AstNode, HasAttrs, edit::IndentLevel, make},
ast::{self, AstNode, HasAttrs, edit::IndentLevel, syntax_factory::SyntaxFactory},
syntax_editor::{Element, Position},
};

Expand Down Expand Up @@ -42,13 +42,15 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
};

acc.add(AssistId::generate("generate_derive"), "Add `#[derive]`", target, |edit| {
let make = SyntaxFactory::without_mappings();

match derive_attr {
None => {
let derive = make::attr_outer(make::meta_token_tree(
make::ext::ident_path("derive"),
make::token_tree(T!['('], vec![]).clone_for_update(),
))
.clone_for_update();
let derive =
make.attr_outer(make.meta_token_tree(
make.ident_path("derive"),
make.token_tree(T!['('], vec![]),
));

let mut editor = edit.make_editor(nominal.syntax());
let indent = IndentLevel::from_node(nominal.syntax());
Expand All @@ -57,11 +59,12 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
.children_with_tokens()
.find(|it| !matches!(it.kind(), WHITESPACE | COMMENT | ATTR))
.map_or(Position::first_child_of(nominal.syntax()), Position::before);

editor.insert_all(
after_attrs_and_comments,
vec![
derive.syntax().syntax_element(),
make::tokens::whitespace(&format!("\n{indent}")).syntax_element(),
make.whitespace(&format!("\n{indent}")).syntax_element(),
],
);

Expand All @@ -72,7 +75,9 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
.expect("failed to get token tree out of Meta")
.r_paren_token()
.expect("make::attr_outer was expected to have a R_PAREN");

let tabstop_before = edit.make_tabstop_before(cap);

editor.add_annotation(delimiter, tabstop_before);
edit.add_file_edits(ctx.vfs_file_id(), editor);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
let if_exprs = successors(Some(if_expr.clone()), |expr| match expr.else_branch()? {
ast::ElseBranch::IfExpr(expr) => Some(expr),
ast::ElseBranch::Block(block) => {
let block = unwrap_trivial_block(block).clone_for_update();
let block = unwrap_trivial_block(block);
else_block = Some(block.reset_indent().indent(IndentLevel(1)));
None
}
Expand Down Expand Up @@ -91,7 +91,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
guard
};

let body = if_expr.then_branch()?.clone_for_update().indent(IndentLevel(1));
let body = if_expr.then_branch()?.indent(IndentLevel(1));
cond_bodies.push((cond, guard, body));
}

Expand All @@ -114,7 +114,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
let make_match_arm =
|(pat, guard, body): (_, Option<ast::Expr>, ast::BlockExpr)| {
// Dedent from original position, then indent for match arm
let body = body.dedent(indent).indent(IndentLevel::single());
let body = body.dedent(indent);
let body = unwrap_trivial_block(body);
match (pat, guard.map(|it| make.match_guard(it))) {
(Some(pat), guard) => make.match_arm(pat, guard, body),
Expand All @@ -127,8 +127,8 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
}
};
let arms = cond_bodies.into_iter().map(make_match_arm).chain([else_arm]);
let match_expr =
make.expr_match(scrutinee_to_be_expr, make.match_arm_list(arms)).indent(indent);
let expr = scrutinee_to_be_expr.reset_indent();
let match_expr = make.expr_match(expr, make.match_arm_list(arms)).indent(indent);
match_expr.into()
};

Expand Down Expand Up @@ -246,7 +246,7 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
first_arm.guard(),
second_arm.guard(),
)?;
let scrutinee = match_expr.expr()?;
let scrutinee = match_expr.expr()?.reset_indent();
let guard = guard.and_then(|it| it.condition());

let let_ = match &if_let_pat {
Expand Down Expand Up @@ -293,10 +293,8 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
} else {
condition
};
let then_expr =
then_expr.clone_for_update().reset_indent().indent(IndentLevel::single());
let else_expr =
else_expr.clone_for_update().reset_indent().indent(IndentLevel::single());
let then_expr = then_expr.reset_indent();
let else_expr = else_expr.reset_indent();
let then_block = make_block_expr(then_expr);
let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) };
let if_let_expr = make
Expand Down Expand Up @@ -956,7 +954,9 @@ fn foo(x: Result<i32, ()>) {
r#"
fn main() {
if true {
$0if let Ok(rel_path) = path.strip_prefix(root_path) {
$0if let Ok(rel_path) = path.strip_prefix(root_path)
.and(x)
{
let rel_path = RelativePathBuf::from_path(rel_path)
.ok()?;
Some((*id, rel_path))
Expand All @@ -971,7 +971,8 @@ fn main() {
r#"
fn main() {
if true {
match path.strip_prefix(root_path) {
match path.strip_prefix(root_path)
.and(x) {
Ok(rel_path) => {
let rel_path = RelativePathBuf::from_path(rel_path)
.ok()?;
Expand All @@ -993,7 +994,9 @@ fn main() {
r#"
fn main() {
if true {
$0if let Ok(rel_path) = path.strip_prefix(root_path) {
$0if let Ok(rel_path) = path.strip_prefix(root_path)
.and(x)
{
Foo {
x: 1
}
Expand All @@ -1008,7 +1011,8 @@ fn main() {
r#"
fn main() {
if true {
match path.strip_prefix(root_path) {
match path.strip_prefix(root_path)
.and(x) {
Ok(rel_path) => {
Foo {
x: 1
Expand All @@ -1023,7 +1027,33 @@ fn main() {
}
}
"#,
)
);

check_assist(
replace_if_let_with_match,
r#"
fn main() {
if true {
$0if true
&& false
{
foo()
}
}
}
"#,
r#"
fn main() {
if true {
match true
&& false {
true => foo(),
false => (),
}
}
}
"#,
);
}

#[test]
Expand Down Expand Up @@ -1878,7 +1908,9 @@ fn foo(x: Result<i32, ()>) {
r#"
fn main() {
if true {
$0match path.strip_prefix(root_path) {
$0match path.strip_prefix(root_path)
.and(x)
{
Ok(rel_path) => Foo {
x: 2
}
Expand All @@ -1892,7 +1924,8 @@ fn main() {
r#"
fn main() {
if true {
if let Ok(rel_path) = path.strip_prefix(root_path) {
if let Ok(rel_path) = path.strip_prefix(root_path)
.and(x) {
Foo {
x: 2
}
Expand All @@ -1911,7 +1944,9 @@ fn main() {
r#"
fn main() {
if true {
$0match path.strip_prefix(root_path) {
$0match path.strip_prefix(root_path)
.and(x)
{
Ok(rel_path) => {
let rel_path = RelativePathBuf::from_path(rel_path)
.ok()?;
Expand All @@ -1929,7 +1964,8 @@ fn main() {
r#"
fn main() {
if true {
if let Ok(rel_path) = path.strip_prefix(root_path) {
if let Ok(rel_path) = path.strip_prefix(root_path)
.and(x) {
let rel_path = RelativePathBuf::from_path(rel_path)
.ok()?;
Some((*id, rel_path))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub(crate) fn complete_pattern(
if refutable || single_variant_enum(variant.parent_enum(ctx.db)) =>
{
acc.add_variant_pat(ctx, pattern_ctx, None, variant, Some(name.clone()));
true
false
}
hir::ModuleDef::Adt(hir::Adt::Enum(e)) => refutable || single_variant_enum(e),
hir::ModuleDef::Const(..) => refutable,
Expand Down
32 changes: 28 additions & 4 deletions src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ fn foo() {
st Record
st Tuple
st Unit
ev TupleV
bn Record {…} Record { field$1 }$0
bn Tuple(…) Tuple($1)$0
bn TupleV(…) TupleV($1)$0
Expand Down Expand Up @@ -159,8 +158,6 @@ fn foo(foo: Foo) { match foo { Foo { x: $0 } } }
expect![[r#"
en Bar
st Foo
ev Nil
ev Value
bn Foo {…} Foo { x$1 }$0
bn Nil Nil$0
bn Value Value$0
Expand Down Expand Up @@ -189,7 +186,6 @@ fn foo() {
st Record
st Tuple
st Unit
ev Variant
bn Record {…} Record { field$1 }$0
bn Tuple(…) Tuple($1)$0
bn Variant Variant$0
Expand Down Expand Up @@ -354,6 +350,34 @@ fn func() {
);
}

#[test]
fn enum_unqualified() {
check_with_base_items(
r#"
use Enum::*;
fn func() {
if let $0 = unknown {}
}
"#,
expect![[r#"
ct CONST
en Enum
ma makro!(…) macro_rules! makro
md module
st Record
st Tuple
st Unit
bn Record {…} Record { field$1 }$0
bn RecordV {…} RecordV { field$1 }$0
bn Tuple(…) Tuple($1)$0
bn TupleV(…) TupleV($1)$0
bn UnitV UnitV$0
kw mut
kw ref
"#]],
);
}

#[test]
fn completes_in_record_field_pat() {
check(
Expand Down
Loading
Loading