From 73161cc9cdcdf7b9f797d7984f2cad497a3f4553 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Tue, 27 Oct 2020 20:23:09 +0100 Subject: do not use associated types placeholder for inlay hint #6191 Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/hir_ty/src/display.rs | 26 ++++++++++++++++---- crates/hir_ty/src/tests/regression.rs | 8 +++--- crates/hir_ty/src/tests/traits.rs | 46 +++++++++++++++++++++++++++-------- 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index d2e151f25..43db24882 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -390,11 +390,27 @@ impl HirDisplay for ApplicationTy { }; let trait_ = f.db.trait_data(trait_); let type_alias = f.db.type_alias_data(type_alias); - write!(f, "{}::{}", trait_.name, type_alias.name)?; - if self.parameters.len() > 0 { - write!(f, "<")?; - f.write_joined(&*self.parameters.0, ", ")?; - write!(f, ">")?; + + // Use placeholder associated types when the target is source code (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) + if f.display_target.is_source_code() || self.parameters.len() > 1 { + write!(f, "{}::{}", trait_.name, type_alias.name)?; + if self.parameters.len() > 0 { + write!(f, "<")?; + f.write_joined(&*self.parameters.0, ", ")?; + write!(f, ">")?; + } + } else { + if self.parameters.len() == 1 { + write!( + f, + "<{} as {}>::{}", + self.parameters.as_single().display(f.db), + trait_.name, + type_alias.name + )?; + } else { + write!(f, "{}::{}", trait_.name, type_alias.name)?; + } } } TypeCtor::ForeignType(type_alias) => { diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 94d86b0d1..66e171f24 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs @@ -831,11 +831,11 @@ fn issue_4966() { 356..362 'repeat': Repeat f64>> 365..390 'Repeat...nner }': Repeat f64>> 383..388 'inner': Map<|&f64| -> f64> - 401..404 'vec': Vec f64>>>> - 407..416 'from_iter': fn from_iter f64>>>, Repeat f64>>>(Repeat f64>>) -> Vec f64>>>> - 407..424 'from_i...epeat)': Vec f64>>>> + 401..404 'vec': Vec< f64>> as IntoIterator>::Item> + 407..416 'from_iter': fn from_iter< f64>> as IntoIterator>::Item, Repeat f64>>>(Repeat f64>>) -> Vec< f64>> as IntoIterator>::Item> + 407..424 'from_i...epeat)': Vec< f64>> as IntoIterator>::Item> 417..423 'repeat': Repeat f64>> - 431..434 'vec': Vec f64>>>> + 431..434 'vec': Vec< f64>> as IntoIterator>::Item> 431..444 'vec.foo_bar()': {unknown} "#]], ); diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 41d097519..7ad8b5830 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -384,12 +384,12 @@ fn infer_project_associated_type() { 108..261 '{ ...ter; }': () 118..119 'x': u32 145..146 '1': u32 - 156..157 'y': Iterable::Item - 183..192 'no_matter': Iterable::Item - 202..203 'z': Iterable::Item - 215..224 'no_matter': Iterable::Item - 234..235 'a': Iterable::Item - 249..258 'no_matter': Iterable::Item + 156..157 'y': ::Item + 183..192 'no_matter': ::Item + 202..203 'z': ::Item + 215..224 'no_matter': ::Item + 234..235 'a': ::Item + 249..258 'no_matter': ::Item "#]], ); } @@ -908,7 +908,6 @@ fn test(t: T) { (*t); } #[test] fn associated_type_placeholder() { - // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. check_types( r#" pub trait ApplyL { @@ -924,7 +923,7 @@ impl ApplyL for RefMutL { fn test() { let y: as ApplyL>::Out = no_matter; y; -} //^ ApplyL::Out +} //^ ::Out "#, ); } @@ -941,7 +940,7 @@ fn foo(t: T) -> ::Out; fn test(t: T) { let y = foo(t); y; -} //^ ApplyL::Out +} //^ ::Out "#, ); } @@ -2120,7 +2119,7 @@ fn unselected_projection_on_impl_self() { "#, expect![[r#" 40..44 'self': &Self - 46..47 'x': Trait::Item + 46..47 'x': ::Item 126..130 'self': &S 132..133 'x': u32 147..161 '{ let y = x; }': () @@ -3151,3 +3150,30 @@ 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::Bar { + let y = Default::default(); + + y + } + "#, + expect![[r#" + 122..164 '{ ... y }': ::Bar + 132..133 'y': ::Bar + 136..152 'Defaul...efault': fn default<::Bar>() -> ::Bar + 136..154 'Defaul...ault()': ::Bar + 161..162 'y': ::Bar + "#]], + ); +} -- cgit v1.2.3 From 8762b797fd37e9a9cab3e5fe534a9672f30e6022 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Wed, 28 Oct 2020 11:20:05 +0100 Subject: do not use associated types placeholder for inlay hint Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/hir_ty/src/display.rs | 88 ++++++++++++++++++++++++++------------- crates/hir_ty/src/tests/traits.rs | 45 ++++++++++++++++++-- 2 files changed, 102 insertions(+), 31 deletions(-) diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 43db24882..f1232a72f 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -74,7 +74,10 @@ pub trait HirDisplay { curr_size: 0, max_size: None, omit_verbose_types: false, + #[cfg(not(test))] display_target: DisplayTarget::SourceCode { module_id }, + #[cfg(test)] + display_target: DisplayTarget::Test { module_id }, }) { Ok(()) => {} Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"), @@ -134,12 +137,25 @@ enum DisplayTarget { /// Display types for inserting them in source files. /// The generated code should compile, so paths need to be qualified. SourceCode { module_id: ModuleId }, + /// Only for test purpose to keep real types + #[cfg(test)] + Test { module_id: ModuleId }, } impl DisplayTarget { fn is_source_code(&self) -> bool { matches!(self, Self::SourceCode {..}) } + fn is_test(&self) -> bool { + #[cfg(test)] + { + matches!(self, Self::Test {..}) + } + #[cfg(not(test))] + { + false + } + } } #[derive(Debug)] @@ -341,41 +357,57 @@ impl HirDisplay for ApplicationTy { )); } } + #[cfg(test)] + 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, + )); + } + } } if self.parameters.len() > 0 { - let parameters_to_write = - if f.display_target.is_source_code() || f.omit_verbose_types() { - match self - .ctor - .as_generic_def() - .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) => { - let mut default_from = 0; - for (i, parameter) in self.parameters.iter().enumerate() { - match (parameter, default_parameters.get(i)) { - (&Ty::Unknown, _) | (_, None) => { + let parameters_to_write = if f.display_target.is_source_code() + || f.display_target.is_test() + || f.omit_verbose_types() + { + match self + .ctor + .as_generic_def() + .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) => { + let mut default_from = 0; + for (i, parameter) in self.parameters.iter().enumerate() { + 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; } - (_, 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 { - self.parameters.0.as_ref() - }; + } + } else { + self.parameters.0.as_ref() + }; if !parameters_to_write.is_empty() { write!(f, "<")?; f.write_joined(parameters_to_write, ", ")?; @@ -391,8 +423,8 @@ impl HirDisplay for ApplicationTy { let trait_ = f.db.trait_data(trait_); let type_alias = f.db.type_alias_data(type_alias); - // Use placeholder associated types when the target is source code (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) - if f.display_target.is_source_code() || self.parameters.len() > 1 { + // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) + if f.display_target.is_test() || self.parameters.len() > 1 { write!(f, "{}::{}", trait_.name, type_alias.name)?; if self.parameters.len() > 0 { write!(f, "<")?; diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 7ad8b5830..e98d7c064 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -1,7 +1,7 @@ use expect_test::expect; use test_utils::mark; -use super::{check_infer, check_infer_with_mismatches, check_types}; +use super::{check_infer, check_infer_with_mismatches, check_types, check_types_source_code}; #[test] fn infer_await() { @@ -907,7 +907,7 @@ fn test(t: T) { (*t); } } #[test] -fn associated_type_placeholder() { +fn associated_type_inlay_hints() { check_types( r#" pub trait ApplyL { @@ -929,7 +929,7 @@ fn test() { } #[test] -fn associated_type_placeholder_2() { +fn associated_type_inlay_hints_2() { check_types( r#" pub trait ApplyL { @@ -945,6 +945,45 @@ fn test(t: T) { ); } +#[test] +fn associated_type_placeholder() { + check_types_source_code( + r#" +pub trait ApplyL { + type Out; +} + +pub struct RefMutL; + +impl ApplyL for RefMutL { + type Out = ::Out; +} + +fn test() { + let y: as ApplyL>::Out = no_matter; + y; +} //^ ApplyL::Out +"#, + ); +} + +#[test] +fn associated_type_placeholder_2() { + check_types_source_code( + r#" +pub trait ApplyL { + type Out; +} +fn foo(t: T) -> ::Out; + +fn test(t: T) { + let y = foo(t); + y; +} //^ ApplyL::Out +"#, + ); +} + #[test] fn argument_impl_trait() { check_infer_with_mismatches( -- cgit v1.2.3 From ef2f7bb2438e66fd046791bb67849b6c61d946ab Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Wed, 28 Oct 2020 12:29:42 +0100 Subject: do not use associated types placeholder for inlay hint Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/hir_ty/src/display.rs | 104 +++++++++++++-------------- crates/hir_ty/src/tests.rs | 8 ++- crates/hir_ty/src/tests/method_resolution.rs | 40 +++++------ crates/hir_ty/src/tests/regression.rs | 8 +-- crates/hir_ty/src/tests/traits.rs | 82 +++------------------ crates/ide/src/inlay_hints.rs | 21 ++++++ 6 files changed, 108 insertions(+), 155 deletions(-) diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index f1232a72f..ddfd8c8af 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -74,9 +74,29 @@ pub trait HirDisplay { curr_size: 0, max_size: None, omit_verbose_types: false, - #[cfg(not(test))] 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 { + 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 }, }) { Ok(()) => {} @@ -138,7 +158,6 @@ enum DisplayTarget { /// The generated code should compile, so paths need to be qualified. SourceCode { module_id: ModuleId }, /// Only for test purpose to keep real types - #[cfg(test)] Test { module_id: ModuleId }, } @@ -147,14 +166,7 @@ impl DisplayTarget { matches!(self, Self::SourceCode {..}) } fn is_test(&self) -> bool { - #[cfg(test)] - { - matches!(self, Self::Test {..}) - } - #[cfg(not(test))] - { - false - } + matches!(self, Self::Test {..}) } } @@ -344,21 +356,7 @@ impl HirDisplay for ApplicationTy { }; write!(f, "{}", name)?; } - DisplayTarget::SourceCode { 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 } => { + DisplayTarget::SourceCode { module_id } | DisplayTarget::Test { module_id } => { if let Some(path) = find_path::find_path( f.db.upcast(), ItemInNs::Types(def_id.into()), @@ -374,40 +372,38 @@ impl HirDisplay for ApplicationTy { } if self.parameters.len() > 0 { - let parameters_to_write = if f.display_target.is_source_code() - || f.display_target.is_test() - || f.omit_verbose_types() - { - match self - .ctor - .as_generic_def() - .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) => { - let mut default_from = 0; - for (i, parameter) in self.parameters.iter().enumerate() { - 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 { + let parameters_to_write = + if f.display_target.is_source_code() || f.omit_verbose_types() { + match self + .ctor + .as_generic_def() + .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) => { + let mut default_from = 0; + for (i, parameter) in self.parameters.iter().enumerate() { + 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; + } + } } } + &self.parameters.0[0..default_from] } - &self.parameters.0[0..default_from] } - } - } else { - self.parameters.0.as_ref() - }; + } else { + self.parameters.0.as_ref() + }; if !parameters_to_write.is_empty() { write!(f, "<")?; f.write_joined(parameters_to_write, ", ")?; diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 0445efc9e..510baadf2 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs @@ -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", " ")) }; 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!( buf, "{}{:?} '{}': {}\n", macro_prefix, range, ellipsize(text, 15), - ty.display(&db) + ty.display_test(&db, module).unwrap() ); } if include_mismatches { @@ -174,13 +175,14 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { for (src_ptr, mismatch) in &mismatches { let range = src_ptr.value.text_range(); 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!( buf, "{}{:?}: expected {}, got {}\n", macro_prefix, range, - mismatch.expected.display(&db), - mismatch.actual.display(&db), + mismatch.expected.display_test(&db, module).unwrap(), + mismatch.actual.display_test(&db, module).unwrap(), ); } } diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 0f17ff151..596d4f182 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs @@ -108,16 +108,16 @@ fn infer_associated_method_with_modules() { check_infer( r#" mod a { - struct A; + pub struct A; impl A { pub fn thing() -> A { A {} }} } mod b { - struct B; + pub struct B; impl B { pub fn thing() -> u32 { 99 }} - mod c { - struct C; + pub mod c { + pub struct C; impl C { pub fn thing() -> C { C {} }} } } @@ -130,22 +130,22 @@ fn infer_associated_method_with_modules() { } "#, expect![[r#" - 55..63 '{ A {} }': A - 57..61 'A {}': A - 125..131 '{ 99 }': u32 - 127..129 '99': u32 - 201..209 '{ C {} }': C - 203..207 'C {}': C - 240..324 '{ ...g(); }': () - 250..251 'x': A - 254..265 'a::A::thing': fn thing() -> A - 254..267 'a::A::thing()': A - 277..278 'y': u32 - 281..292 'b::B::thing': fn thing() -> u32 - 281..294 'b::B::thing()': u32 - 304..305 'z': C - 308..319 'c::C::thing': fn thing() -> C - 308..321 'c::C::thing()': C + 59..67 '{ A {} }': a::A + 61..65 'A {}': a::A + 133..139 '{ 99 }': u32 + 135..137 '99': u32 + 217..225 '{ C {} }': c::C + 219..223 'C {}': c::C + 256..340 '{ ...g(); }': () + 266..267 'x': a::A + 270..281 'a::A::thing': fn thing() -> A + 270..283 'a::A::thing()': a::A + 293..294 'y': u32 + 297..308 'b::B::thing': fn thing() -> u32 + 297..310 'b::B::thing()': u32 + 320..321 'z': c::C + 324..335 'c::C::thing': fn thing() -> C + 324..337 'c::C::thing()': c::C "#]], ); } diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 66e171f24..42d08f12c 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs @@ -831,11 +831,11 @@ fn issue_4966() { 356..362 'repeat': Repeat f64>> 365..390 'Repeat...nner }': Repeat f64>> 383..388 'inner': Map<|&f64| -> f64> - 401..404 'vec': Vec< f64>> as IntoIterator>::Item> - 407..416 'from_iter': fn from_iter< f64>> as IntoIterator>::Item, Repeat f64>>>(Repeat f64>>) -> Vec< f64>> as IntoIterator>::Item> - 407..424 'from_i...epeat)': Vec< f64>> as IntoIterator>::Item> + 401..404 'vec': Vec f64>>>> + 407..416 'from_iter': fn from_iter f64>>>, Repeat f64>>>(Repeat f64>>) -> Vec< f64>> as IntoIterator>::Item> + 407..424 'from_i...epeat)': Vec f64>>>> 417..423 'repeat': Repeat f64>> - 431..434 'vec': Vec< f64>> as IntoIterator>::Item> + 431..434 'vec': Vec f64>>>> 431..444 'vec.foo_bar()': {unknown} "#]], ); diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index e98d7c064..4d193dea9 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -1,7 +1,7 @@ use expect_test::expect; 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] fn infer_await() { @@ -384,12 +384,12 @@ fn infer_project_associated_type() { 108..261 '{ ...ter; }': () 118..119 'x': u32 145..146 '1': u32 - 156..157 'y': ::Item - 183..192 'no_matter': ::Item - 202..203 'z': ::Item - 215..224 'no_matter': ::Item - 234..235 'a': ::Item - 249..258 'no_matter': ::Item + 156..157 'y': Iterable::Item + 183..192 'no_matter': Iterable::Item + 202..203 'z': Iterable::Item + 215..224 'no_matter': Iterable::Item + 234..235 'a': Iterable::Item + 249..258 'no_matter': Iterable::Item "#]], ); } @@ -945,45 +945,6 @@ fn test(t: T) { ); } -#[test] -fn associated_type_placeholder() { - check_types_source_code( - r#" -pub trait ApplyL { - type Out; -} - -pub struct RefMutL; - -impl ApplyL for RefMutL { - type Out = ::Out; -} - -fn test() { - let y: as ApplyL>::Out = no_matter; - y; -} //^ ApplyL::Out -"#, - ); -} - -#[test] -fn associated_type_placeholder_2() { - check_types_source_code( - r#" -pub trait ApplyL { - type Out; -} -fn foo(t: T) -> ::Out; - -fn test(t: T) { - let y = foo(t); - y; -} //^ ApplyL::Out -"#, - ); -} - #[test] fn argument_impl_trait() { check_infer_with_mismatches( @@ -2158,7 +2119,7 @@ fn unselected_projection_on_impl_self() { "#, expect![[r#" 40..44 'self': &Self - 46..47 'x': ::Item + 46..47 'x': Trait::Item 126..130 'self': &S 132..133 'x': u32 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::Bar { - let y = Default::default(); - - y - } - "#, - expect![[r#" - 122..164 '{ ... y }': ::Bar - 132..133 'y': ::Bar - 136..152 'Defaul...efault': fn default<::Bar>() -> ::Bar - 136..154 'Defaul...ault()': ::Bar - 161..162 'y': ::Bar - "#]], - ); -} diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 49d8e4ae1..adb93efd7 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -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::Bar { + let y = Default::default(); + //^ ::Bar + + y + } + "#, + ); + } } -- cgit v1.2.3 From 0aca7b78de234526e1d85a4dfd23fb4f374908ea Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Wed, 28 Oct 2020 15:09:47 +0100 Subject: do not use associated types placeholder for inlay hint Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/hir_ty/src/display.rs | 56 +++++++++++----------------- crates/hir_ty/src/tests.rs | 8 ++-- crates/hir_ty/src/tests/method_resolution.rs | 40 ++++++++++---------- 3 files changed, 44 insertions(+), 60 deletions(-) diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index ddfd8c8af..0bf181a92 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -84,26 +84,17 @@ pub trait HirDisplay { } /// Returns a String representation of `self` for test purposes - fn display_test<'a>( - &'a self, - db: &'a dyn HirDatabase, - module_id: ModuleId, - ) -> Result { - let mut result = String::new(); - match self.hir_fmt(&mut HirFormatter { + fn display_test<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self> + where + Self: Sized, + { + HirDisplayWrapper { db, - fmt: &mut result, - buf: String::with_capacity(20), - curr_size: 0, + t: self, max_size: None, omit_verbose_types: false, - display_target: DisplayTarget::Test { module_id }, - }) { - Ok(()) => {} - Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"), - Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e), - }; - Ok(result) + display_target: DisplayTarget::Test, + } } } @@ -158,7 +149,7 @@ enum DisplayTarget { /// The generated code should compile, so paths need to be qualified. SourceCode { module_id: ModuleId }, /// Only for test purpose to keep real types - Test { module_id: ModuleId }, + Test, } impl DisplayTarget { @@ -166,7 +157,7 @@ impl DisplayTarget { matches!(self, Self::SourceCode {..}) } fn is_test(&self) -> bool { - matches!(self, Self::Test {..}) + matches!(self, Self::Test) } } @@ -348,7 +339,7 @@ impl HirDisplay for ApplicationTy { } TypeCtor::Adt(def_id) => { match f.display_target { - DisplayTarget::Diagnostics => { + DisplayTarget::Diagnostics | DisplayTarget::Test => { let name = match def_id { AdtId::StructId(it) => f.db.struct_data(it).name.clone(), AdtId::UnionId(it) => f.db.union_data(it).name.clone(), @@ -356,7 +347,7 @@ impl HirDisplay for ApplicationTy { }; write!(f, "{}", name)?; } - DisplayTarget::SourceCode { module_id } | DisplayTarget::Test { module_id } => { + DisplayTarget::SourceCode { module_id } => { if let Some(path) = find_path::find_path( f.db.upcast(), ItemInNs::Types(def_id.into()), @@ -417,28 +408,23 @@ impl HirDisplay for ApplicationTy { _ => panic!("not an associated type"), }; let trait_ = f.db.trait_data(trait_); - let type_alias = f.db.type_alias_data(type_alias); + let type_alias_data = f.db.type_alias_data(type_alias); // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) - if f.display_target.is_test() || self.parameters.len() > 1 { - write!(f, "{}::{}", trait_.name, type_alias.name)?; + if f.display_target.is_test() { + write!(f, "{}::{}", trait_.name, type_alias_data.name)?; if self.parameters.len() > 0 { write!(f, "<")?; f.write_joined(&*self.parameters.0, ", ")?; write!(f, ">")?; } } else { - if self.parameters.len() == 1 { - write!( - f, - "<{} as {}>::{}", - self.parameters.as_single().display(f.db), - trait_.name, - type_alias.name - )?; - } else { - write!(f, "{}::{}", trait_.name, type_alias.name)?; - } + let projection_ty = ProjectionTy { + associated_ty: type_alias, + parameters: self.parameters.clone(), + }; + + projection_ty.hir_fmt(f)?; } } TypeCtor::ForeignType(type_alias) => { diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 510baadf2..29b178ec1 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs @@ -157,14 +157,13 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { (node.value.text_range(), node.value.text().to_string().replace("\n", " ")) }; 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!( buf, "{}{:?} '{}': {}\n", macro_prefix, range, ellipsize(text, 15), - ty.display_test(&db, module).unwrap() + ty.display_test(&db) ); } if include_mismatches { @@ -175,14 +174,13 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { for (src_ptr, mismatch) in &mismatches { let range = src_ptr.value.text_range(); 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!( buf, "{}{:?}: expected {}, got {}\n", macro_prefix, range, - mismatch.expected.display_test(&db, module).unwrap(), - mismatch.actual.display_test(&db, module).unwrap(), + mismatch.expected.display_test(&db), + mismatch.actual.display_test(&db), ); } } diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 596d4f182..0f17ff151 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs @@ -108,16 +108,16 @@ fn infer_associated_method_with_modules() { check_infer( r#" mod a { - pub struct A; + struct A; impl A { pub fn thing() -> A { A {} }} } mod b { - pub struct B; + struct B; impl B { pub fn thing() -> u32 { 99 }} - pub mod c { - pub struct C; + mod c { + struct C; impl C { pub fn thing() -> C { C {} }} } } @@ -130,22 +130,22 @@ fn infer_associated_method_with_modules() { } "#, expect![[r#" - 59..67 '{ A {} }': a::A - 61..65 'A {}': a::A - 133..139 '{ 99 }': u32 - 135..137 '99': u32 - 217..225 '{ C {} }': c::C - 219..223 'C {}': c::C - 256..340 '{ ...g(); }': () - 266..267 'x': a::A - 270..281 'a::A::thing': fn thing() -> A - 270..283 'a::A::thing()': a::A - 293..294 'y': u32 - 297..308 'b::B::thing': fn thing() -> u32 - 297..310 'b::B::thing()': u32 - 320..321 'z': c::C - 324..335 'c::C::thing': fn thing() -> C - 324..337 'c::C::thing()': c::C + 55..63 '{ A {} }': A + 57..61 'A {}': A + 125..131 '{ 99 }': u32 + 127..129 '99': u32 + 201..209 '{ C {} }': C + 203..207 'C {}': C + 240..324 '{ ...g(); }': () + 250..251 'x': A + 254..265 'a::A::thing': fn thing() -> A + 254..267 'a::A::thing()': A + 277..278 'y': u32 + 281..292 'b::B::thing': fn thing() -> u32 + 281..294 'b::B::thing()': u32 + 304..305 'z': C + 308..319 'c::C::thing': fn thing() -> C + 308..321 'c::C::thing()': C "#]], ); } -- cgit v1.2.3 From ec3638adb93ea425f825cc976bcae816f7e5c50b Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Wed, 28 Oct 2020 15:42:51 +0100 Subject: do not use associated types placeholder for inlay hint Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/hir_ty/src/display.rs | 12 ++++++++++-- crates/hir_ty/src/tests.rs | 2 +- crates/hir_ty/src/tests/regression.rs | 2 +- crates/hir_ty/src/tests/traits.rs | 9 +++++---- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 0bf181a92..822ef4477 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs @@ -332,7 +332,11 @@ impl HirDisplay for ApplicationTy { let ret_display = if f.omit_verbose_types() { ret.display_truncated(f.db, f.max_size) } else { - ret.display(f.db) + if f.display_target.is_test() { + ret.display_test(f.db) + } else { + ret.display(f.db) + } }; write!(f, " -> {}", ret_display)?; } @@ -472,7 +476,11 @@ impl HirDisplay for ApplicationTy { let ret_display = if f.omit_verbose_types() { sig.ret().display_truncated(f.db, f.max_size) } else { - sig.ret().display(f.db) + if f.display_target.is_test() { + sig.ret().display_test(f.db) + } else { + sig.ret().display(f.db) + } }; write!(f, " -> {}", ret_display)?; } else { diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 29b178ec1..104ef334c 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs @@ -74,7 +74,7 @@ fn check_types_impl(ra_fixture: &str, display_source: bool) { let module = db.module_for_file(file_id); ty.display_source_code(&db, module).unwrap() } else { - ty.display(&db).to_string() + ty.display_test(&db).to_string() }; assert_eq!(expected, actual); checked_one = true; diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 42d08f12c..94d86b0d1 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs @@ -832,7 +832,7 @@ fn issue_4966() { 365..390 'Repeat...nner }': Repeat f64>> 383..388 'inner': Map<|&f64| -> f64> 401..404 'vec': Vec f64>>>> - 407..416 'from_iter': fn from_iter f64>>>, Repeat f64>>>(Repeat f64>>) -> Vec< f64>> as IntoIterator>::Item> + 407..416 'from_iter': fn from_iter f64>>>, Repeat f64>>>(Repeat f64>>) -> Vec f64>>>> 407..424 'from_i...epeat)': Vec f64>>>> 417..423 'repeat': Repeat f64>> 431..434 'vec': Vec f64>>>> diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 4d193dea9..41d097519 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -907,7 +907,8 @@ fn test(t: T) { (*t); } } #[test] -fn associated_type_inlay_hints() { +fn associated_type_placeholder() { + // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. check_types( r#" pub trait ApplyL { @@ -923,13 +924,13 @@ impl ApplyL for RefMutL { fn test() { let y: as ApplyL>::Out = no_matter; y; -} //^ ::Out +} //^ ApplyL::Out "#, ); } #[test] -fn associated_type_inlay_hints_2() { +fn associated_type_placeholder_2() { check_types( r#" pub trait ApplyL { @@ -940,7 +941,7 @@ fn foo(t: T) -> ::Out; fn test(t: T) { let y = foo(t); y; -} //^ ::Out +} //^ ApplyL::Out "#, ); } -- cgit v1.2.3