mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 14:21:44 +00:00
Add support for inline bounds
E.g. impl<T: Clone> Foo for T.
This commit is contained in:
parent
d6dc75f9f2
commit
cbe75676b9
2 changed files with 60 additions and 16 deletions
|
@ -90,8 +90,17 @@ impl GenericParams {
|
||||||
fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) {
|
fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) {
|
||||||
for (idx, type_param) in params.type_params().enumerate() {
|
for (idx, type_param) in params.type_params().enumerate() {
|
||||||
let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing);
|
let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing);
|
||||||
let param = GenericParam { idx: idx as u32 + start, name };
|
let param = GenericParam { idx: idx as u32 + start, name: name.clone() };
|
||||||
self.params.push(param);
|
self.params.push(param);
|
||||||
|
|
||||||
|
let type_ref = TypeRef::Path(name.into());
|
||||||
|
for bound in type_param
|
||||||
|
.type_bound_list()
|
||||||
|
.iter()
|
||||||
|
.flat_map(|type_bound_list| type_bound_list.bounds())
|
||||||
|
{
|
||||||
|
self.add_where_predicate_from_bound(bound, type_ref.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +110,14 @@ impl GenericParams {
|
||||||
Some(type_ref) => type_ref,
|
Some(type_ref) => type_ref,
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
|
let type_ref = TypeRef::from_ast(type_ref);
|
||||||
for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
|
for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
|
||||||
|
self.add_where_predicate_from_bound(bound, type_ref.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_where_predicate_from_bound(&mut self, bound: &ast::TypeBound, type_ref: TypeRef) {
|
||||||
let path = bound
|
let path = bound
|
||||||
.type_ref()
|
.type_ref()
|
||||||
.and_then(|tr| match tr.kind() {
|
.and_then(|tr| match tr.kind() {
|
||||||
|
@ -111,14 +127,9 @@ impl GenericParams {
|
||||||
.and_then(Path::from_ast);
|
.and_then(Path::from_ast);
|
||||||
let path = match path {
|
let path = match path {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => continue,
|
None => return,
|
||||||
};
|
};
|
||||||
self.where_predicates.push(WherePredicate {
|
self.where_predicates.push(WherePredicate { type_ref, trait_ref: path });
|
||||||
type_ref: TypeRef::from_ast(type_ref),
|
|
||||||
trait_ref: path,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
|
pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
|
||||||
|
|
|
@ -2535,6 +2535,22 @@ fn test() { (&S).foo()<|>; }
|
||||||
assert_eq!(t, "{unknown}");
|
assert_eq!(t, "{unknown}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn method_resolution_where_clause_inline_not_met() {
|
||||||
|
// The blanket impl shouldn't apply because we can't prove S: Clone
|
||||||
|
let t = type_at(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
trait Clone {}
|
||||||
|
trait Trait { fn foo(self) -> u128; }
|
||||||
|
struct S;
|
||||||
|
impl<T: Clone> Trait for T {}
|
||||||
|
fn test() { (&S).foo()<|>; }
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_eq!(t, "{unknown}");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn method_resolution_where_clause_1() {
|
fn method_resolution_where_clause_1() {
|
||||||
let t = type_at(
|
let t = type_at(
|
||||||
|
@ -2568,6 +2584,23 @@ fn test() { S2.into()<|>; }
|
||||||
assert_eq!(t, "S1");
|
assert_eq!(t, "S1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn method_resolution_where_clause_inline() {
|
||||||
|
let t = type_at(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
trait Into<T> { fn into(self) -> T; }
|
||||||
|
trait From<T> { fn from(other: T) -> Self; }
|
||||||
|
struct S1;
|
||||||
|
struct S2;
|
||||||
|
impl From<S2> for S1 {};
|
||||||
|
impl<T, U: From<T>> Into<U> for T {}
|
||||||
|
fn test() { S2.into()<|>; }
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_eq!(t, "S1");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn method_resolution_encountering_fn_type() {
|
fn method_resolution_encountering_fn_type() {
|
||||||
covers!(trait_resolution_on_fn_type);
|
covers!(trait_resolution_on_fn_type);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue