do not use associated types placeholder for inlay hint

Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
This commit is contained in:
Benjamin Coenen 2020-10-28 12:29:42 +01:00
parent 8762b797fd
commit ef2f7bb243
6 changed files with 108 additions and 155 deletions

View file

@ -74,9 +74,29 @@ pub trait HirDisplay {
curr_size: 0, curr_size: 0,
max_size: None, max_size: None,
omit_verbose_types: false, omit_verbose_types: false,
#[cfg(not(test))]
display_target: DisplayTarget::SourceCode { module_id }, display_target: DisplayTarget::SourceCode { module_id },
#[cfg(test)] }) {
Ok(()) => {}
Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),
};
Ok(result)
}
/// Returns a String representation of `self` for test purposes
fn display_test<'a>(
&'a self,
db: &'a dyn HirDatabase,
module_id: ModuleId,
) -> Result<String, DisplaySourceCodeError> {
let mut result = String::new();
match self.hir_fmt(&mut HirFormatter {
db,
fmt: &mut result,
buf: String::with_capacity(20),
curr_size: 0,
max_size: None,
omit_verbose_types: false,
display_target: DisplayTarget::Test { module_id }, display_target: DisplayTarget::Test { module_id },
}) { }) {
Ok(()) => {} Ok(()) => {}
@ -138,7 +158,6 @@ enum DisplayTarget {
/// The generated code should compile, so paths need to be qualified. /// The generated code should compile, so paths need to be qualified.
SourceCode { module_id: ModuleId }, SourceCode { module_id: ModuleId },
/// Only for test purpose to keep real types /// Only for test purpose to keep real types
#[cfg(test)]
Test { module_id: ModuleId }, Test { module_id: ModuleId },
} }
@ -147,14 +166,7 @@ impl DisplayTarget {
matches!(self, Self::SourceCode {..}) matches!(self, Self::SourceCode {..})
} }
fn is_test(&self) -> bool { fn is_test(&self) -> bool {
#[cfg(test)] matches!(self, Self::Test {..})
{
matches!(self, Self::Test {..})
}
#[cfg(not(test))]
{
false
}
} }
} }
@ -344,21 +356,7 @@ impl HirDisplay for ApplicationTy {
}; };
write!(f, "{}", name)?; write!(f, "{}", name)?;
} }
DisplayTarget::SourceCode { module_id } => { DisplayTarget::SourceCode { module_id } | DisplayTarget::Test { module_id } => {
if let Some(path) = find_path::find_path(
f.db.upcast(),
ItemInNs::Types(def_id.into()),
module_id,
) {
write!(f, "{}", path)?;
} else {
return Err(HirDisplayError::DisplaySourceCodeError(
DisplaySourceCodeError::PathNotFound,
));
}
}
#[cfg(test)]
DisplayTarget::Test { module_id } => {
if let Some(path) = find_path::find_path( if let Some(path) = find_path::find_path(
f.db.upcast(), f.db.upcast(),
ItemInNs::Types(def_id.into()), ItemInNs::Types(def_id.into()),
@ -374,40 +372,38 @@ impl HirDisplay for ApplicationTy {
} }
if self.parameters.len() > 0 { if self.parameters.len() > 0 {
let parameters_to_write = if f.display_target.is_source_code() let parameters_to_write =
|| f.display_target.is_test() if f.display_target.is_source_code() || f.omit_verbose_types() {
|| f.omit_verbose_types() match self
{ .ctor
match self .as_generic_def()
.ctor .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
.as_generic_def() .filter(|defaults| !defaults.is_empty())
.map(|generic_def_id| f.db.generic_defaults(generic_def_id)) {
.filter(|defaults| !defaults.is_empty()) None => self.parameters.0.as_ref(),
{ Some(default_parameters) => {
None => self.parameters.0.as_ref(), let mut default_from = 0;
Some(default_parameters) => { for (i, parameter) in self.parameters.iter().enumerate() {
let mut default_from = 0; match (parameter, default_parameters.get(i)) {
for (i, parameter) in self.parameters.iter().enumerate() { (&Ty::Unknown, _) | (_, None) => {
match (parameter, default_parameters.get(i)) {
(&Ty::Unknown, _) | (_, None) => {
default_from = i + 1;
}
(_, Some(default_parameter)) => {
let actual_default = default_parameter
.clone()
.subst(&self.parameters.prefix(i));
if parameter != &actual_default {
default_from = i + 1; default_from = i + 1;
} }
(_, Some(default_parameter)) => {
let actual_default = default_parameter
.clone()
.subst(&self.parameters.prefix(i));
if parameter != &actual_default {
default_from = i + 1;
}
}
} }
} }
&self.parameters.0[0..default_from]
} }
&self.parameters.0[0..default_from]
} }
} } else {
} else { self.parameters.0.as_ref()
self.parameters.0.as_ref() };
};
if !parameters_to_write.is_empty() { if !parameters_to_write.is_empty() {
write!(f, "<")?; write!(f, "<")?;
f.write_joined(parameters_to_write, ", ")?; f.write_joined(parameters_to_write, ", ")?;

View file

@ -157,13 +157,14 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
(node.value.text_range(), node.value.text().to_string().replace("\n", " ")) (node.value.text_range(), node.value.text().to_string().replace("\n", " "))
}; };
let macro_prefix = if node.file_id != file_id.into() { "!" } else { "" }; let macro_prefix = if node.file_id != file_id.into() { "!" } else { "" };
let module = db.module_for_file(node.file_id.original_file(&db));
format_to!( format_to!(
buf, buf,
"{}{:?} '{}': {}\n", "{}{:?} '{}': {}\n",
macro_prefix, macro_prefix,
range, range,
ellipsize(text, 15), ellipsize(text, 15),
ty.display(&db) ty.display_test(&db, module).unwrap()
); );
} }
if include_mismatches { if include_mismatches {
@ -174,13 +175,14 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
for (src_ptr, mismatch) in &mismatches { for (src_ptr, mismatch) in &mismatches {
let range = src_ptr.value.text_range(); let range = src_ptr.value.text_range();
let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" };
let module = db.module_for_file(src_ptr.file_id.original_file(&db));
format_to!( format_to!(
buf, buf,
"{}{:?}: expected {}, got {}\n", "{}{:?}: expected {}, got {}\n",
macro_prefix, macro_prefix,
range, range,
mismatch.expected.display(&db), mismatch.expected.display_test(&db, module).unwrap(),
mismatch.actual.display(&db), mismatch.actual.display_test(&db, module).unwrap(),
); );
} }
} }

View file

@ -108,16 +108,16 @@ fn infer_associated_method_with_modules() {
check_infer( check_infer(
r#" r#"
mod a { mod a {
struct A; pub struct A;
impl A { pub fn thing() -> A { A {} }} impl A { pub fn thing() -> A { A {} }}
} }
mod b { mod b {
struct B; pub struct B;
impl B { pub fn thing() -> u32 { 99 }} impl B { pub fn thing() -> u32 { 99 }}
mod c { pub mod c {
struct C; pub struct C;
impl C { pub fn thing() -> C { C {} }} impl C { pub fn thing() -> C { C {} }}
} }
} }
@ -130,22 +130,22 @@ fn infer_associated_method_with_modules() {
} }
"#, "#,
expect![[r#" expect![[r#"
55..63 '{ A {} }': A 59..67 '{ A {} }': a::A
57..61 'A {}': A 61..65 'A {}': a::A
125..131 '{ 99 }': u32 133..139 '{ 99 }': u32
127..129 '99': u32 135..137 '99': u32
201..209 '{ C {} }': C 217..225 '{ C {} }': c::C
203..207 'C {}': C 219..223 'C {}': c::C
240..324 '{ ...g(); }': () 256..340 '{ ...g(); }': ()
250..251 'x': A 266..267 'x': a::A
254..265 'a::A::thing': fn thing() -> A 270..281 'a::A::thing': fn thing() -> A
254..267 'a::A::thing()': A 270..283 'a::A::thing()': a::A
277..278 'y': u32 293..294 'y': u32
281..292 'b::B::thing': fn thing() -> u32 297..308 'b::B::thing': fn thing() -> u32
281..294 'b::B::thing()': u32 297..310 'b::B::thing()': u32
304..305 'z': C 320..321 'z': c::C
308..319 'c::C::thing': fn thing() -> C 324..335 'c::C::thing': fn thing() -> C
308..321 'c::C::thing()': C 324..337 'c::C::thing()': c::C
"#]], "#]],
); );
} }

View file

@ -831,11 +831,11 @@ fn issue_4966() {
356..362 'repeat': Repeat<Map<|&f64| -> f64>> 356..362 'repeat': Repeat<Map<|&f64| -> f64>>
365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>> 365..390 'Repeat...nner }': Repeat<Map<|&f64| -> f64>>
383..388 'inner': Map<|&f64| -> f64> 383..388 'inner': Map<|&f64| -> f64>
401..404 'vec': Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> 401..404 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
407..416 'from_iter': fn from_iter<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> 407..416 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>, Repeat<Map<|&f64| -> f64>>>(Repeat<Map<|&f64| -> f64>>) -> Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item>
407..424 'from_i...epeat)': Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> 407..424 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
417..423 'repeat': Repeat<Map<|&f64| -> f64>> 417..423 'repeat': Repeat<Map<|&f64| -> f64>>
431..434 'vec': Vec<<Repeat<Map<|&f64| -> f64>> as IntoIterator>::Item> 431..434 'vec': Vec<IntoIterator::Item<Repeat<Map<|&f64| -> f64>>>>
431..444 'vec.foo_bar()': {unknown} 431..444 'vec.foo_bar()': {unknown}
"#]], "#]],
); );

View file

@ -1,7 +1,7 @@
use expect_test::expect; use expect_test::expect;
use test_utils::mark; use test_utils::mark;
use super::{check_infer, check_infer_with_mismatches, check_types, check_types_source_code}; use super::{check_infer, check_infer_with_mismatches, check_types};
#[test] #[test]
fn infer_await() { fn infer_await() {
@ -384,12 +384,12 @@ fn infer_project_associated_type() {
108..261 '{ ...ter; }': () 108..261 '{ ...ter; }': ()
118..119 'x': u32 118..119 'x': u32
145..146 '1': u32 145..146 '1': u32
156..157 'y': <T as Iterable>::Item 156..157 'y': Iterable::Item<T>
183..192 'no_matter': <T as Iterable>::Item 183..192 'no_matter': Iterable::Item<T>
202..203 'z': <T as Iterable>::Item 202..203 'z': Iterable::Item<T>
215..224 'no_matter': <T as Iterable>::Item 215..224 'no_matter': Iterable::Item<T>
234..235 'a': <T as Iterable>::Item 234..235 'a': Iterable::Item<T>
249..258 'no_matter': <T as Iterable>::Item 249..258 'no_matter': Iterable::Item<T>
"#]], "#]],
); );
} }
@ -945,45 +945,6 @@ fn test<T: ApplyL>(t: T) {
); );
} }
#[test]
fn associated_type_placeholder() {
check_types_source_code(
r#"
pub trait ApplyL {
type Out;
}
pub struct RefMutL<T>;
impl<T> ApplyL for RefMutL<T> {
type Out = <T as ApplyL>::Out;
}
fn test<T: ApplyL>() {
let y: <RefMutL<T> as ApplyL>::Out = no_matter;
y;
} //^ ApplyL::Out<T>
"#,
);
}
#[test]
fn associated_type_placeholder_2() {
check_types_source_code(
r#"
pub trait ApplyL {
type Out;
}
fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;
fn test<T: ApplyL>(t: T) {
let y = foo(t);
y;
} //^ ApplyL::Out<T>
"#,
);
}
#[test] #[test]
fn argument_impl_trait() { fn argument_impl_trait() {
check_infer_with_mismatches( check_infer_with_mismatches(
@ -2158,7 +2119,7 @@ fn unselected_projection_on_impl_self() {
"#, "#,
expect![[r#" expect![[r#"
40..44 'self': &Self 40..44 'self': &Self
46..47 'x': <Self as Trait>::Item 46..47 'x': Trait::Item<Self>
126..130 'self': &S 126..130 'self': &S
132..133 'x': u32 132..133 'x': u32
147..161 '{ let y = x; }': () 147..161 '{ let y = x; }': ()
@ -3189,30 +3150,3 @@ fn test() {
"#, "#,
); );
} }
#[test]
fn infer_call_method_return_associated_types_with_generic() {
check_infer(
r#"
pub trait Default {
fn default() -> Self;
}
pub trait Foo {
type Bar: Default;
}
pub fn quux<T: Foo>() -> T::Bar {
let y = Default::default();
y
}
"#,
expect![[r#"
122..164 '{ ... y }': <T as Foo>::Bar
132..133 'y': <T as Foo>::Bar
136..152 'Defaul...efault': fn default<<T as Foo>::Bar>() -> <T as Foo>::Bar
136..154 'Defaul...ault()': <T as Foo>::Bar
161..162 'y': <T as Foo>::Bar
"#]],
);
}

View file

@ -1235,4 +1235,25 @@ fn main() {
"#, "#,
); );
} }
#[test]
fn infer_call_method_return_associated_types_with_generic() {
check(
r#"
pub trait Default {
fn default() -> Self;
}
pub trait Foo {
type Bar: Default;
}
pub fn quux<T: Foo>() -> T::Bar {
let y = Default::default();
//^ <T as Foo>::Bar
y
}
"#,
);
}
} }