Wrap dyn type with parentheses in suggestion
This commit is contained in:
parent
453ceafce3
commit
31e581ec12
10 changed files with 286 additions and 62 deletions
|
@ -644,13 +644,49 @@ impl<'hir> Generics<'hir> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bounds_span_for_suggestions(&self, param_def_id: LocalDefId) -> Option<Span> {
|
/// Returns a suggestable empty span right after the "final" bound of the generic parameter.
|
||||||
|
///
|
||||||
|
/// If that bound needs to be wrapped in parentheses to avoid ambiguity with
|
||||||
|
/// subsequent bounds, it also returns an empty span for an open parenthesis
|
||||||
|
/// as the second component.
|
||||||
|
///
|
||||||
|
/// E.g., adding `+ 'static` after `Fn() -> dyn Future<Output = ()>` or
|
||||||
|
/// `Fn() -> &'static dyn Debug` requires parentheses:
|
||||||
|
/// `Fn() -> (dyn Future<Output = ()>) + 'static` and
|
||||||
|
/// `Fn() -> &'static (dyn Debug) + 'static`, respectively.
|
||||||
|
pub fn bounds_span_for_suggestions(
|
||||||
|
&self,
|
||||||
|
param_def_id: LocalDefId,
|
||||||
|
) -> Option<(Span, Option<Span>)> {
|
||||||
self.bounds_for_param(param_def_id).flat_map(|bp| bp.bounds.iter().rev()).find_map(
|
self.bounds_for_param(param_def_id).flat_map(|bp| bp.bounds.iter().rev()).find_map(
|
||||||
|bound| {
|
|bound| {
|
||||||
|
let span_for_parentheses = if let Some(trait_ref) = bound.trait_ref()
|
||||||
|
&& let [.., segment] = trait_ref.path.segments
|
||||||
|
&& segment.args().parenthesized == GenericArgsParentheses::ParenSugar
|
||||||
|
&& let [binding] = segment.args().bindings
|
||||||
|
&& let TypeBindingKind::Equality { term: Term::Ty(ret_ty) } = binding.kind
|
||||||
|
&& let ret_ty = ret_ty.peel_refs()
|
||||||
|
&& let TyKind::TraitObject(
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar,
|
||||||
|
) = ret_ty.kind
|
||||||
|
&& ret_ty.span.can_be_used_for_suggestions()
|
||||||
|
{
|
||||||
|
Some(ret_ty.span)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
span_for_parentheses.map_or_else(
|
||||||
|
|| {
|
||||||
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
|
// We include bounds that come from a `#[derive(_)]` but point at the user's code,
|
||||||
// as we use this method to get a span appropriate for suggestions.
|
// as we use this method to get a span appropriate for suggestions.
|
||||||
let bs = bound.span();
|
let bs = bound.span();
|
||||||
bs.can_be_used_for_suggestions().then(|| bs.shrink_to_hi())
|
bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None))
|
||||||
|
},
|
||||||
|
|span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3291,14 +3291,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
param.name.ident(),
|
param.name.ident(),
|
||||||
));
|
));
|
||||||
let bounds_span = hir_generics.bounds_span_for_suggestions(def_id);
|
let bounds_span = hir_generics.bounds_span_for_suggestions(def_id);
|
||||||
if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
|
if rcvr_ty.is_ref()
|
||||||
|
&& param.is_impl_trait()
|
||||||
|
&& let Some((bounds_span, _)) = bounds_span
|
||||||
|
{
|
||||||
err.multipart_suggestions(
|
err.multipart_suggestions(
|
||||||
msg,
|
msg,
|
||||||
candidates.iter().map(|t| {
|
candidates.iter().map(|t| {
|
||||||
vec![
|
vec![
|
||||||
(param.span.shrink_to_lo(), "(".to_string()),
|
(param.span.shrink_to_lo(), "(".to_string()),
|
||||||
(
|
(
|
||||||
bounds_span.unwrap(),
|
bounds_span,
|
||||||
format!(" + {})", self.tcx.def_path_str(t.def_id)),
|
format!(" + {})", self.tcx.def_path_str(t.def_id)),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -3308,32 +3311,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (sp, introducer) = if let Some(span) = bounds_span {
|
let (sp, introducer, open_paren_sp) =
|
||||||
(span, Introducer::Plus)
|
if let Some((span, open_paren_sp)) = bounds_span {
|
||||||
|
(span, Introducer::Plus, open_paren_sp)
|
||||||
} else if let Some(colon_span) = param.colon_span {
|
} else if let Some(colon_span) = param.colon_span {
|
||||||
(colon_span.shrink_to_hi(), Introducer::Nothing)
|
(colon_span.shrink_to_hi(), Introducer::Nothing, None)
|
||||||
} else if param.is_impl_trait() {
|
} else if param.is_impl_trait() {
|
||||||
(param.span.shrink_to_hi(), Introducer::Plus)
|
(param.span.shrink_to_hi(), Introducer::Plus, None)
|
||||||
} else {
|
} else {
|
||||||
(param.span.shrink_to_hi(), Introducer::Colon)
|
(param.span.shrink_to_hi(), Introducer::Colon, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
err.span_suggestions(
|
let all_suggs = candidates.iter().map(|cand| {
|
||||||
sp,
|
let suggestion = format!(
|
||||||
msg,
|
|
||||||
candidates.iter().map(|t| {
|
|
||||||
format!(
|
|
||||||
"{} {}",
|
"{} {}",
|
||||||
match introducer {
|
match introducer {
|
||||||
Introducer::Plus => " +",
|
Introducer::Plus => " +",
|
||||||
Introducer::Colon => ":",
|
Introducer::Colon => ":",
|
||||||
Introducer::Nothing => "",
|
Introducer::Nothing => "",
|
||||||
},
|
},
|
||||||
self.tcx.def_path_str(t.def_id)
|
self.tcx.def_path_str(cand.def_id)
|
||||||
)
|
);
|
||||||
}),
|
|
||||||
|
let mut suggs = vec![];
|
||||||
|
|
||||||
|
if let Some(open_paren_sp) = open_paren_sp {
|
||||||
|
suggs.push((open_paren_sp, "(".to_string()));
|
||||||
|
suggs.push((sp, format!("){suggestion}")));
|
||||||
|
} else {
|
||||||
|
suggs.push((sp, suggestion));
|
||||||
|
}
|
||||||
|
|
||||||
|
suggs
|
||||||
|
});
|
||||||
|
|
||||||
|
err.multipart_suggestions(
|
||||||
|
msg,
|
||||||
|
all_suggs,
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Node::Item(hir::Item {
|
Node::Item(hir::Item {
|
||||||
|
|
|
@ -2369,7 +2369,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
generic_param_scope = self.tcx.local_parent(generic_param_scope);
|
generic_param_scope = self.tcx.local_parent(generic_param_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
// type_param_sugg_span is (span, has_bounds)
|
// type_param_sugg_span is (span, has_bounds, needs_parentheses)
|
||||||
let (type_scope, type_param_sugg_span) = match bound_kind {
|
let (type_scope, type_param_sugg_span) = match bound_kind {
|
||||||
GenericKind::Param(ref param) => {
|
GenericKind::Param(ref param) => {
|
||||||
let generics = self.tcx.generics_of(generic_param_scope);
|
let generics = self.tcx.generics_of(generic_param_scope);
|
||||||
|
@ -2380,10 +2380,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
// instead we suggest `T: 'a + 'b` in that case.
|
// instead we suggest `T: 'a + 'b` in that case.
|
||||||
let hir_generics = self.tcx.hir().get_generics(scope).unwrap();
|
let hir_generics = self.tcx.hir().get_generics(scope).unwrap();
|
||||||
let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
|
let sugg_span = match hir_generics.bounds_span_for_suggestions(def_id) {
|
||||||
Some(span) => Some((span, true)),
|
Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
|
||||||
// If `param` corresponds to `Self`, no usable suggestion span.
|
// If `param` corresponds to `Self`, no usable suggestion span.
|
||||||
None if generics.has_self && param.index == 0 => None,
|
None if generics.has_self && param.index == 0 => None,
|
||||||
None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false)),
|
None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false, None)),
|
||||||
};
|
};
|
||||||
(scope, sugg_span)
|
(scope, sugg_span)
|
||||||
}
|
}
|
||||||
|
@ -2406,12 +2406,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
let mut suggs = vec![];
|
let mut suggs = vec![];
|
||||||
let lt_name = self.suggest_name_region(sub, &mut suggs);
|
let lt_name = self.suggest_name_region(sub, &mut suggs);
|
||||||
|
|
||||||
if let Some((sp, has_lifetimes)) = type_param_sugg_span
|
if let Some((sp, has_lifetimes, open_paren_sp)) = type_param_sugg_span
|
||||||
&& suggestion_scope == type_scope
|
&& suggestion_scope == type_scope
|
||||||
{
|
{
|
||||||
let suggestion =
|
let suggestion =
|
||||||
if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
|
if has_lifetimes { format!(" + {lt_name}") } else { format!(": {lt_name}") };
|
||||||
|
|
||||||
|
if let Some(open_paren_sp) = open_paren_sp {
|
||||||
|
suggs.push((open_paren_sp, "(".to_string()));
|
||||||
|
suggs.push((sp, format!("){suggestion}")));
|
||||||
|
} else {
|
||||||
suggs.push((sp, suggestion))
|
suggs.push((sp, suggestion))
|
||||||
|
}
|
||||||
} else if let GenericKind::Alias(ref p) = bound_kind
|
} else if let GenericKind::Alias(ref p) = bound_kind
|
||||||
&& let ty::Projection = p.kind(self.tcx)
|
&& let ty::Projection = p.kind(self.tcx)
|
||||||
&& let DefKind::AssocTy = self.tcx.def_kind(p.def_id)
|
&& let DefKind::AssocTy = self.tcx.def_kind(p.def_id)
|
||||||
|
|
|
@ -279,10 +279,8 @@ pub fn suggest_constraining_type_params<'a>(
|
||||||
constraint.sort();
|
constraint.sort();
|
||||||
constraint.dedup();
|
constraint.dedup();
|
||||||
let constraint = constraint.join(" + ");
|
let constraint = constraint.join(" + ");
|
||||||
let mut suggest_restrict = |span, bound_list_non_empty| {
|
let mut suggest_restrict = |span, bound_list_non_empty, open_paren_sp| {
|
||||||
suggestions.push((
|
let suggestion = if span_to_replace.is_some() {
|
||||||
span,
|
|
||||||
if span_to_replace.is_some() {
|
|
||||||
constraint.clone()
|
constraint.clone()
|
||||||
} else if constraint.starts_with('<') {
|
} else if constraint.starts_with('<') {
|
||||||
constraint.to_string()
|
constraint.to_string()
|
||||||
|
@ -290,13 +288,20 @@ pub fn suggest_constraining_type_params<'a>(
|
||||||
format!(" + {constraint}")
|
format!(" + {constraint}")
|
||||||
} else {
|
} else {
|
||||||
format!(" {constraint}")
|
format!(" {constraint}")
|
||||||
},
|
};
|
||||||
SuggestChangingConstraintsMessage::RestrictBoundFurther,
|
|
||||||
))
|
use SuggestChangingConstraintsMessage::RestrictBoundFurther;
|
||||||
|
|
||||||
|
if let Some(open_paren_sp) = open_paren_sp {
|
||||||
|
suggestions.push((open_paren_sp, "(".to_string(), RestrictBoundFurther));
|
||||||
|
suggestions.push((span, format!("){suggestion}"), RestrictBoundFurther));
|
||||||
|
} else {
|
||||||
|
suggestions.push((span, suggestion, RestrictBoundFurther));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(span) = span_to_replace {
|
if let Some(span) = span_to_replace {
|
||||||
suggest_restrict(span, true);
|
suggest_restrict(span, true, None);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,8 +332,8 @@ pub fn suggest_constraining_type_params<'a>(
|
||||||
// --
|
// --
|
||||||
// |
|
// |
|
||||||
// replace with: `T: Bar +`
|
// replace with: `T: Bar +`
|
||||||
if let Some(span) = generics.bounds_span_for_suggestions(param.def_id) {
|
if let Some((span, open_paren_sp)) = generics.bounds_span_for_suggestions(param.def_id) {
|
||||||
suggest_restrict(span, true);
|
suggest_restrict(span, true, open_paren_sp);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2938,17 +2938,28 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`.
|
// Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`.
|
||||||
let (span, separator) = if let Some(s) = generics.bounds_span_for_suggestions(param.def_id)
|
let (span, separator, open_paren_sp) =
|
||||||
{
|
if let Some((s, open_paren_sp)) = generics.bounds_span_for_suggestions(param.def_id) {
|
||||||
(s, " +")
|
(s, " +", open_paren_sp)
|
||||||
} else {
|
} else {
|
||||||
(param.name.ident().span.shrink_to_hi(), ":")
|
(param.name.ident().span.shrink_to_hi(), ":", None)
|
||||||
};
|
};
|
||||||
err.span_suggestion_verbose(
|
|
||||||
span,
|
let mut suggs = vec![];
|
||||||
|
let suggestion = format!("{separator} ?Sized");
|
||||||
|
|
||||||
|
if let Some(open_paren_sp) = open_paren_sp {
|
||||||
|
suggs.push((open_paren_sp, "(".to_string()));
|
||||||
|
suggs.push((span, format!("){suggestion}")));
|
||||||
|
} else {
|
||||||
|
suggs.push((span, suggestion));
|
||||||
|
}
|
||||||
|
|
||||||
|
err.multipart_suggestion_verbose(
|
||||||
"consider relaxing the implicit `Sized` restriction",
|
"consider relaxing the implicit `Sized` restriction",
|
||||||
format!("{separator} ?Sized"),
|
suggs,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,18 @@ impl Foo for S {}
|
||||||
impl Bar for S {}
|
impl Bar for S {}
|
||||||
|
|
||||||
fn test(foo: impl Foo + Bar) {
|
fn test(foo: impl Foo + Bar) {
|
||||||
foo.hello(); //~ ERROR E0599
|
foo.hello(); //~ ERROR no method named `hello` found
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
fn method(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for fn() {}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn test2(f: impl Fn() -> (dyn std::fmt::Debug) + Trait) {
|
||||||
|
f.method(); //~ ERROR no method named `method` found
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -12,7 +12,18 @@ impl Foo for S {}
|
||||||
impl Bar for S {}
|
impl Bar for S {}
|
||||||
|
|
||||||
fn test(foo: impl Foo) {
|
fn test(foo: impl Foo) {
|
||||||
foo.hello(); //~ ERROR E0599
|
foo.hello(); //~ ERROR no method named `hello` found
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
fn method(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for fn() {}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn test2(f: impl Fn() -> dyn std::fmt::Debug) {
|
||||||
|
f.method(); //~ ERROR no method named `method` found
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -12,6 +12,20 @@ help: the following trait defines an item `hello`, perhaps you need to restrict
|
||||||
LL | fn test(foo: impl Foo + Bar) {
|
LL | fn test(foo: impl Foo + Bar) {
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0599]: no method named `method` found for type parameter `impl Fn() -> dyn std::fmt::Debug` in the current scope
|
||||||
|
--> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:26:7
|
||||||
|
|
|
||||||
|
LL | fn test2(f: impl Fn() -> dyn std::fmt::Debug) {
|
||||||
|
| -------------------------------- method `method` not found for this type parameter
|
||||||
|
LL | f.method();
|
||||||
|
| ^^^^^^ method not found in `impl Fn() -> dyn std::fmt::Debug`
|
||||||
|
|
|
||||||
|
= help: items from traits can only be used if the type parameter is bounded by the trait
|
||||||
|
help: the following trait defines an item `method`, perhaps you need to restrict type parameter `impl Fn() -> dyn std::fmt::Debug` with it:
|
||||||
|
|
|
||||||
|
LL | fn test2(f: impl Fn() -> (dyn std::fmt::Debug) + Trait) {
|
||||||
|
| + +++++++++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0599`.
|
For more information about this error, try `rustc --explain E0599`.
|
||||||
|
|
35
tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs
Normal file
35
tests/ui/suggestions/wrap-dyn-in-suggestion-issue-120223.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#![feature(dyn_star)] //~ WARNING the feature `dyn_star` is incomplete
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
|
||||||
|
pub fn dyn_func<T>(
|
||||||
|
executor: impl FnOnce(T) -> dyn Future<Output = ()>,
|
||||||
|
) -> Box<dyn FnOnce(T) -> dyn Future<Output = ()>> {
|
||||||
|
Box::new(executor) //~ ERROR may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dyn_star_func<T>(
|
||||||
|
executor: impl FnOnce(T) -> dyn* Future<Output = ()>,
|
||||||
|
) -> Box<dyn FnOnce(T) -> dyn* Future<Output = ()>> {
|
||||||
|
Box::new(executor) //~ ERROR may not live long enough
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait {
|
||||||
|
fn method(&self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for fn() {}
|
||||||
|
|
||||||
|
pub fn in_ty_param<T: Fn() -> dyn std::fmt::Debug> (t: T) {
|
||||||
|
t.method();
|
||||||
|
//~^ ERROR no method named `method` found for type parameter `T`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {
|
||||||
|
without_sized::<T>();
|
||||||
|
//~^ ERROR the size for values of type `T` cannot be known at compilation time
|
||||||
|
}
|
||||||
|
|
||||||
|
fn without_sized<T: Fn() -> &'static dyn std::fmt::Debug>() {}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,78 @@
|
||||||
|
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
|
--> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:1:12
|
||||||
|
|
|
||||||
|
LL | #![feature(dyn_star)]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||||
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
|
error[E0599]: no method named `method` found for type parameter `T` in the current scope
|
||||||
|
--> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:24:7
|
||||||
|
|
|
||||||
|
LL | pub fn in_ty_param<T: Fn() -> dyn std::fmt::Debug> (t: T) {
|
||||||
|
| - method `method` not found for this type parameter
|
||||||
|
LL | t.method();
|
||||||
|
| ^^^^^^ method not found in `T`
|
||||||
|
|
|
||||||
|
= help: items from traits can only be used if the type parameter is bounded by the trait
|
||||||
|
help: the following trait defines an item `method`, perhaps you need to restrict type parameter `T` with it:
|
||||||
|
|
|
||||||
|
LL | pub fn in_ty_param<T: Fn() -> (dyn std::fmt::Debug) + Trait> (t: T) {
|
||||||
|
| + +++++++++
|
||||||
|
|
||||||
|
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||||
|
--> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:29:21
|
||||||
|
|
|
||||||
|
LL | fn with_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {
|
||||||
|
| - this type parameter needs to be `Sized`
|
||||||
|
LL | without_sized::<T>();
|
||||||
|
| ^ doesn't have a size known at compile-time
|
||||||
|
|
|
||||||
|
note: required by an implicit `Sized` bound in `without_sized`
|
||||||
|
--> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:33:18
|
||||||
|
|
|
||||||
|
LL | fn without_sized<T: Fn() -> &'static dyn std::fmt::Debug>() {}
|
||||||
|
| ^ required by the implicit `Sized` requirement on this type parameter in `without_sized`
|
||||||
|
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||||
|
|
|
||||||
|
LL - fn with_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {
|
||||||
|
LL + fn with_sized<T: Fn() -> &'static (dyn std::fmt::Debug)>() {
|
||||||
|
|
|
||||||
|
help: consider relaxing the implicit `Sized` restriction
|
||||||
|
|
|
||||||
|
LL | fn without_sized<T: Fn() -> &'static (dyn std::fmt::Debug) + ?Sized>() {}
|
||||||
|
| + ++++++++++
|
||||||
|
|
||||||
|
error[E0310]: the parameter type `impl FnOnce(T) -> dyn Future<Output = ()>` may not live long enough
|
||||||
|
--> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:8:5
|
||||||
|
|
|
||||||
|
LL | Box::new(executor)
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| the parameter type `impl FnOnce(T) -> dyn Future<Output = ()>` must be valid for the static lifetime...
|
||||||
|
| ...so that the type `impl FnOnce(T) -> dyn Future<Output = ()>` will meet its required lifetime bounds
|
||||||
|
|
|
||||||
|
help: consider adding an explicit lifetime bound
|
||||||
|
|
|
||||||
|
LL | executor: impl FnOnce(T) -> (dyn Future<Output = ()>) + 'static,
|
||||||
|
| + +++++++++++
|
||||||
|
|
||||||
|
error[E0310]: the parameter type `impl FnOnce(T) -> Future<Output = ()>` may not live long enough
|
||||||
|
--> $DIR/wrap-dyn-in-suggestion-issue-120223.rs:14:5
|
||||||
|
|
|
||||||
|
LL | Box::new(executor)
|
||||||
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
| |
|
||||||
|
| the parameter type `impl FnOnce(T) -> Future<Output = ()>` must be valid for the static lifetime...
|
||||||
|
| ...so that the type `impl FnOnce(T) -> Future<Output = ()>` will meet its required lifetime bounds
|
||||||
|
|
|
||||||
|
help: consider adding an explicit lifetime bound
|
||||||
|
|
|
||||||
|
LL | executor: impl FnOnce(T) -> (dyn* Future<Output = ()>) + 'static,
|
||||||
|
| + +++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0277, E0310, E0599.
|
||||||
|
For more information about an error, try `rustc --explain E0277`.
|
Loading…
Add table
Add a link
Reference in a new issue