Skip to content

Commit 4bc683d

Browse files
committed
Bring back goto def redirect for parse -> FromStr
1 parent 48d17b4 commit 4bc683d

File tree

5 files changed

+59
-4
lines changed

5 files changed

+59
-4
lines changed

src/tools/rust-analyzer/crates/hir/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -4682,6 +4682,10 @@ impl Type {
46824682
matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
46834683
}
46844684

4685+
pub fn is_str(&self) -> bool {
4686+
matches!(self.ty.kind(Interner), TyKind::Str)
4687+
}
4688+
46854689
pub fn is_never(&self) -> bool {
46864690
matches!(self.ty.kind(Interner), TyKind::Never)
46874691
}

src/tools/rust-analyzer/crates/hir/src/semantics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1441,7 +1441,7 @@ impl<'db> SemanticsImpl<'db> {
14411441

14421442
/// Env is used to derive the trait environment
14431443
// FIXME: better api for the trait environment
1444-
pub fn resolve_impl_method(
1444+
pub fn resolve_trait_impl_method(
14451445
&self,
14461446
env: Type,
14471447
trait_: Trait,

src/tools/rust-analyzer/crates/ide/src/goto_definition.rs

+43-3
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,35 @@ fn find_definition_for_known_blanket_dual_impls(
141141
let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?;
142142
let callable = sema.resolve_method_call_as_callable(&method_call)?;
143143
let CallableKind::Function(f) = callable.kind() else { return None };
144-
let t = f.as_assoc_item(sema.db)?.container_trait(sema.db)?;
144+
let assoc = f.as_assoc_item(sema.db)?;
145145

146146
let return_type = callable.return_type();
147147
let fd = FamousDefs(sema, return_type.krate(sema.db));
148+
149+
let t = match assoc.container(sema.db) {
150+
hir::AssocItemContainer::Trait(t) => t,
151+
hir::AssocItemContainer::Impl(impl_)
152+
if impl_.self_ty(sema.db).is_str() && f.name(sema.db) == sym::parse =>
153+
{
154+
let t = fd.core_convert_FromStr()?;
155+
let t_f = t.function(sema.db, &sym::from_str)?;
156+
return sema
157+
.resolve_trait_impl_method(
158+
return_type.clone(),
159+
t,
160+
t_f,
161+
[return_type.type_arguments().next()?],
162+
)
163+
.map(|f| def_to_nav(sema.db, f.into()));
164+
}
165+
hir::AssocItemContainer::Impl(_) => return None,
166+
};
167+
148168
let fn_name = f.name(sema.db);
149169
let f = if fn_name == sym::into && fd.core_convert_Into() == Some(t) {
150170
let dual = fd.core_convert_From()?;
151171
let dual_f = dual.function(sema.db, &sym::from)?;
152-
sema.resolve_impl_method(
172+
sema.resolve_trait_impl_method(
153173
return_type.clone(),
154174
dual,
155175
dual_f,
@@ -158,7 +178,7 @@ fn find_definition_for_known_blanket_dual_impls(
158178
} else if fn_name == sym::try_into && fd.core_convert_TryInto() == Some(t) {
159179
let dual = fd.core_convert_TryFrom()?;
160180
let dual_f = dual.function(sema.db, &sym::try_from)?;
161-
sema.resolve_impl_method(
181+
sema.resolve_trait_impl_method(
162182
return_type.clone(),
163183
dual,
164184
dual_f,
@@ -3191,6 +3211,26 @@ impl TryInto<B> for A {
31913211
fn f() {
31923212
let a = A;
31933213
let b: Result<B, _> = a.try_into$0();
3214+
}
3215+
"#,
3216+
);
3217+
}
3218+
3219+
#[test]
3220+
fn parse_call_to_from_str_definition() {
3221+
check(
3222+
r#"
3223+
//- minicore: from, str
3224+
struct A;
3225+
impl FromStr for A {
3226+
type Error = String;
3227+
fn from_str(value: &str) -> Result<Self, Self::Error> {
3228+
//^^^^^^^^
3229+
Ok(A)
3230+
}
3231+
}
3232+
fn f() {
3233+
let a: Result<A, _> = "aaaaaa".parse$0();
31943234
}
31953235
"#,
31963236
);

src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs

+1
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ define_symbols! {
243243
from,
244244
From,
245245
FromStr,
246+
from_str,
246247
from_output,
247248
from_residual,
248249
from_usize,

src/tools/rust-analyzer/crates/test-utils/src/minicore.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,15 @@ pub mod str {
15741574
pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
15751575
""
15761576
}
1577+
pub trait FromStr: Sized {
1578+
type Err;
1579+
fn from_str(s: &str) -> Result<Self, Self::Err>;
1580+
}
1581+
impl str {
1582+
pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
1583+
FromStr::from_str(self)
1584+
}
1585+
}
15771586
}
15781587
// endregion:str
15791588

@@ -1848,6 +1857,7 @@ pub mod prelude {
18481857
option::Option::{self, None, Some}, // :option
18491858
panic, // :panic
18501859
result::Result::{self, Err, Ok}, // :result
1860+
str::FromStr, // :str
18511861
};
18521862
}
18531863

0 commit comments

Comments
 (0)