Merge pull request #19581 from Veykril/push-uvyutolsqnun

Render more lifetimes
This commit is contained in:
Lukas Wirth 2025-05-02 12:47:03 +00:00 committed by GitHub
commit 9625ef795d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 201 additions and 149 deletions

View File

@ -90,11 +90,26 @@ pub struct HirFormatter<'a> {
show_container_bounds: bool, show_container_bounds: bool,
omit_verbose_types: bool, omit_verbose_types: bool,
closure_style: ClosureStyle, closure_style: ClosureStyle,
display_lifetimes: DisplayLifetime,
display_kind: DisplayKind, display_kind: DisplayKind,
display_target: DisplayTarget, display_target: DisplayTarget,
bounds_formatting_ctx: BoundsFormattingCtx, bounds_formatting_ctx: BoundsFormattingCtx,
} }
// FIXME: To consider, ref and dyn trait lifetimes can be omitted if they are `'_`, path args should
// not be when in signatures
// So this enum does not encode this well enough
// Also 'static can be omitted for ref and dyn trait lifetimes in static/const item types
// FIXME: Also named lifetimes may be rendered in places where their name is not in scope?
#[derive(Copy, Clone)]
pub enum DisplayLifetime {
Always,
OnlyStatic,
OnlyNamed,
OnlyNamedOrStatic,
Never,
}
#[derive(Default)] #[derive(Default)]
enum BoundsFormattingCtx { enum BoundsFormattingCtx {
Entered { Entered {
@ -155,6 +170,21 @@ impl HirFormatter<'_> {
} }
} }
} }
fn render_lifetime(&self, lifetime: &Lifetime) -> bool {
match self.display_lifetimes {
DisplayLifetime::Always => true,
DisplayLifetime::OnlyStatic => matches!(***lifetime.interned(), LifetimeData::Static),
DisplayLifetime::OnlyNamed => {
matches!(***lifetime.interned(), LifetimeData::Placeholder(_))
}
DisplayLifetime::OnlyNamedOrStatic => matches!(
***lifetime.interned(),
LifetimeData::Static | LifetimeData::Placeholder(_)
),
DisplayLifetime::Never => false,
}
}
} }
pub trait HirDisplay { pub trait HirDisplay {
@ -189,6 +219,7 @@ pub trait HirDisplay {
display_kind, display_kind,
closure_style, closure_style,
show_container_bounds, show_container_bounds,
display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
} }
} }
@ -212,6 +243,7 @@ pub trait HirDisplay {
display_target, display_target,
display_kind: DisplayKind::Diagnostics, display_kind: DisplayKind::Diagnostics,
show_container_bounds: false, show_container_bounds: false,
display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
} }
} }
@ -236,6 +268,7 @@ pub trait HirDisplay {
display_target, display_target,
display_kind: DisplayKind::Diagnostics, display_kind: DisplayKind::Diagnostics,
show_container_bounds: false, show_container_bounds: false,
display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
} }
} }
@ -260,6 +293,7 @@ pub trait HirDisplay {
display_target, display_target,
display_kind: DisplayKind::Diagnostics, display_kind: DisplayKind::Diagnostics,
show_container_bounds: false, show_container_bounds: false,
display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
} }
} }
@ -284,6 +318,7 @@ pub trait HirDisplay {
display_target: DisplayTarget::from_crate(db, module_id.krate()), display_target: DisplayTarget::from_crate(db, module_id.krate()),
display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque }, display_kind: DisplayKind::SourceCode { target_module_id: module_id, allow_opaque },
show_container_bounds: false, show_container_bounds: false,
display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
bounds_formatting_ctx: Default::default(), bounds_formatting_ctx: Default::default(),
}) { }) {
Ok(()) => {} Ok(()) => {}
@ -312,6 +347,7 @@ pub trait HirDisplay {
display_target, display_target,
display_kind: DisplayKind::Test, display_kind: DisplayKind::Test,
show_container_bounds: false, show_container_bounds: false,
display_lifetimes: DisplayLifetime::Always,
} }
} }
@ -336,6 +372,7 @@ pub trait HirDisplay {
display_target, display_target,
display_kind: DisplayKind::Diagnostics, display_kind: DisplayKind::Diagnostics,
show_container_bounds, show_container_bounds,
display_lifetimes: DisplayLifetime::OnlyNamedOrStatic,
} }
} }
} }
@ -480,6 +517,7 @@ pub struct HirDisplayWrapper<'a, T> {
display_kind: DisplayKind, display_kind: DisplayKind,
display_target: DisplayTarget, display_target: DisplayTarget,
show_container_bounds: bool, show_container_bounds: bool,
display_lifetimes: DisplayLifetime,
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
@ -502,7 +540,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
self.t.hir_fmt(&mut HirFormatter { self.t.hir_fmt(&mut HirFormatter {
db: self.db, db: self.db,
fmt: f, fmt: f,
buf: String::with_capacity(20), buf: String::with_capacity(self.max_size.unwrap_or(20)),
curr_size: 0, curr_size: 0,
max_size: self.max_size, max_size: self.max_size,
entity_limit: self.limited_size, entity_limit: self.limited_size,
@ -511,6 +549,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
display_target: self.display_target, display_target: self.display_target,
closure_style: self.closure_style, closure_style: self.closure_style,
show_container_bounds: self.show_container_bounds, show_container_bounds: self.show_container_bounds,
display_lifetimes: self.display_lifetimes,
bounds_formatting_ctx: Default::default(), bounds_formatting_ctx: Default::default(),
}) })
} }
@ -519,6 +558,11 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
self.closure_style = c; self.closure_style = c;
self self
} }
pub fn with_lifetime_display(mut self, l: DisplayLifetime) -> Self {
self.display_lifetimes = l;
self
}
} }
impl<T> fmt::Display for HirDisplayWrapper<'_, T> impl<T> fmt::Display for HirDisplayWrapper<'_, T>
@ -1022,9 +1066,7 @@ impl HirDisplay for Ty {
kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => { kind @ (TyKind::Raw(m, t) | TyKind::Ref(m, _, t)) => {
if let TyKind::Ref(_, l, _) = kind { if let TyKind::Ref(_, l, _) = kind {
f.write_char('&')?; f.write_char('&')?;
if cfg!(test) { if f.render_lifetime(l) {
// rendering these unconditionally is probably too much (at least for inlay
// hints) so we gate it to testing only for the time being
l.hir_fmt(f)?; l.hir_fmt(f)?;
f.write_char(' ')?; f.write_char(' ')?;
} }
@ -1055,9 +1097,10 @@ impl HirDisplay for Ty {
}) })
}; };
let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) { let (preds_to_print, has_impl_fn_pred) = match t.kind(Interner) {
TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { TyKind::Dyn(dyn_ty) => {
let bounds = dyn_ty.bounds.skip_binders().interned(); let bounds = dyn_ty.bounds.skip_binders().interned();
(bounds.len(), contains_impl_fn(bounds)) let render_lifetime = f.render_lifetime(&dyn_ty.lifetime);
(bounds.len() + render_lifetime as usize, contains_impl_fn(bounds))
} }
TyKind::Alias(AliasTy::Opaque(OpaqueTy { TyKind::Alias(AliasTy::Opaque(OpaqueTy {
opaque_ty_id, opaque_ty_id,
@ -1479,7 +1522,7 @@ impl HirDisplay for Ty {
TyKind::BoundVar(idx) => idx.hir_fmt(f)?, TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
TyKind::Dyn(dyn_ty) => { TyKind::Dyn(dyn_ty) => {
// Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation. // Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation.
// FIXME: `Iterator::partition_in_place()` or `Vec::drain_filter()` may make it // FIXME: `Iterator::partition_in_place()` or `Vec::extract_if()` may make it
// more efficient when either of them hits stable. // more efficient when either of them hits stable.
let mut bounds: SmallVec<[_; 4]> = let mut bounds: SmallVec<[_; 4]> =
dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect(); dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect();
@ -1488,6 +1531,17 @@ impl HirDisplay for Ty {
bounds.extend(others); bounds.extend(others);
bounds.extend(auto_traits); bounds.extend(auto_traits);
if f.render_lifetime(&dyn_ty.lifetime) {
// we skip the binders in `write_bounds_like_dyn_trait_with_prefix`
bounds.push(Binders::empty(
Interner,
chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
ty: self.clone(),
lifetime: dyn_ty.lifetime.clone(),
}),
));
}
write_bounds_like_dyn_trait_with_prefix( write_bounds_like_dyn_trait_with_prefix(
f, f,
"dyn", "dyn",
@ -1989,7 +2043,6 @@ impl HirDisplay for LifetimeData {
write!(f, "{}", param_data.name.display(f.db, f.edition()))?; write!(f, "{}", param_data.name.display(f.db, f.edition()))?;
Ok(()) Ok(())
} }
_ if f.display_kind.is_source_code() => write!(f, "'_"),
LifetimeData::BoundVar(idx) => idx.hir_fmt(f), LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
LifetimeData::InferenceVar(_) => write!(f, "_"), LifetimeData::InferenceVar(_) => write!(f, "_"),
LifetimeData::Static => write!(f, "'static"), LifetimeData::Static => write!(f, "'static"),

View File

@ -561,7 +561,7 @@ trait Foo {}
fn test(f: impl Foo, g: &(impl Foo + ?Sized)) { fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
let _: &dyn Foo = &f; let _: &dyn Foo = &f;
let _: &dyn Foo = g; let _: &dyn Foo = g;
//^ expected &'? dyn Foo, got &'? impl Foo + ?Sized //^ expected &'? (dyn Foo + 'static), got &'? impl Foo + ?Sized
} }
"#, "#,
); );
@ -827,11 +827,11 @@ struct V<T> { t: T }
fn main() { fn main() {
let a: V<&dyn Tr>; let a: V<&dyn Tr>;
(a,) = V { t: &S }; (a,) = V { t: &S };
//^^^^expected V<&'? S>, got (V<&'? dyn Tr>,) //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,)
let mut a: V<&dyn Tr> = V { t: &S }; let mut a: V<&dyn Tr> = V { t: &S };
(a,) = V { t: &S }; (a,) = V { t: &S };
//^^^^expected V<&'? S>, got (V<&'? dyn Tr>,) //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,)
} }
"#, "#,
); );

View File

@ -65,13 +65,13 @@ trait A {
} }
trait B: A {} trait B: A {}
fn test( fn test<'a>(
_: &(dyn A<Assoc = ()> + Send), _: &(dyn A<Assoc = ()> + Send),
//^ &'_ (dyn A<Assoc = ()> + Send) //^ &(dyn A<Assoc = ()> + Send + 'static)
_: &(dyn Send + A<Assoc = ()>), _: &'a (dyn Send + A<Assoc = ()>),
//^ &'_ (dyn A<Assoc = ()> + Send) //^ &'a (dyn A<Assoc = ()> + Send + 'static)
_: &dyn B<Assoc = ()>, _: &dyn B<Assoc = ()>,
//^ &'_ (dyn B<Assoc = ()>) //^ &(dyn B<Assoc = ()> + 'static)
) {} ) {}
"#, "#,
); );
@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
trait Foo<'a> {} trait Foo<'a> {}
fn foo(foo: &dyn for<'a> Foo<'a>) {} fn foo(foo: &dyn for<'a> Foo<'a>) {}
// ^^^ &'_ dyn Foo<'_> // ^^^ &(dyn Foo<'?> + 'static)
"#, "#,
); );
} }
@ -111,11 +111,11 @@ fn test(
b; b;
//^ impl Foo //^ impl Foo
c; c;
//^ &'_ impl Foo + ?Sized //^ &impl Foo + ?Sized
d; d;
//^ S<impl Foo> //^ S<impl Foo>
ref_any; ref_any;
//^^^^^^^ &'_ impl ?Sized //^^^^^^^ &impl ?Sized
empty; empty;
} //^^^^^ impl Sized } //^^^^^ impl Sized
"#, "#,
@ -192,7 +192,7 @@ fn test(
b; b;
//^ fn(impl Foo) -> impl Foo //^ fn(impl Foo) -> impl Foo
c; c;
} //^ fn(&'_ impl Foo + ?Sized) -> &'_ impl Foo + ?Sized } //^ fn(&impl Foo + ?Sized) -> &impl Foo + ?Sized
"#, "#,
); );
} }

View File

@ -1153,9 +1153,9 @@ fn dyn_trait_super_trait_not_in_scope() {
51..55 'self': &'? Self 51..55 'self': &'? Self
64..69 '{ 0 }': u32 64..69 '{ 0 }': u32
66..67 '0': u32 66..67 '0': u32
176..177 'd': &'? dyn Trait 176..177 'd': &'? (dyn Trait + 'static)
191..207 '{ ...o(); }': () 191..207 '{ ...o(); }': ()
197..198 'd': &'? dyn Trait 197..198 'd': &'? (dyn Trait + 'static)
197..204 'd.foo()': u32 197..204 'd.foo()': u32
"#]], "#]],
); );
@ -2019,10 +2019,10 @@ impl dyn Error + Send {
/// Attempts to downcast the box to a concrete type. /// Attempts to downcast the box to a concrete type.
pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> { pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
let err: Box<dyn Error> = self; let err: Box<dyn Error> = self;
// ^^^^ expected Box<dyn Error>, got Box<dyn Error + Send> // ^^^^ expected Box<dyn Error + 'static>, got Box<dyn Error + Send + 'static>
// FIXME, type mismatch should not occur // FIXME, type mismatch should not occur
<dyn Error>::downcast(err).map_err(|_| loop {}) <dyn Error>::downcast(err).map_err(|_| loop {})
//^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error>) -> Result<Box<{unknown}>, Box<dyn Error>> //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + 'static>) -> Result<Box<{unknown}>, Box<dyn Error + 'static>>
} }
} }
"#, "#,

View File

@ -629,7 +629,7 @@ fn issue_4053_diesel_where_clauses() {
488..522 '{ ... }': () 488..522 '{ ... }': ()
498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> 498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
498..508 'self.order': O 498..508 'self.order': O
498..515 'self.o...into()': dyn QueryFragment<DB> 498..515 'self.o...into()': dyn QueryFragment<DB> + 'static
"#]], "#]],
); );
} }
@ -773,7 +773,7 @@ fn issue_4800() {
"#, "#,
expect![[r#" expect![[r#"
379..383 'self': &'? mut PeerSet<D> 379..383 'self': &'? mut PeerSet<D>
401..424 '{ ... }': dyn Future<Output = ()> 401..424 '{ ... }': dyn Future<Output = ()> + 'static
411..418 'loop {}': ! 411..418 'loop {}': !
416..418 '{}': () 416..418 '{}': ()
575..579 'self': &'? mut Self 575..579 'self': &'? mut Self

View File

@ -2741,11 +2741,11 @@ impl B for Astruct {}
715..744 '#[rust...1i32])': Box<[i32; 1], Global> 715..744 '#[rust...1i32])': Box<[i32; 1], Global>
737..743 '[1i32]': [i32; 1] 737..743 '[1i32]': [i32; 1]
738..742 '1i32': i32 738..742 '1i32': i32
755..756 'v': Vec<Box<dyn B, Global>, Global> 755..756 'v': Vec<Box<dyn B + 'static, Global>, Global>
776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B, Global>, Global>(Box<[Box<dyn B, Global>], Global>) -> Vec<Box<dyn B, Global>, Global> 776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B + 'static, Global>, Global>(Box<[Box<dyn B + 'static, Global>], Global>) -> Vec<Box<dyn B + 'static, Global>, Global>
776..850 '<[_]> ...ct)]))': Vec<Box<dyn B, Global>, Global> 776..850 '<[_]> ...ct)]))': Vec<Box<dyn B + 'static, Global>, Global>
794..849 '#[rust...uct)])': Box<[Box<dyn B, Global>; 1], Global> 794..849 '#[rust...uct)])': Box<[Box<dyn B + 'static, Global>; 1], Global>
816..848 '[#[rus...ruct)]': [Box<dyn B, Global>; 1] 816..848 '[#[rus...ruct)]': [Box<dyn B + 'static, Global>; 1]
817..847 '#[rust...truct)': Box<Astruct, Global> 817..847 '#[rust...truct)': Box<Astruct, Global>
839..846 'Astruct': Astruct 839..846 'Astruct': Astruct
"#]], "#]],

View File

@ -1475,26 +1475,26 @@ fn test(x: Box<dyn Trait<u64>>, y: &dyn Trait<u64>) {
expect![[r#" expect![[r#"
29..33 'self': &'? Self 29..33 'self': &'? Self
54..58 'self': &'? Self 54..58 'self': &'? Self
198..200 '{}': Box<dyn Trait<u64>> 198..200 '{}': Box<dyn Trait<u64> + 'static>
210..211 'x': Box<dyn Trait<u64>> 210..211 'x': Box<dyn Trait<u64> + 'static>
234..235 'y': &'? dyn Trait<u64> 234..235 'y': &'? (dyn Trait<u64> + 'static)
254..371 '{ ...2(); }': () 254..371 '{ ...2(); }': ()
260..261 'x': Box<dyn Trait<u64>> 260..261 'x': Box<dyn Trait<u64> + 'static>
267..268 'y': &'? dyn Trait<u64> 267..268 'y': &'? (dyn Trait<u64> + 'static)
278..279 'z': Box<dyn Trait<u64>> 278..279 'z': Box<dyn Trait<u64> + 'static>
282..285 'bar': fn bar() -> Box<dyn Trait<u64>> 282..285 'bar': fn bar() -> Box<dyn Trait<u64> + 'static>
282..287 'bar()': Box<dyn Trait<u64>> 282..287 'bar()': Box<dyn Trait<u64> + 'static>
293..294 'x': Box<dyn Trait<u64>> 293..294 'x': Box<dyn Trait<u64> + 'static>
293..300 'x.foo()': u64 293..300 'x.foo()': u64
306..307 'y': &'? dyn Trait<u64> 306..307 'y': &'? (dyn Trait<u64> + 'static)
306..313 'y.foo()': u64 306..313 'y.foo()': u64
319..320 'z': Box<dyn Trait<u64>> 319..320 'z': Box<dyn Trait<u64> + 'static>
319..326 'z.foo()': u64 319..326 'z.foo()': u64
332..333 'x': Box<dyn Trait<u64>> 332..333 'x': Box<dyn Trait<u64> + 'static>
332..340 'x.foo2()': i64 332..340 'x.foo2()': i64
346..347 'y': &'? dyn Trait<u64> 346..347 'y': &'? (dyn Trait<u64> + 'static)
346..354 'y.foo2()': i64 346..354 'y.foo2()': i64
360..361 'z': Box<dyn Trait<u64>> 360..361 'z': Box<dyn Trait<u64> + 'static>
360..368 'z.foo2()': i64 360..368 'z.foo2()': i64
"#]], "#]],
); );
@ -1523,14 +1523,14 @@ fn test(s: S<u32, i32>) {
expect![[r#" expect![[r#"
32..36 'self': &'? Self 32..36 'self': &'? Self
102..106 'self': &'? S<T, U> 102..106 'self': &'? S<T, U>
128..139 '{ loop {} }': &'? dyn Trait<T, U> 128..139 '{ loop {} }': &'? (dyn Trait<T, U> + 'static)
130..137 'loop {}': ! 130..137 'loop {}': !
135..137 '{}': () 135..137 '{}': ()
175..179 'self': &'? Self 175..179 'self': &'? Self
251..252 's': S<u32, i32> 251..252 's': S<u32, i32>
267..289 '{ ...z(); }': () 267..289 '{ ...z(); }': ()
273..274 's': S<u32, i32> 273..274 's': S<u32, i32>
273..280 's.bar()': &'? dyn Trait<u32, i32> 273..280 's.bar()': &'? (dyn Trait<u32, i32> + 'static)
273..286 's.bar().baz()': (u32, i32) 273..286 's.bar().baz()': (u32, i32)
"#]], "#]],
); );
@ -1556,20 +1556,20 @@ fn test(x: Trait, y: &Trait) -> u64 {
}"#, }"#,
expect![[r#" expect![[r#"
26..30 'self': &'? Self 26..30 'self': &'? Self
60..62 '{}': dyn Trait 60..62 '{}': dyn Trait + 'static
72..73 'x': dyn Trait 72..73 'x': dyn Trait + 'static
82..83 'y': &'? dyn Trait 82..83 'y': &'? (dyn Trait + 'static)
100..175 '{ ...o(); }': u64 100..175 '{ ...o(); }': u64
106..107 'x': dyn Trait 106..107 'x': dyn Trait + 'static
113..114 'y': &'? dyn Trait 113..114 'y': &'? (dyn Trait + 'static)
124..125 'z': dyn Trait 124..125 'z': dyn Trait + 'static
128..131 'bar': fn bar() -> dyn Trait 128..131 'bar': fn bar() -> dyn Trait + 'static
128..133 'bar()': dyn Trait 128..133 'bar()': dyn Trait + 'static
139..140 'x': dyn Trait 139..140 'x': dyn Trait + 'static
139..146 'x.foo()': u64 139..146 'x.foo()': u64
152..153 'y': &'? dyn Trait 152..153 'y': &'? (dyn Trait + 'static)
152..159 'y.foo()': u64 152..159 'y.foo()': u64
165..166 'z': dyn Trait 165..166 'z': dyn Trait + 'static
165..172 'z.foo()': u64 165..172 'z.foo()': u64
"#]], "#]],
); );
@ -1589,10 +1589,10 @@ fn main() {
expect![[r#" expect![[r#"
31..35 'self': &'? S 31..35 'self': &'? S
37..39 '{}': () 37..39 '{}': ()
47..48 '_': &'? dyn Fn(S) 47..48 '_': &'? (dyn Fn(S) + 'static)
58..60 '{}': () 58..60 '{}': ()
71..105 '{ ...()); }': () 71..105 '{ ...()); }': ()
77..78 'f': fn f(&'? dyn Fn(S)) 77..78 'f': fn f(&'? (dyn Fn(S) + 'static))
77..102 'f(&|nu...foo())': () 77..102 'f(&|nu...foo())': ()
79..101 '&|numb....foo()': &'? impl Fn(S) 79..101 '&|numb....foo()': &'? impl Fn(S)
80..101 '|numbe....foo()': impl Fn(S) 80..101 '|numbe....foo()': impl Fn(S)
@ -2927,13 +2927,13 @@ fn test(x: &dyn Foo) {
foo(x); foo(x);
}"#, }"#,
expect![[r#" expect![[r#"
21..22 'x': &'? dyn Foo 21..22 'x': &'? (dyn Foo + 'static)
34..36 '{}': () 34..36 '{}': ()
46..47 'x': &'? dyn Foo 46..47 'x': &'? (dyn Foo + 'static)
59..74 '{ foo(x); }': () 59..74 '{ foo(x); }': ()
65..68 'foo': fn foo(&'? dyn Foo) 65..68 'foo': fn foo(&'? (dyn Foo + 'static))
65..71 'foo(x)': () 65..71 'foo(x)': ()
69..70 'x': &'? dyn Foo 69..70 'x': &'? (dyn Foo + 'static)
"#]], "#]],
); );
} }
@ -3210,13 +3210,13 @@ fn foo() {
218..324 '{ ...&s); }': () 218..324 '{ ...&s); }': ()
228..229 's': Option<i32> 228..229 's': Option<i32>
232..236 'None': Option<i32> 232..236 'None': Option<i32>
246..247 'f': Box<dyn FnOnce(&'? Option<i32>)> 246..247 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static>
281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>)> 281..310 'Box { ... {}) }': Box<dyn FnOnce(&'? Option<i32>) + 'static>
294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option<i32>) 294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option<i32>)
300..307 '|ps| {}': impl FnOnce(&'? Option<i32>) 300..307 '|ps| {}': impl FnOnce(&'? Option<i32>)
301..303 'ps': &'? Option<i32> 301..303 'ps': &'? Option<i32>
305..307 '{}': () 305..307 '{}': ()
316..317 'f': Box<dyn FnOnce(&'? Option<i32>)> 316..317 'f': Box<dyn FnOnce(&'? Option<i32>) + 'static>
316..321 'f(&s)': () 316..321 'f(&s)': ()
318..320 '&s': &'? Option<i32> 318..320 '&s': &'? Option<i32>
319..320 's': Option<i32> 319..320 's': Option<i32>
@ -4252,9 +4252,9 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
"#, "#,
expect![[r#" expect![[r#"
90..94 'self': &'? Self 90..94 'self': &'? Self
127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32>) 127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
164..195 '{ ...f(); }': () 164..195 '{ ...f(); }': ()
170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32>) 170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + 'static)
170..184 'v.get::<i32>()': &'? i32 170..184 'v.get::<i32>()': &'? i32
170..192 'v.get:...eref()': &'? i32 170..192 'v.get:...eref()': &'? i32
"#]], "#]],
@ -4735,7 +4735,7 @@ pub async fn foo_async<'a>() -> Box<dyn Trait + 'a> {
fn foo() { fn foo() {
foo_async(); foo_async();
//^^^^^^^^^^^impl Future<Output = Box<dyn Trait>> + ?Sized //^^^^^^^^^^^impl Future<Output = Box<dyn Trait + '?>> + ?Sized
} }
"#, "#,
) )

View File

@ -1066,7 +1066,7 @@ fn foo() {
r#" r#"
fn foo() { fn foo() {
let (mut a, b) = (0.1, "abc"); let (mut a, b) = (0.1, "abc");
fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) { fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) {
*a = 1.2; *a = 1.2;
let c = *b; let c = *b;
} }
@ -1098,7 +1098,7 @@ fn foo() {
r#" r#"
fn foo() { fn foo() {
let (mut a, b) = (0.1, "abc"); let (mut a, b) = (0.1, "abc");
fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) { fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) {
let _: &mut bool = p2; let _: &mut bool = p2;
*a = 1.2; *a = 1.2;
let c = *b; let c = *b;
@ -1136,7 +1136,7 @@ fn foo() {
r#" r#"
fn foo() { fn foo() {
let (mut a, b) = (0.1, "abc"); let (mut a, b) = (0.1, "abc");
fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&str) { fn closure(p1: i32, p2: &mut bool, a: &mut f64, b: &&'static str) {
let _: &mut bool = p2; let _: &mut bool = p2;
*a = 1.2; *a = 1.2;
let c = *b; let c = *b;

View File

@ -5033,7 +5033,7 @@ fn main() {
fun_name(bar); fun_name(bar);
} }
fn $0fun_name(bar: &str) { fn $0fun_name(bar: &'static str) {
m!(bar); m!(bar);
} }
"#, "#,

View File

@ -631,7 +631,7 @@ fn main() {
"#, "#,
r#" r#"
fn main() { fn main() {
const $0HELLO: &str = "hello"; const $0HELLO: &'static str = "hello";
} }
"#, "#,
"Extract into constant", "Extract into constant",
@ -726,7 +726,7 @@ fn main() {
"#, "#,
r#" r#"
fn main() { fn main() {
static $0HELLO: &str = "hello"; static $0HELLO: &'static str = "hello";
} }
"#, "#,
"Extract into static", "Extract into static",
@ -2528,13 +2528,13 @@ fn foo() {
check_assist_by_label( check_assist_by_label(
extract_variable, extract_variable,
r#" r#"
struct Entry(&str); struct Entry<'a>(&'a str);
fn foo() { fn foo() {
let entry = Entry($0"Hello"$0); let entry = Entry($0"Hello"$0);
} }
"#, "#,
r#" r#"
struct Entry(&str); struct Entry<'a>(&'a str);
fn foo() { fn foo() {
let $0hello = "Hello"; let $0hello = "Hello";
let entry = Entry(hello); let entry = Entry(hello);
@ -2546,13 +2546,13 @@ fn foo() {
check_assist_by_label( check_assist_by_label(
extract_variable, extract_variable,
r#" r#"
struct Entry(&str); struct Entry<'a>(&'a str);
fn foo() { fn foo() {
let entry = Entry($0"Hello"$0); let entry = Entry($0"Hello"$0);
} }
"#, "#,
r#" r#"
struct Entry(&str); struct Entry<'a>(&'a str);
fn foo() { fn foo() {
const $0HELLO: &str = "Hello"; const $0HELLO: &str = "Hello";
let entry = Entry(HELLO); let entry = Entry(HELLO);
@ -2564,13 +2564,13 @@ fn foo() {
check_assist_by_label( check_assist_by_label(
extract_variable, extract_variable,
r#" r#"
struct Entry(&str); struct Entry<'a>(&'a str);
fn foo() { fn foo() {
let entry = Entry($0"Hello"$0); let entry = Entry($0"Hello"$0);
} }
"#, "#,
r#" r#"
struct Entry(&str); struct Entry<'a>(&'a str);
fn foo() { fn foo() {
static $0HELLO: &str = "Hello"; static $0HELLO: &str = "Hello";
let entry = Entry(HELLO); let entry = Entry(HELLO);
@ -2587,13 +2587,13 @@ fn foo() {
check_assist_by_label( check_assist_by_label(
extract_variable, extract_variable,
r#" r#"
struct Entry { message: &str } struct Entry<'a> { message: &'a str }
fn foo() { fn foo() {
let entry = Entry { message: $0"Hello"$0 }; let entry = Entry { message: $0"Hello"$0 };
} }
"#, "#,
r#" r#"
struct Entry { message: &str } struct Entry<'a> { message: &'a str }
fn foo() { fn foo() {
let $0message = "Hello"; let $0message = "Hello";
let entry = Entry { message }; let entry = Entry { message };
@ -2605,13 +2605,13 @@ fn foo() {
check_assist_by_label( check_assist_by_label(
extract_variable, extract_variable,
r#" r#"
struct Entry { message: &str } struct Entry<'a> { message: &'a str }
fn foo() { fn foo() {
let entry = Entry { message: $0"Hello"$0 }; let entry = Entry { message: $0"Hello"$0 };
} }
"#, "#,
r#" r#"
struct Entry { message: &str } struct Entry<'a> { message: &'a str }
fn foo() { fn foo() {
const $0HELLO: &str = "Hello"; const $0HELLO: &str = "Hello";
let entry = Entry { message: HELLO }; let entry = Entry { message: HELLO };
@ -2623,13 +2623,13 @@ fn foo() {
check_assist_by_label( check_assist_by_label(
extract_variable, extract_variable,
r#" r#"
struct Entry { message: &str } struct Entry<'a> { message: &'a str }
fn foo() { fn foo() {
let entry = Entry { message: $0"Hello"$0 }; let entry = Entry { message: $0"Hello"$0 };
} }
"#, "#,
r#" r#"
struct Entry { message: &str } struct Entry<'a> { message: &'a str }
fn foo() { fn foo() {
static $0HELLO: &str = "Hello"; static $0HELLO: &str = "Hello";
let entry = Entry { message: HELLO }; let entry = Entry { message: HELLO };

View File

@ -47,7 +47,7 @@ use crate::{
// bar("", baz()); // bar("", baz());
// } // }
// //
// fn bar(arg: &str, baz: Baz) ${0:-> _} { // fn bar(arg: &'static str, baz: Baz) ${0:-> _} {
// todo!() // todo!()
// } // }
// //
@ -1518,7 +1518,7 @@ fn foo() {
bar("bar") bar("bar")
} }
fn bar(arg: &str) { fn bar(arg: &'static str) {
${0:todo!()} ${0:todo!()}
} }
"#, "#,
@ -2135,7 +2135,7 @@ fn foo() {
bar(baz(), baz(), "foo", "bar") bar(baz(), baz(), "foo", "bar")
} }
fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) { fn bar(baz_1: Baz, baz_2: Baz, arg_1: &'static str, arg_2: &'static str) {
${0:todo!()} ${0:todo!()}
} }
"#, "#,
@ -3103,7 +3103,7 @@ pub struct Foo {
field_2: String, field_2: String,
} }
impl Foo { impl Foo {
fn new(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) -> Self { fn new(baz_1: Baz, baz_2: Baz, arg_1: &'static str, arg_2: &'static str) -> Self {
${0:Self { field_1: todo!(), field_2: todo!() }} ${0:Self { field_1: todo!(), field_2: todo!() }}
} }
} }

View File

@ -1737,7 +1737,7 @@ fn foo() {
bar("", baz()); bar("", baz());
} }
fn bar(arg: &str, baz: Baz) ${0:-> _} { fn bar(arg: &'static str, baz: Baz) ${0:-> _} {
todo!() todo!()
} }

View File

@ -1517,7 +1517,7 @@ fn main() {
en Enum Enum en Enum Enum
fn function() fn() fn function() fn()
fn main() fn() fn main() fn()
lc variable &str lc variable &'static str
ma helper!() macro_rules! helper ma helper!() macro_rules! helper
ma m!() macro_rules! m ma m!() macro_rules! m
ma makro!() macro_rules! makro ma makro!() macro_rules! makro

View File

@ -1358,7 +1358,7 @@ pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone, { 0u8 }
fn main() { fo$0 } fn main() { fo$0 }
"#, "#,
CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function),
expect!("fn(&mut T) -> u8"), expect!("fn(&'x mut T) -> u8"),
expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"), expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"),
); );
@ -1391,7 +1391,7 @@ fn main() {
} }
"#, "#,
CompletionItemKind::SymbolKind(SymbolKind::Method), CompletionItemKind::SymbolKind(SymbolKind::Method),
expect!("const fn(&'foo mut self, &Foo) -> !"), expect!("const fn(&'foo mut self, &'foo Foo) -> !"),
expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"), expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"),
); );
} }

View File

@ -432,7 +432,7 @@ impl Tr<$0
en Enum Enum en Enum Enum
ma makro!() macro_rules! makro ma makro!() macro_rules! makro
md module md module
sp Self dyn Tr<{unknown}> sp Self dyn Tr<{unknown}> + 'static
st Record Record st Record Record
st S S st S S
st Tuple Tuple st Tuple Tuple

View File

@ -31,7 +31,7 @@ fn foo() {
x(); x();
// ^^^ error: expected function, found i32 // ^^^ error: expected function, found i32
""(); ""();
// ^^^^ error: expected function, found &str // ^^^^ error: expected function, found &'static str
foo(); foo();
} }
"#, "#,

View File

@ -166,7 +166,7 @@ fn main() {
let _ = ptr as bool; let _ = ptr as bool;
//^^^^^^^^^^^ error: cannot cast `*const ()` as `bool` //^^^^^^^^^^^ error: cannot cast `*const ()` as `bool`
let v = "hello" as bool; let v = "hello" as bool;
//^^^^^^^^^^^^^^^ error: casting `&str` as `bool` is invalid: needs casting through a raw pointer first //^^^^^^^^^^^^^^^ error: casting `&'static str` as `bool` is invalid: needs casting through a raw pointer first
} }
"#, "#,
); );
@ -956,7 +956,7 @@ fn main() {
fn main() { fn main() {
let pointer: usize = &1_i32 as *const i32 as usize; let pointer: usize = &1_i32 as *const i32 as usize;
let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 };
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `*const i32` as `&i32` //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: non-primitive cast: `*const i32` as `&'static i32`
} }
"#, "#,
); );
@ -992,7 +992,7 @@ impl Deref for Foo {
fn main() { fn main() {
let _ = "foo" as bool; let _ = "foo" as bool;
//^^^^^^^^^^^^^ error: casting `&str` as `bool` is invalid: needs casting through a raw pointer first //^^^^^^^^^^^^^ error: casting `&'static str` as `bool` is invalid: needs casting through a raw pointer first
let _ = Foo as bool; let _ = Foo as bool;
//^^^^^^^^^^^ error: non-primitive cast: `Foo` as `bool` //^^^^^^^^^^^ error: non-primitive cast: `Foo` as `bool`

View File

@ -306,10 +306,9 @@ fn str_ref_to_owned(
acc: &mut Vec<Assist>, acc: &mut Vec<Assist>,
) -> Option<()> { ) -> Option<()> {
let expected = d.expected.display(ctx.sema.db, ctx.display_target); let expected = d.expected.display(ctx.sema.db, ctx.display_target);
let actual = d.actual.display(ctx.sema.db, ctx.display_target);
// FIXME do this properly // FIXME do this properly
if expected.to_string() != "String" || actual.to_string() != "&str" { let is_applicable = d.actual.strip_reference().is_str() && expected.to_string() == "String";
if !is_applicable {
return None; return None;
} }
@ -1176,7 +1175,7 @@ trait B {}
fn test(a: &dyn A) -> &dyn B { fn test(a: &dyn A) -> &dyn B {
a a
//^ error: expected &dyn B, found &dyn A //^ error: expected &(dyn B + 'static), found &(dyn A + 'static)
} }
"#, "#,
); );

View File

@ -151,7 +151,7 @@ fn main() {
fn main() { fn main() {
let mut x = t(); let mut x = t();
x = _; x = _;
//^ 💡 error: invalid `_` expression, expected type `&str` //^ 💡 error: invalid `_` expression, expected type `&'static str`
x = ""; x = "";
} }
fn t<T>() -> T { loop {} } fn t<T>() -> T { loop {} }

View File

@ -269,7 +269,7 @@ impl<T, U> A<T, U> {
} }
fn main() { fn main() {
let a = A {a: 0, b: ""}; let a = A {a: 0, b: ""};
A::<i32, &str>::foo(); A::<i32, &'static str>::foo();
} }
"#, "#,
); );

View File

@ -7086,7 +7086,7 @@ fn foo() {
"#, "#,
expect![[r#" expect![[r#"
```rust ```rust
&str &'static str
```"#]], ```"#]],
); );
} }
@ -8228,7 +8228,7 @@ format_args!("{aaaaa$0}");
*aaaaa* *aaaaa*
```rust ```rust
let aaaaa: &str let aaaaa: &'static str
``` ```
"#]], "#]],
); );
@ -8248,7 +8248,7 @@ format_args!("{$0aaaaa}");
*aaaaa* *aaaaa*
```rust ```rust
let aaaaa: &str let aaaaa: &'static str
``` ```
"#]], "#]],
); );
@ -8268,7 +8268,7 @@ format_args!(r"{$0aaaaa}");
*aaaaa* *aaaaa*
```rust ```rust
let aaaaa: &str let aaaaa: &'static str
``` ```
"#]], "#]],
); );
@ -8293,7 +8293,7 @@ foo!(r"{$0aaaaa}");
*aaaaa* *aaaaa*
```rust ```rust
let aaaaa: &str let aaaaa: &'static str
``` ```
"#]], "#]],
); );
@ -8337,7 +8337,7 @@ fn main() {
expect![[r#" expect![[r#"
*"🦀\u{1f980}\\\x41"* *"🦀\u{1f980}\\\x41"*
```rust ```rust
&str &'static str
``` ```
___ ___
@ -8353,7 +8353,7 @@ fn main() {
expect![[r#" expect![[r#"
*r"🦀\u{1f980}\\\x41"* *r"🦀\u{1f980}\\\x41"*
```rust ```rust
&str &'static str
``` ```
___ ___
@ -8375,7 +8375,7 @@ fsdghs";
fsdghs"* fsdghs"*
```rust ```rust
&str &'static str
``` ```
___ ___
@ -8395,7 +8395,7 @@ fn main() {
expect![[r#" expect![[r#"
*c"🦀\u{1f980}\\\x41"* *c"🦀\u{1f980}\\\x41"*
```rust ```rust
&{unknown} &'static {unknown}
``` ```
___ ___
@ -8414,7 +8414,7 @@ fn main() {
expect![[r#" expect![[r#"
*r"`[^`]*`"* *r"`[^`]*`"*
```rust ```rust
&str &'static str
``` ```
___ ___
@ -8429,7 +8429,7 @@ fn main() {
expect![[r#" expect![[r#"
*r"`"* *r"`"*
```rust ```rust
&str &'static str
``` ```
___ ___
@ -8444,7 +8444,7 @@ fn main() {
expect![[r#" expect![[r#"
*r" "* *r" "*
```rust ```rust
&str &'static str
``` ```
___ ___
@ -8460,7 +8460,7 @@ fn main() {
expect![[r#" expect![[r#"
*r" Hello World "* *r" Hello World "*
```rust ```rust
&str &'static str
``` ```
___ ___
@ -8480,7 +8480,7 @@ fn main() {
expect![[r#" expect![[r#"
*b"\xF0\x9F\xA6\x80\\"* *b"\xF0\x9F\xA6\x80\\"*
```rust ```rust
&[u8; 5] &'static [u8; 5]
``` ```
___ ___
@ -8496,7 +8496,7 @@ fn main() {
expect![[r#" expect![[r#"
*br"\xF0\x9F\xA6\x80\\"* *br"\xF0\x9F\xA6\x80\\"*
```rust ```rust
&[u8; 18] &'static [u8; 18]
``` ```
___ ___
@ -9070,7 +9070,7 @@ struct Pedro$0<'a> {
```rust ```rust
struct Pedro<'a> { struct Pedro<'a> {
hola: &str, hola: &'a str,
} }
``` ```
@ -9937,7 +9937,7 @@ fn baz() {
--- ---
`U` = `i32`, `T` = `&str` `U` = `i32`, `T` = `&'static str`
"#]], "#]],
); );
} }
@ -10030,7 +10030,7 @@ fn bar() {
--- ---
`T` = `i8`, `U` = `&str` `T` = `i8`, `U` = `&'static str`
"#]], "#]],
); );
} }

View File

@ -380,9 +380,9 @@ fn main() {
let foo = foo3(); let foo = foo3();
// ^^^ impl Fn(f64, f64) -> u32 // ^^^ impl Fn(f64, f64) -> u32
let foo = foo4(); let foo = foo4();
// ^^^ &dyn Fn(f64, f64) -> u32 // ^^^ &'static (dyn Fn(f64, f64) -> u32 + 'static)
let foo = foo5(); let foo = foo5();
// ^^^ &dyn Fn(&dyn Fn(f64, f64) -> u32, f64) -> u32 // ^^^ &'static (dyn Fn(&(dyn Fn(f64, f64) -> u32 + 'static), f64) -> u32 + 'static)
let foo = foo6(); let foo = foo6();
// ^^^ impl Fn(f64, f64) -> u32 // ^^^ impl Fn(f64, f64) -> u32
let foo = foo7(); let foo = foo7();
@ -413,7 +413,7 @@ fn main() {
let foo = foo3(); let foo = foo3();
// ^^^ impl Fn(f64, f64) -> u32 // ^^^ impl Fn(f64, f64) -> u32
let foo = foo4(); let foo = foo4();
// ^^^ &dyn Fn(f64, f64) -> u32 // ^^^ &'static (dyn Fn(f64, f64) -> u32 + 'static)
let foo = foo5(); let foo = foo5();
let foo = foo6(); let foo = foo6();
let foo = foo7(); let foo = foo7();
@ -528,7 +528,7 @@ fn main() {
//^^^^ i32 //^^^^ i32
let _ = 22; let _ = 22;
let test = "test"; let test = "test";
//^^^^ &str //^^^^ &'static str
let test = InnerStruct {}; let test = InnerStruct {};
//^^^^ InnerStruct //^^^^ InnerStruct
@ -618,12 +618,12 @@ impl<T> Iterator for IntoIter<T> {
fn main() { fn main() {
let mut data = Vec::new(); let mut data = Vec::new();
//^^^^ Vec<&str> //^^^^ Vec<&'static str>
data.push("foo"); data.push("foo");
for i in data { for i in data {
//^ &str //^ &'static str
let z = i; let z = i;
//^ &str //^ &'static str
} }
} }
"#, "#,
@ -651,8 +651,8 @@ fn main() {
//^^ Vec<Box<&(dyn Display + Sync)>> //^^ Vec<Box<&(dyn Display + Sync)>>
let _v = { Vec::<Box<*const (dyn Display + Sync)>>::new() }; let _v = { Vec::<Box<*const (dyn Display + Sync)>>::new() };
//^^ Vec<Box<*const (dyn Display + Sync)>> //^^ Vec<Box<*const (dyn Display + Sync)>>
let _v = { Vec::<Box<dyn Display + Sync>>::new() }; let _v = { Vec::<Box<dyn Display + Sync + 'static>>::new() };
//^^ Vec<Box<dyn Display + Sync>> //^^ Vec<Box<dyn Display + Sync + 'static>>
} }
"#, "#,
); );
@ -1017,7 +1017,7 @@ fn test<T>(t: T) {
"#, "#,
expect![[r#" expect![[r#"
fn test<T>(t: T) { fn test<T>(t: T) {
let f = |a: i32, b: &str, c: T| {}; let f = |a: i32, b: &'static str, c: T| {};
let result: () = f(42, "", t); let result: () = f(42, "", t);
} }
"#]], "#]],

View File

@ -194,7 +194,7 @@ impl Tr for () {
//^ impl Tr for () //^ impl Tr for ()
impl dyn Tr { impl dyn Tr {
} }
//^ impl dyn Tr //^ impl dyn Tr + 'static
static S0: () = 0; static S0: () = 0;
static S1: () = {}; static S1: () = {};

View File

@ -1064,7 +1064,7 @@ fn main() {
), ),
work_done_progress_params: Default::default(), work_done_progress_params: Default::default(),
}); });
assert!(res.to_string().contains("&str")); assert!(res.to_string().contains("&'static str"));
let res = server.send_request::<HoverRequest>(HoverParams { let res = server.send_request::<HoverRequest>(HoverParams {
text_document_position_params: TextDocumentPositionParams::new( text_document_position_params: TextDocumentPositionParams::new(
@ -1073,7 +1073,7 @@ fn main() {
), ),
work_done_progress_params: Default::default(), work_done_progress_params: Default::default(),
}); });
assert!(res.to_string().contains("&str")); assert!(res.to_string().contains("&'static str"));
server.request::<GotoTypeDefinition>( server.request::<GotoTypeDefinition>(
GotoDefinitionParams { GotoDefinitionParams {