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

@ -429,18 +429,18 @@ trait Tr<T> {
impl Tr<$0 impl Tr<$0
"#, "#,
expect![[r#" expect![[r#"
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
st Unit Unit st Unit Unit
tt Tr tt Tr
tt Trait tt Trait
un Union Union un Union Union
bt u32 u32 bt u32 u32
kw crate:: kw crate::
kw self:: kw self::
"#]], "#]],

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

@ -7085,9 +7085,9 @@ 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,12 +8460,12 @@ fn main() {
expect![[r#" expect![[r#"
*r" Hello World "* *r" Hello World "*
```rust ```rust
&str &'static str
``` ```
___ ___
value of literal: ` Hello World ` value of literal: ` Hello World `
"#]], "#]],
) )
} }
@ -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 {