Skip to content

Commit

Permalink
Bring back goto def redirect for parse -> FromStr
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Jan 20, 2025
1 parent 48d17b4 commit 4bc683d
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 4 deletions.
4 changes: 4 additions & 0 deletions src/tools/rust-analyzer/crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4682,6 +4682,10 @@ impl Type {
matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
}

pub fn is_str(&self) -> bool {
matches!(self.ty.kind(Interner), TyKind::Str)
}

pub fn is_never(&self) -> bool {
matches!(self.ty.kind(Interner), TyKind::Never)
}
Expand Down
2 changes: 1 addition & 1 deletion src/tools/rust-analyzer/crates/hir/src/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1441,7 +1441,7 @@ impl<'db> SemanticsImpl<'db> {

/// Env is used to derive the trait environment
// FIXME: better api for the trait environment
pub fn resolve_impl_method(
pub fn resolve_trait_impl_method(
&self,
env: Type,
trait_: Trait,
Expand Down
46 changes: 43 additions & 3 deletions src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,35 @@ fn find_definition_for_known_blanket_dual_impls(
let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?;
let callable = sema.resolve_method_call_as_callable(&method_call)?;
let CallableKind::Function(f) = callable.kind() else { return None };
let t = f.as_assoc_item(sema.db)?.container_trait(sema.db)?;
let assoc = f.as_assoc_item(sema.db)?;

let return_type = callable.return_type();
let fd = FamousDefs(sema, return_type.krate(sema.db));

let t = match assoc.container(sema.db) {
hir::AssocItemContainer::Trait(t) => t,
hir::AssocItemContainer::Impl(impl_)
if impl_.self_ty(sema.db).is_str() && f.name(sema.db) == sym::parse =>
{
let t = fd.core_convert_FromStr()?;
let t_f = t.function(sema.db, &sym::from_str)?;
return sema
.resolve_trait_impl_method(
return_type.clone(),
t,
t_f,
[return_type.type_arguments().next()?],
)
.map(|f| def_to_nav(sema.db, f.into()));
}
hir::AssocItemContainer::Impl(_) => return None,
};

let fn_name = f.name(sema.db);
let f = if fn_name == sym::into && fd.core_convert_Into() == Some(t) {
let dual = fd.core_convert_From()?;
let dual_f = dual.function(sema.db, &sym::from)?;
sema.resolve_impl_method(
sema.resolve_trait_impl_method(
return_type.clone(),
dual,
dual_f,
Expand All @@ -158,7 +178,7 @@ fn find_definition_for_known_blanket_dual_impls(
} else if fn_name == sym::try_into && fd.core_convert_TryInto() == Some(t) {
let dual = fd.core_convert_TryFrom()?;
let dual_f = dual.function(sema.db, &sym::try_from)?;
sema.resolve_impl_method(
sema.resolve_trait_impl_method(
return_type.clone(),
dual,
dual_f,
Expand Down Expand Up @@ -3191,6 +3211,26 @@ impl TryInto<B> for A {
fn f() {
let a = A;
let b: Result<B, _> = a.try_into$0();
}
"#,
);
}

#[test]
fn parse_call_to_from_str_definition() {
check(
r#"
//- minicore: from, str
struct A;
impl FromStr for A {
type Error = String;
fn from_str(value: &str) -> Result<Self, Self::Error> {
//^^^^^^^^
Ok(A)
}
}
fn f() {
let a: Result<A, _> = "aaaaaa".parse$0();
}
"#,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ define_symbols! {
from,
From,
FromStr,
from_str,
from_output,
from_residual,
from_usize,
Expand Down
10 changes: 10 additions & 0 deletions src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,15 @@ pub mod str {
pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
""
}
pub trait FromStr: Sized {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
impl str {
pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
FromStr::from_str(self)
}
}
}
// endregion:str

Expand Down Expand Up @@ -1848,6 +1857,7 @@ pub mod prelude {
option::Option::{self, None, Some}, // :option
panic, // :panic
result::Result::{self, Err, Ok}, // :result
str::FromStr, // :str
};
}

Expand Down

0 comments on commit 4bc683d

Please sign in to comment.