Skip to content

Do not suggest using a const parameter when there are bounds on an unused type parameter #93400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode,

use std::convert::TryInto;
use std::iter;
use std::lazy::Lazy;
use std::ops::ControlFlow;

/// Helper type of a temporary returned by `.for_item(...)`.
Expand Down Expand Up @@ -1720,8 +1721,29 @@ fn check_variances_for_type_defn<'tcx>(

identify_constrained_generic_params(tcx, ty_predicates, None, &mut constrained_parameters);

// Lazily calculated because it is only needed in case of an error.
let explicitly_bounded_params = Lazy::new(|| {
let icx = crate::collect::ItemCtxt::new(tcx, item.def_id.to_def_id());
hir_generics
.where_clause
.predicates
.iter()
.filter_map(|predicate| match predicate {
hir::WherePredicate::BoundPredicate(predicate) => {
match icx.to_ty(predicate.bounded_ty).kind() {
ty::Param(data) => Some(Parameter(data.index)),
_ => None,
}
}
_ => None,
})
.collect::<FxHashSet<_>>()
});

for (index, _) in variances.iter().enumerate() {
if constrained_parameters.contains(&Parameter(index as u32)) {
let parameter = Parameter(index as u32);

if constrained_parameters.contains(&parameter) {
continue;
}

Expand All @@ -1730,13 +1752,19 @@ fn check_variances_for_type_defn<'tcx>(
match param.name {
hir::ParamName::Error => {}
_ => {
report_bivariance(tcx, param);
let has_explicit_bounds =
!param.bounds.is_empty() || explicitly_bounded_params.contains(&parameter);
report_bivariance(tcx, param, has_explicit_bounds);
}
}
}
}

fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) -> ErrorReported {
fn report_bivariance(
tcx: TyCtxt<'_>,
param: &rustc_hir::GenericParam<'_>,
has_explicit_bounds: bool,
) -> ErrorReported {
let span = param.span;
let param_name = param.name.ident().name;
let mut err = error_392(tcx, span, param_name);
Expand All @@ -1754,7 +1782,7 @@ fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) -> Er
};
err.help(&msg);

if matches!(param.kind, rustc_hir::GenericParamKind::Type { .. }) {
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds {
err.help(&format!(
"if you intended `{0}` to be a const parameter, use `const {0}: usize` instead",
param_name
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ This API is completely unstable and subject to change.
#![feature(slice_partition_dedup)]
#![feature(control_flow_enum)]
#![feature(hash_drain_filter)]
#![feature(once_cell)]
#![recursion_limit = "256"]
#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]

Expand Down
1 change: 0 additions & 1 deletion src/test/ui/issues/issue-17904-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ LL | struct Foo<T> where T: Copy;
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: usize` instead

error: aborting due to previous error

Expand Down
1 change: 0 additions & 1 deletion src/test/ui/issues/issue-37534.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ LL | struct Foo<T: ?Hash> { }
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: usize` instead

error: aborting due to 2 previous errors; 1 warning emitted

Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/variance/variance-unused-type-param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,13 @@ enum ListCell<T> {
Nil
}

struct WithBounds<T: Sized> {}
//~^ ERROR parameter `T` is never used

struct WithWhereBounds<T> where T: Sized {}
//~^ ERROR parameter `T` is never used

struct WithOutlivesBounds<T: 'static> {}
//~^ ERROR parameter `T` is never used

fn main() {}
26 changes: 25 additions & 1 deletion src/test/ui/variance/variance-unused-type-param.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@ LL | enum ListCell<T> {
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: usize` instead

error: aborting due to 3 previous errors
error[E0392]: parameter `T` is never used
--> $DIR/variance-unused-type-param.rs:19:19
|
LL | struct WithBounds<T: Sized> {}
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`

error[E0392]: parameter `T` is never used
--> $DIR/variance-unused-type-param.rs:22:24
|
LL | struct WithWhereBounds<T> where T: Sized {}
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`

error[E0392]: parameter `T` is never used
--> $DIR/variance-unused-type-param.rs:25:27
|
LL | struct WithOutlivesBounds<T: 'static> {}
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0392`.