This commit is contained in:
A4-Tacks 2025-12-22 18:22:10 +08:00 committed by GitHub
commit 9387b01da1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 69 additions and 2 deletions

View file

@ -14,7 +14,7 @@ use syntax::{
},
ast::{
self, AttrKind, HasArgList, HasGenericArgs, HasGenericParams, HasLoopBody, HasName,
NameOrNameRef,
NameOrNameRef, RangeItem,
},
match_ast,
};
@ -86,7 +86,8 @@ pub(super) fn expand_and_analyze<'db>(
// add the relative offset back, so that left_biased finds the proper token
let original_offset = expansion.original_offset + relative_offset;
let token = expansion.original_file.token_at_offset(original_offset).left_biased()?;
let token = expansion.original_file.token_at_offset(original_offset);
let token = left_biased_or_after_l_paren(token)?;
analyze(sema, expansion, original_token, &token).map(|(analysis, expected, qualifier_ctx)| {
AnalysisResult { analysis, expected, qualifier_ctx, token, original_offset }
@ -761,6 +762,11 @@ fn expected_type_and_name<'db>(
let ty = sema.type_of_pat(&ast::Pat::from(it)).map(TypeInfo::original);
(ty, None)
},
ast::RangeExpr(it) => {
let bound = it.start().or_else(|| it.end());
let ty = bound.and_then(|it| sema.type_of_expr(&it)).map(TypeInfo::original);
(ty, None)
},
ast::Fn(it) => {
cov_mark::hit!(expected_type_fn_ret_with_leading_char);
cov_mark::hit!(expected_type_fn_ret_without_leading_char);
@ -2065,3 +2071,12 @@ fn prev_special_biased_token_at_trivia(mut token: SyntaxToken) -> SyntaxToken {
}
token
}
fn left_biased_or_after_l_paren(token: syntax::TokenAtOffset<SyntaxToken>) -> Option<SyntaxToken> {
match token {
syntax::TokenAtOffset::None => None,
syntax::TokenAtOffset::Single(it) => Some(it),
syntax::TokenAtOffset::Between(left, right) if left.kind() == T!['('] => Some(right),
syntax::TokenAtOffset::Between(left, _) => Some(left),
}
}

View file

@ -647,3 +647,55 @@ fn foo() {
expect![[r#"ty: bool, name: ?"#]],
);
}
#[test]
fn expected_type_range_expr() {
check_expected_type_and_name(
r#"
//- minicore: range
enum State { Stop }
fn bar(x: core::ops::Range<State>) {}
fn foo() {
bar(State::Stop..$0)
}
"#,
expect![[r#"ty: State, name: ?"#]],
);
check_expected_type_and_name(
r#"
//- minicore: range
enum State { Stop }
fn bar(x: core::ops::Range<State>) {}
fn foo() {
bar($0..State::Stop)
}
"#,
expect![[r#"ty: State, name: ?"#]],
);
// FIXME: Analyze the type of `..` and use the generic parameters of Range*
check_expected_type_and_name(
r#"
//- minicore: range
enum State { Stop }
fn bar(x: core::ops::Range<State>) {}
fn foo() {
bar(..$0)
}
"#,
expect![[r#"ty: ?, name: ?"#]],
);
check_expected_type_and_name(
r#"
//- minicore: range
enum State { Stop }
fn bar(x: core::ops::Range<State>) {}
fn foo() {
bar($0..)
}
"#,
expect![[r#"ty: ?, name: ?"#]],
);
}