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 11:20:05 +01:00
parent 73161cc9cd
commit 8762b797fd
2 changed files with 102 additions and 31 deletions

View file

@ -74,7 +74,10 @@ 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)]
display_target: DisplayTarget::Test { module_id },
}) { }) {
Ok(()) => {} Ok(()) => {}
Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"), Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
@ -134,12 +137,25 @@ enum DisplayTarget {
/// Display types for inserting them in source files. /// Display types for inserting them in source files.
/// 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
#[cfg(test)]
Test { module_id: ModuleId },
} }
impl DisplayTarget { impl DisplayTarget {
fn is_source_code(&self) -> bool { fn is_source_code(&self) -> bool {
matches!(self, Self::SourceCode {..}) matches!(self, Self::SourceCode {..})
} }
fn is_test(&self) -> bool {
#[cfg(test)]
{
matches!(self, Self::Test {..})
}
#[cfg(not(test))]
{
false
}
}
} }
#[derive(Debug)] #[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 { if self.parameters.len() > 0 {
let parameters_to_write = let parameters_to_write = if f.display_target.is_source_code()
if f.display_target.is_source_code() || f.omit_verbose_types() { || f.display_target.is_test()
match self || f.omit_verbose_types()
.ctor {
.as_generic_def() match self
.map(|generic_def_id| f.db.generic_defaults(generic_def_id)) .ctor
.filter(|defaults| !defaults.is_empty()) .as_generic_def()
{ .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
None => self.parameters.0.as_ref(), .filter(|defaults| !defaults.is_empty())
Some(default_parameters) => { {
let mut default_from = 0; None => self.parameters.0.as_ref(),
for (i, parameter) in self.parameters.iter().enumerate() { Some(default_parameters) => {
match (parameter, default_parameters.get(i)) { let mut default_from = 0;
(&Ty::Unknown, _) | (_, None) => { 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; 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() { if !parameters_to_write.is_empty() {
write!(f, "<")?; write!(f, "<")?;
f.write_joined(parameters_to_write, ", ")?; f.write_joined(parameters_to_write, ", ")?;
@ -391,8 +423,8 @@ impl HirDisplay for ApplicationTy {
let trait_ = f.db.trait_data(trait_); let trait_ = f.db.trait_data(trait_);
let type_alias = f.db.type_alias_data(type_alias); 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) // 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_source_code() || self.parameters.len() > 1 { if f.display_target.is_test() || self.parameters.len() > 1 {
write!(f, "{}::{}", trait_.name, type_alias.name)?; write!(f, "{}::{}", trait_.name, type_alias.name)?;
if self.parameters.len() > 0 { if self.parameters.len() > 0 {
write!(f, "<")?; write!(f, "<")?;

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}; use super::{check_infer, check_infer_with_mismatches, check_types, check_types_source_code};
#[test] #[test]
fn infer_await() { fn infer_await() {
@ -907,7 +907,7 @@ fn test<T: Trait>(t: T) { (*t); }
} }
#[test] #[test]
fn associated_type_placeholder() { fn associated_type_inlay_hints() {
check_types( check_types(
r#" r#"
pub trait ApplyL { pub trait ApplyL {
@ -929,7 +929,7 @@ fn test<T: ApplyL>() {
} }
#[test] #[test]
fn associated_type_placeholder_2() { fn associated_type_inlay_hints_2() {
check_types( check_types(
r#" r#"
pub trait ApplyL { pub trait ApplyL {
@ -945,6 +945,45 @@ 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(