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:
Jonathan Brouwer
2026-05-15 20:11:41 +02:00
committed by GitHub
42 changed files with 734 additions and 21 deletions
+87
View File
@@ -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, &param, 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
@@ -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
@@ -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
@@ -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
+7
View File
@@ -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`.
+4 -1
View File
@@ -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
+7
View File
@@ -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
+7
View File
@@ -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