mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03:00
Rollup merge of #148788 - TomtheCoder2:unconstrained-parameter-fix, r=davidtwco
Unconstrained parameter fix This PR is an attempt to solve the issue described in the issue rust-lang/rust#107295
This commit is contained in:
@@ -1088,6 +1088,93 @@ pub fn span_for_bound_removal(&self, predicate_pos: usize, bound_pos: usize) ->
|
||||
bound_span.with_lo(bounds[bound_pos - 1].span().hi())
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the span representing the removal of a generic parameter at `param_index`.
|
||||
///
|
||||
/// This function identifies the correct slice of source code to delete so that the
|
||||
/// remaining generic list remains syntactically valid (handling commas and brackets).
|
||||
///
|
||||
/// ### Examples
|
||||
///
|
||||
/// 1. **With a following parameter:** (Includes the trailing comma)
|
||||
/// - Input: `<T, U>` (index 0)
|
||||
/// - Produces span for: `T, `
|
||||
///
|
||||
/// 2. **With a previous parameter:** (Includes the leading comma and bounds)
|
||||
/// - Input: `<T: Clone, U>` (index 1)
|
||||
/// - Produces span for: `, U`
|
||||
///
|
||||
/// 3. **The only parameter:** (Includes the angle brackets)
|
||||
/// - Input: `<T>` (index 0)
|
||||
/// - Produces span for: `<T>`
|
||||
///
|
||||
/// 4. **Parameter with where-clause bounds:**
|
||||
/// - Input: `fn foo<T, U>() where T: Copy` (index 0)
|
||||
/// - Produces span for: `T, ` (The where-clause remains for other logic to handle).
|
||||
pub fn span_for_param_removal(&self, param_index: usize) -> Span {
|
||||
if param_index >= self.params.len() {
|
||||
return self.span.shrink_to_hi();
|
||||
}
|
||||
|
||||
let is_param_explicit = |par: &&GenericParam<'_>| match par.kind {
|
||||
GenericParamKind::Type { .. }
|
||||
| GenericParamKind::Const { .. }
|
||||
| GenericParamKind::Lifetime { kind: LifetimeParamKind::Explicit } => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
// Find the span of the type parameter.
|
||||
if let Some(next) = self.params[param_index + 1..].iter().find(is_param_explicit) {
|
||||
self.params[param_index].span.until(next.span)
|
||||
} else if let Some(prev) = self.params[..param_index].iter().rfind(is_param_explicit) {
|
||||
let mut prev_span = prev.span;
|
||||
// Consider the span of the bounds with the previous generic parameter when there is.
|
||||
if let Some(prev_bounds_span) = self.span_for_param_bounds(prev) {
|
||||
prev_span = prev_span.to(prev_bounds_span);
|
||||
}
|
||||
|
||||
// Consider the span of the bounds with the current generic parameter when there is.
|
||||
prev_span.shrink_to_hi().to(
|
||||
if let Some(cur_bounds_span) = self.span_for_param_bounds(&self.params[param_index])
|
||||
{
|
||||
cur_bounds_span
|
||||
} else {
|
||||
self.params[param_index].span
|
||||
},
|
||||
)
|
||||
} else {
|
||||
// Remove also angle brackets <> when there is just ONE generic parameter.
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the span of the `WherePredicate` associated with the given `GenericParam`, if any.
|
||||
///
|
||||
/// This looks specifically for predicates in the `where` clause that were generated
|
||||
/// from the parameter definition (e.g., `T` in `where T: Bound`).
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// - Input: `param` representing `T`
|
||||
/// - Context: `where T: Clone + Default, U: Copy`
|
||||
/// - Returns: Span of `T: Clone + Default`
|
||||
fn span_for_param_bounds(&self, param: &GenericParam<'hir>) -> Option<Span> {
|
||||
self.predicates
|
||||
.iter()
|
||||
.find(|pred| {
|
||||
if let WherePredicateKind::BoundPredicate(WhereBoundPredicate {
|
||||
origin: PredicateOrigin::GenericParam,
|
||||
bounded_ty,
|
||||
..
|
||||
}) = pred.kind
|
||||
{
|
||||
bounded_ty.span == param.span
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.map(|pred| pred.span)
|
||||
}
|
||||
}
|
||||
|
||||
/// A single predicate in a where-clause.
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
mod precise_captures;
|
||||
pub(crate) use precise_captures::*;
|
||||
|
||||
pub(crate) mod remove_or_use_generic;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}`")]
|
||||
pub(crate) struct AmbiguousAssocItem<'a> {
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit::{self, Visitor, walk_lifetime};
|
||||
use rustc_hir::{GenericArg, HirId, LifetimeKind, Path, QPath, TyKind};
|
||||
use rustc_middle::hir::nested_filter::All;
|
||||
use rustc_middle::ty::{GenericParamDef, GenericParamDefKind, TyCtxt};
|
||||
|
||||
use crate::hir::def::Res;
|
||||
|
||||
/// Use a Visitor to find usages of the type or lifetime parameter
|
||||
struct ParamUsageVisitor<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
/// The `DefId` of the generic parameter we are looking for.
|
||||
param_def_id: DefId,
|
||||
found: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ParamUsageVisitor<'tcx> {
|
||||
type NestedFilter = All;
|
||||
|
||||
fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) -> Self::Result {
|
||||
if let Some(res_def_id) = path.res.opt_def_id() {
|
||||
if res_def_id == self.param_def_id {
|
||||
self.found = true;
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
}
|
||||
intravisit::walk_path(self, path)
|
||||
}
|
||||
|
||||
fn visit_lifetime(&mut self, lifetime: &'tcx rustc_hir::Lifetime) -> Self::Result {
|
||||
if let LifetimeKind::Param(id) = lifetime.kind {
|
||||
if let Some(local_def_id) = self.param_def_id.as_local() {
|
||||
if id == local_def_id {
|
||||
self.found = true;
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
}
|
||||
}
|
||||
walk_lifetime(self, lifetime)
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a suggestion to a diagnostic to either remove an unused generic parameter, or use it.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// - `impl<T> Struct { ... }` where `T` is unused -> suggests removing `T` or using it.
|
||||
/// - `impl<T> Struct { // T used in here }` where `T` is used in the body but not in the self type -> suggests adding `T` to the self type and struct definition.
|
||||
/// - `impl<T> Struct { ... }` where the struct has a generic parameter with a default -> suggests adding `T` to the self type.
|
||||
pub(crate) fn suggest_to_remove_or_use_generic(
|
||||
tcx: TyCtxt<'_>,
|
||||
diag: &mut Diag<'_>,
|
||||
impl_def_id: LocalDefId,
|
||||
param: &GenericParamDef,
|
||||
is_lifetime: bool,
|
||||
) {
|
||||
let node = tcx.hir_node_by_def_id(impl_def_id);
|
||||
let hir_impl = node.expect_item().expect_impl();
|
||||
|
||||
let Some((index, _)) = hir_impl
|
||||
.generics
|
||||
.params
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, par)| par.def_id.to_def_id() == param.def_id)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Get the Struct/ADT definition ID from the self type
|
||||
let struct_def_id = if let TyKind::Path(QPath::Resolved(_, path)) = hir_impl.self_ty.kind
|
||||
&& let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, def_id) = path.res
|
||||
{
|
||||
def_id
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
// Count how many generic parameters are defined in the struct definition
|
||||
let generics = tcx.generics_of(struct_def_id);
|
||||
let total_params = generics
|
||||
.own_params
|
||||
.iter()
|
||||
.filter(|p| {
|
||||
if is_lifetime {
|
||||
matches!(p.kind, GenericParamDefKind::Lifetime)
|
||||
} else {
|
||||
matches!(p.kind, GenericParamDefKind::Type { .. })
|
||||
}
|
||||
})
|
||||
.count();
|
||||
|
||||
// Count how many arguments are currently provided in the impl
|
||||
let mut provided_params = 0;
|
||||
let mut last_segment_args = None;
|
||||
|
||||
if let TyKind::Path(QPath::Resolved(_, path)) = hir_impl.self_ty.kind
|
||||
&& let Some(seg) = path.segments.last()
|
||||
&& let Some(args) = seg.args
|
||||
{
|
||||
last_segment_args = Some(args);
|
||||
provided_params = args
|
||||
.args
|
||||
.iter()
|
||||
.filter(|arg| match arg {
|
||||
GenericArg::Lifetime(_) => is_lifetime,
|
||||
GenericArg::Type(_) => !is_lifetime,
|
||||
_ => false,
|
||||
})
|
||||
.count();
|
||||
}
|
||||
|
||||
let mut visitor = ParamUsageVisitor { tcx, param_def_id: param.def_id, found: false };
|
||||
for item_ref in hir_impl.items {
|
||||
let _ = visitor.visit_impl_item_ref(item_ref);
|
||||
if visitor.found {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let is_param_used = visitor.found;
|
||||
|
||||
let mut suggestions = vec![];
|
||||
|
||||
// Option A: Remove (Only if not used in body)
|
||||
if !is_param_used {
|
||||
suggestions.push((hir_impl.generics.span_for_param_removal(index), String::new()));
|
||||
}
|
||||
|
||||
// Option B: Suggest adding only if there's an available parameter in the struct definition
|
||||
// or the parameter is already used somewhere, then we suggest adding to the impl struct and the struct definition
|
||||
if provided_params < total_params || is_param_used {
|
||||
if let Some(args) = last_segment_args {
|
||||
// Struct already has <...>, append to it
|
||||
suggestions.push((args.span().unwrap().shrink_to_hi(), format!(", {}", param.name)));
|
||||
} else if let TyKind::Path(QPath::Resolved(_, path)) = hir_impl.self_ty.kind {
|
||||
// Struct has no <...> yet, add it
|
||||
let seg = path.segments.last().unwrap();
|
||||
suggestions.push((seg.ident.span.shrink_to_hi(), format!("<{}>", param.name)));
|
||||
}
|
||||
if is_param_used {
|
||||
// If the parameter is used in the body, we also want to suggest adding it to the struct definition if it's not already there
|
||||
let struct_span = tcx.def_span(struct_def_id);
|
||||
let last_param_span = if let Some(local_def_id) = struct_def_id.as_local() {
|
||||
let hir_struct = tcx.hir_node_by_def_id(local_def_id).expect_item().expect_struct();
|
||||
hir_struct.1.params.last().map(|param| param.span)
|
||||
} else {
|
||||
let generics = tcx.generics_of(struct_def_id);
|
||||
generics.own_params.last().map(|param| tcx.def_span(param.def_id))
|
||||
};
|
||||
|
||||
if let Some(last_param_span) = last_param_span {
|
||||
suggestions.push((last_param_span.shrink_to_hi(), format!(", {}", param.name)));
|
||||
} else {
|
||||
suggestions.push((struct_span.shrink_to_hi(), format!("<{}>", param.name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if suggestions.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let parameter_type = if is_lifetime { "lifetime" } else { "type" };
|
||||
if is_param_used {
|
||||
let msg = format!(
|
||||
"use the {} parameter `{}` in the `{}` type and use it in the type definition",
|
||||
parameter_type,
|
||||
param.name,
|
||||
tcx.def_path_str(struct_def_id)
|
||||
);
|
||||
diag.multipart_suggestion(
|
||||
msg,
|
||||
vec![
|
||||
(suggestions[0].0, suggestions[0].1.clone()),
|
||||
(suggestions[1].0, suggestions[1].1.clone()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
let msg = if suggestions.len() == 2 {
|
||||
format!("either remove the unused {} parameter `{}`", parameter_type, param.name)
|
||||
} else {
|
||||
format!("remove the unused {} parameter `{}`", parameter_type, param.name)
|
||||
};
|
||||
diag.span_suggestion(
|
||||
suggestions[0].0,
|
||||
msg,
|
||||
suggestions[0].1.clone(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if suggestions.len() == 2 {
|
||||
let msg = format!("or use it");
|
||||
diag.span_suggestion(
|
||||
suggestions[1].0,
|
||||
msg,
|
||||
suggestions[1].1.clone(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
use crate::constrained_generic_params as cgp;
|
||||
use crate::errors::UnconstrainedGenericParameter;
|
||||
use crate::errors::remove_or_use_generic::suggest_to_remove_or_use_generic;
|
||||
|
||||
mod min_specialization;
|
||||
|
||||
@@ -177,6 +178,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained(
|
||||
);
|
||||
}
|
||||
}
|
||||
suggest_to_remove_or_use_generic(tcx, &mut diag, impl_def_id, param, true);
|
||||
res = Err(diag.emit());
|
||||
}
|
||||
}
|
||||
@@ -242,6 +244,7 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained(
|
||||
const_param_note2: const_param_note,
|
||||
});
|
||||
diag.code(E0207);
|
||||
suggest_to_remove_or_use_generic(tcx, &mut diag, impl_def_id, ¶m, false);
|
||||
res = Err(diag.emit());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
--> $DIR/not-wf-ambiguous-normalization.rs:14:6
|
||||
|
|
||||
LL | impl<T> Allocator for DefaultAllocator {
|
||||
| ^ unconstrained type parameter
|
||||
| -^-
|
||||
| ||
|
||||
| |unconstrained type parameter
|
||||
| help: remove the unused type parameter `T`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
+4
-1
@@ -2,7 +2,10 @@ error[E0207]: the type parameter `Q` is not constrained by the impl trait, self
|
||||
--> $DIR/unconstrained-param-in-impl-ambiguity.rs:7:13
|
||||
|
|
||||
LL | unsafe impl<Q: Trait> Send for Inner {}
|
||||
| ^ unconstrained type parameter
|
||||
| -^--------
|
||||
| ||
|
||||
| |unconstrained type parameter
|
||||
| help: remove the unused type parameter `Q`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -3,6 +3,13 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
|
||||
|
|
||||
LL | impl<'a> Foo<fn(&())> {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
|
||||
help: use the lifetime parameter `'a` in the `Foo` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Foo<T, 'a>(T);
|
||||
LL |
|
||||
LL ~ impl<'a> Foo<fn(&()), 'a> {
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/hr-do-not-blame-outlives-static-ice.rs:13:11
|
||||
|
||||
@@ -2,7 +2,10 @@ error[E0207]: the type parameter `X` is not constrained by the impl trait, self
|
||||
--> $DIR/inherent-assoc-ty-mismatch-issue-153539.rs:9:6
|
||||
|
|
||||
LL | impl<X> S<'_> {
|
||||
| ^ unconstrained type parameter
|
||||
| -^-
|
||||
| ||
|
||||
| |unconstrained type parameter
|
||||
| help: remove the unused type parameter `X`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/inherent-assoc-ty-mismatch-issue-153539.rs:17:5
|
||||
|
||||
+4
-1
@@ -27,7 +27,10 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
--> $DIR/next-solver-opaque-inherent-fn-ptr-issue-155204.rs:7:6
|
||||
|
|
||||
LL | impl<T> Windows<fn(&())> {
|
||||
| ^ unconstrained type parameter
|
||||
| -^-
|
||||
| ||
|
||||
| |unconstrained type parameter
|
||||
| help: remove the unused type parameter `T`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/next-solver-opaque-inherent-fn-ptr-issue-155204.rs:12:22
|
||||
|
||||
@@ -24,7 +24,10 @@ error[E0207]: the const parameter `X` is not constrained by the impl trait, self
|
||||
--> $DIR/next-solver-opaque-inherent-no-ice.rs:6:6
|
||||
|
|
||||
LL | impl<const X: y> Foo {
|
||||
| ^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `X`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
@@ -3,6 +3,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
|
|
||||
LL | impl<T: Tr> S<T::Assoc> {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `S` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct S<T, T>(T);
|
||||
LL |
|
||||
LL | trait Tr { type Assoc; fn test(); }
|
||||
LL |
|
||||
LL ~ impl<T: Tr> S<T::Assoc, T> {
|
||||
|
|
||||
|
||||
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/issue-26262.rs:17:6
|
||||
|
||||
@@ -3,6 +3,15 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
|
||||
|
|
||||
LL | impl<'a> Fun for Holder {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
|
||||
help: use the lifetime parameter `'a` in the `Holder` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Holder<'a> {
|
||||
LL | x: String,
|
||||
LL | }
|
||||
LL |
|
||||
LL ~ impl<'a> Fun for Holder<'a> {
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -8,7 +8,10 @@ error[E0207]: the const parameter `H` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-78654.rs:9:6
|
||||
|
|
||||
LL | impl<const H: feature> Foo {
|
||||
| ^^^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `H`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
@@ -8,7 +8,10 @@ error[E0207]: the const parameter `H` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-78654.rs:9:6
|
||||
|
|
||||
LL | impl<const H: feature> Foo {
|
||||
| ^^^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `H`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
@@ -37,7 +37,10 @@ error[E0207]: the const parameter `N` is not constrained by the impl trait, self
|
||||
--> $DIR/unsized-anon-const-err-2.rs:13:6
|
||||
|
|
||||
LL | impl<const N: i32> Copy for S<A> {}
|
||||
| ^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `N`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
@@ -46,7 +49,10 @@ error[E0207]: the const parameter `M` is not constrained by the impl trait, self
|
||||
--> $DIR/unsized-anon-const-err-2.rs:16:6
|
||||
|
|
||||
LL | impl<const M: usize> Copy for S<A> {}
|
||||
| ^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `M`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
+4
-1
@@ -24,7 +24,10 @@ error[E0207]: the const parameter `NUM` is not constrained by the impl trait, se
|
||||
--> $DIR/post-analysis-user-facing-param-env.rs:5:10
|
||||
|
|
||||
LL | impl<'a, const NUM: usize> std::ops::Add<&'a Foo> for Foo
|
||||
| ^^^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| --^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | unconstrained const parameter
|
||||
| help: remove the unused type parameter `NUM`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
@@ -71,6 +71,14 @@ LL | impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, {}> {
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
help: use the type parameter `N` in the `ConstChunksExact` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct ConstChunksExact<'rem, T: 'a, const N: usize, N> {}
|
||||
LL |
|
||||
LL |
|
||||
LL |
|
||||
LL ~ impl<'a, T, const N: usize> Iterator for ConstChunksExact<'a, T, {}, N> {
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
||||
@@ -14,7 +14,10 @@ error[E0207]: the const parameter `N` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-68366.rs:12:7
|
||||
|
|
||||
LL | impl <const N: usize> Collatz<{Some(N)}> {}
|
||||
| ^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `N`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
@@ -23,7 +26,10 @@ error[E0207]: the const parameter `N` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-68366.rs:19:6
|
||||
|
|
||||
LL | impl<const N: usize> Foo {}
|
||||
| ^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `N`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
@@ -23,7 +23,10 @@ error[E0207]: the const parameter `N` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-68366.rs:12:7
|
||||
|
|
||||
LL | impl <const N: usize> Collatz<{Some(N)}> {}
|
||||
| ^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `N`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
@@ -32,7 +35,10 @@ error[E0207]: the const parameter `N` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-68366.rs:19:6
|
||||
|
|
||||
LL | impl<const N: usize> Foo {}
|
||||
| ^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `N`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
@@ -53,6 +53,14 @@ LL | impl<'a, T: std::fmt::Debug, const N: usize> Iterator for ConstChunksExact<
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
help: use the type parameter `N` in the `ConstChunksExact` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct ConstChunksExact<'a, T: '_, const assert: usize, N> {}
|
||||
LL |
|
||||
LL |
|
||||
LL |
|
||||
LL ~ impl<'a, T: std::fmt::Debug, const N: usize> Iterator for ConstChunksExact<'a, T, {}, N> {
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/normalizing_with_unconstrained_impl_params.rs:6:27
|
||||
|
||||
@@ -22,7 +22,10 @@ error[E0207]: the const parameter `UNUSED` is not constrained by the impl trait,
|
||||
--> $DIR/unconstrained_const_param_on_drop.rs:3:6
|
||||
|
|
||||
LL | impl<const UNUSED: usize> Drop for Foo {}
|
||||
| ^^^^^^^^^^^^^^^^^^^ unconstrained const parameter
|
||||
| -^^^^^^^^^^^^^^^^^^^-
|
||||
| ||
|
||||
| |unconstrained const parameter
|
||||
| help: remove the unused type parameter `UNUSED`
|
||||
|
|
||||
= note: expressions using a const parameter must map each value to a distinct output value
|
||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
@@ -3,6 +3,13 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
|
|
||||
LL | impl<T: Default> Foo {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `Foo` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Foo<T>;
|
||||
LL |
|
||||
LL ~ impl<T: Default> Foo<T> {
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -3,6 +3,15 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self
|
||||
|
|
||||
LL | impl<'b, T, U> AsRef2 for Foo<T>
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `U` in the `Foo` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Foo<T, U>(T);
|
||||
LL | #[derive(Debug)]
|
||||
LL | struct FooRef<'a, U>(&'a [U]);
|
||||
LL |
|
||||
LL ~ impl<'b, T, U> AsRef2 for Foo<T, U>
|
||||
|
|
||||
|
||||
error[E0309]: the parameter type `U` may not live long enough
|
||||
--> $DIR/issue-87735.rs:34:3
|
||||
|
||||
@@ -2,7 +2,10 @@ error[E0207]: the type parameter `I` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-88526.rs:25:13
|
||||
|
|
||||
LL | impl<'q, Q, I, F> A for TestB<Q, F>
|
||||
| ^ unconstrained type parameter
|
||||
| ^--
|
||||
| |
|
||||
| unconstrained type parameter
|
||||
| help: remove the unused type parameter `I`
|
||||
|
||||
error[E0309]: the parameter type `F` may not live long enough
|
||||
--> $DIR/issue-88526.rs:16:5
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
//! Test that making use of parameter is suggested when a parameter with default type is available
|
||||
|
||||
struct S<U = i32> {
|
||||
_u: U,
|
||||
}
|
||||
impl<V> MyTrait for S {}
|
||||
//~^ ERROR the type parameter `V` is not constrained by the impl trait, self type, or predicates
|
||||
|
||||
struct S2<T, U = i32> {
|
||||
_t: T,
|
||||
_u: U,
|
||||
}
|
||||
impl<T, V> MyTrait for S2<T> {}
|
||||
//~^ ERROR the type parameter `V` is not constrained by the impl trait, self type, or predicates
|
||||
|
||||
trait MyTrait {}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,35 @@
|
||||
error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-param-default-available.rs:6:6
|
||||
|
|
||||
LL | impl<V> MyTrait for S {}
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: either remove the unused type parameter `V`
|
||||
|
|
||||
LL - impl<V> MyTrait for S {}
|
||||
LL + impl MyTrait for S {}
|
||||
|
|
||||
help: or use it
|
||||
|
|
||||
LL | impl<V> MyTrait for S<V> {}
|
||||
| +++
|
||||
|
||||
error[E0207]: the type parameter `V` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-param-default-available.rs:13:9
|
||||
|
|
||||
LL | impl<T, V> MyTrait for S2<T> {}
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: either remove the unused type parameter `V`
|
||||
|
|
||||
LL - impl<T, V> MyTrait for S2<T> {}
|
||||
LL + impl<T> MyTrait for S2<T> {}
|
||||
|
|
||||
help: or use it
|
||||
|
|
||||
LL | impl<T, V> MyTrait for S2<T, V> {}
|
||||
| +++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0207`.
|
||||
@@ -2,13 +2,19 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
--> $DIR/unconstrained-type-params-inherent-impl.rs:11:6
|
||||
|
|
||||
LL | impl<T> MyType {
|
||||
| ^ unconstrained type parameter
|
||||
| -^-
|
||||
| ||
|
||||
| |unconstrained type parameter
|
||||
| help: remove the unused type parameter `T`
|
||||
|
||||
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-type-params-inherent-impl.rs:20:9
|
||||
|
|
||||
LL | impl<T, U> MyType1<T> {
|
||||
| ^ unconstrained type parameter
|
||||
| --^
|
||||
| | |
|
||||
| | unconstrained type parameter
|
||||
| help: remove the unused type parameter `U`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
//! Test that making use of parameter is suggested when the parameter is used in the impl
|
||||
//! but not in the trait or self type
|
||||
|
||||
struct S;
|
||||
impl<T> S {
|
||||
//~^ ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
fn foo(&self, x: T) {
|
||||
// use T here
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct S2<F> {
|
||||
_f: F,
|
||||
}
|
||||
impl<F, T> S2<F> {
|
||||
//~^ ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
fn foo(&self, x: T) {
|
||||
// use T here
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,29 @@
|
||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-used-param.rs:5:6
|
||||
|
|
||||
LL | impl<T> S {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `S` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct S<T>;
|
||||
LL ~ impl<T> S<T> {
|
||||
|
|
||||
|
||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-used-param.rs:16:9
|
||||
|
|
||||
LL | impl<F, T> S2<F> {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `S2` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct S2<F, T> {
|
||||
LL | _f: F,
|
||||
LL | }
|
||||
LL ~ impl<F, T> S2<F, T> {
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0207`.
|
||||
@@ -2,7 +2,10 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-16562.rs:10:6
|
||||
|
|
||||
LL | impl<T, M: MatrixShape> Collection for Col<M, usize> {
|
||||
| ^ unconstrained type parameter
|
||||
| ^--
|
||||
| |
|
||||
| unconstrained type parameter
|
||||
| help: remove the unused type parameter `T`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -3,6 +3,13 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
|
||||
|
|
||||
LL | impl<'a> Iterator for Newtype {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
|
||||
help: use the lifetime parameter `'a` in the `Newtype` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Newtype<'a>(Option<Box<usize>>);
|
||||
LL |
|
||||
LL ~ impl<'a> Iterator for Newtype<'a> {
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -3,6 +3,13 @@ error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait,
|
||||
|
|
||||
LL | impl<'a> MethodType for MTFn {
|
||||
| ^^ unconstrained lifetime parameter
|
||||
|
|
||||
help: use the lifetime parameter `'a` in the `MTFn` type and use it in the type definition
|
||||
|
|
||||
LL ~ pub struct MTFn<'a>;
|
||||
LL |
|
||||
LL ~ impl<'a> MethodType for MTFn<'a> {
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
//! This file is used to test suggestions for generics in other crates.
|
||||
|
||||
pub struct External;
|
||||
pub struct ExternalGeneric<T>(T);
|
||||
@@ -0,0 +1,54 @@
|
||||
//@ aux-build:generics_other_crate.rs
|
||||
|
||||
extern crate generics_other_crate;
|
||||
use generics_other_crate::External;
|
||||
|
||||
struct Local;
|
||||
struct Defaulted<T = u32>(T);
|
||||
|
||||
// Case 1: Unused parameter -> suggests removing T
|
||||
impl<T> Local {}
|
||||
//~^ ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
//~| HELP: remove the unused type parameter `T`
|
||||
|
||||
// Case 2: T used in body but not in self type
|
||||
// -> suggests adding T to self type and struct definition
|
||||
impl<T> Local {
|
||||
//~^ ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
//~| HELP: use the type parameter `T` in the `Local` type and use it in the type definition
|
||||
fn check() {
|
||||
let _: T;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Case 3: Struct has a generic parameter with a default
|
||||
// -> suggests adding T to the self type
|
||||
impl<T> Defaulted {}
|
||||
//~^ ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
//~| HELP: either remove the unused type parameter `T`
|
||||
//~| HELP: or use it
|
||||
|
||||
// Case 4: Generated from a macro
|
||||
macro_rules! make_impl {
|
||||
($t:ident) => {
|
||||
impl<$t> Local {}
|
||||
//~^ HELP: remove the unused type parameter `U`
|
||||
}
|
||||
}
|
||||
make_impl!(U);
|
||||
//~^ ERROR the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
|
||||
// Case 5: Type defined in another crate
|
||||
impl<T> External {
|
||||
//~^ ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
//~| ERROR: cannot define inherent `impl` for a type outside of the crate where the type is defined [E0116]
|
||||
//~| HELP: use the type parameter `T` in the `External` type and use it in the type definition
|
||||
//~| HELP: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
|
||||
fn check() {
|
||||
let _: T;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,68 @@
|
||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-params.rs:10:6
|
||||
|
|
||||
LL | impl<T> Local {}
|
||||
| -^-
|
||||
| ||
|
||||
| |unconstrained type parameter
|
||||
| help: remove the unused type parameter `T`
|
||||
|
||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-params.rs:16:6
|
||||
|
|
||||
LL | impl<T> Local {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `Local` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Local<T>;
|
||||
LL | struct Defaulted<T = u32>(T);
|
||||
...
|
||||
LL | // -> suggests adding T to self type and struct definition
|
||||
LL ~ impl<T> Local<T> {
|
||||
|
|
||||
|
||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-params.rs:27:6
|
||||
|
|
||||
LL | impl<T> Defaulted {}
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: either remove the unused type parameter `T`
|
||||
|
|
||||
LL - impl<T> Defaulted {}
|
||||
LL + impl Defaulted {}
|
||||
|
|
||||
help: or use it
|
||||
|
|
||||
LL | impl<T> Defaulted<T> {}
|
||||
| +++
|
||||
|
||||
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-params.rs:39:12
|
||||
|
|
||||
LL | impl<$t> Local {}
|
||||
| ---- help: remove the unused type parameter `U`
|
||||
...
|
||||
LL | make_impl!(U);
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained-params.rs:43:6
|
||||
|
|
||||
LL | impl<T> External {
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
|
||||
--> $DIR/unconstrained-params.rs:43:1
|
||||
|
|
||||
LL | impl<T> External {
|
||||
| ^^^^^^^^^^^^^^^^ impl for type defined outside of crate
|
||||
|
|
||||
= help: consider defining a trait and implementing it for the type or using a newtype wrapper like `struct MyType(ExternalType);` and implement it
|
||||
= note: for more details about the orphan rules, see <https://doc.rust-lang.org/reference/items/implementations.html?highlight=orphan#orphan-rules>
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0116, E0207.
|
||||
For more information about an error, try `rustc --explain E0116`.
|
||||
@@ -2,7 +2,10 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:19:9
|
||||
|
|
||||
LL | impl<T, U> Trait<()> for B<T>
|
||||
| ^ unconstrained type parameter
|
||||
| --^
|
||||
| | |
|
||||
| | unconstrained type parameter
|
||||
| help: remove the unused type parameter `U`
|
||||
|
||||
error[E0277]: the trait bound `(): IncompleteGuidance` is not satisfied
|
||||
--> $DIR/leaking-vars-in-cause-code-2.rs:29:19
|
||||
|
||||
@@ -3,6 +3,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
|
|
||||
LL | impl<T: ?Sized> Every for Thing {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `Thing` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Thing<T>;
|
||||
LL |
|
||||
...
|
||||
LL | }
|
||||
LL ~ impl<T: ?Sized> Every for Thing<T> {
|
||||
|
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/unconstrained-projection-normalization-2.rs:16:18
|
||||
|
||||
@@ -3,6 +3,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
|
|
||||
LL | impl<T: ?Sized> Every for Thing {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `Thing` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Thing<T>;
|
||||
LL |
|
||||
...
|
||||
LL | }
|
||||
LL ~ impl<T: ?Sized> Every for Thing<T> {
|
||||
|
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/unconstrained-projection-normalization-2.rs:16:18
|
||||
|
||||
@@ -3,6 +3,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
|
|
||||
LL | impl<T: ?Sized> Every for Thing {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `Thing` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Thing<T>;
|
||||
LL |
|
||||
...
|
||||
LL | }
|
||||
LL ~ impl<T: ?Sized> Every for Thing<T> {
|
||||
|
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/unconstrained-projection-normalization.rs:15:18
|
||||
|
||||
@@ -3,6 +3,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
|
|
||||
LL | impl<T: ?Sized> Every for Thing {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `Thing` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Thing<T>;
|
||||
LL |
|
||||
...
|
||||
LL | }
|
||||
LL ~ impl<T: ?Sized> Every for Thing<T> {
|
||||
|
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/unconstrained-projection-normalization.rs:15:18
|
||||
|
||||
@@ -3,6 +3,15 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
|
|
||||
LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
|
||||
| ^ unconstrained type parameter
|
||||
|
|
||||
help: use the type parameter `T` in the `Scope` type and use it in the type definition
|
||||
|
|
||||
LL ~ struct Scope<T, T>(Phantom2<DummyT<T>>);
|
||||
LL |
|
||||
...
|
||||
LL |
|
||||
LL ~ impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U, T> {
|
||||
|
|
||||
|
||||
error: item does not constrain `DummyT::{opaque#0}`
|
||||
--> $DIR/ice-failed-to-resolve-instance-for-110696.rs:30:8
|
||||
|
||||
@@ -2,7 +2,10 @@ error[E0207]: the type parameter `T` is not constrained by the impl trait, self
|
||||
--> $DIR/issue-74244.rs:9:6
|
||||
|
|
||||
LL | impl<T> Allocator for DefaultAllocator {
|
||||
| ^ unconstrained type parameter
|
||||
| -^-
|
||||
| ||
|
||||
| |unconstrained type parameter
|
||||
| help: remove the unused type parameter `T`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user