Skip to content

Commit 4520045

Browse files
Do not suggest using a const parameter when there are bounds on an unused type parameter
The user wrote the bound, so it's obvious they want a type.
1 parent d4de1f2 commit 4520045

File tree

6 files changed

+67
-7
lines changed

6 files changed

+67
-7
lines changed

compiler/rustc_typeck/src/check/wfcheck.rs

+32-4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode,
3131

3232
use std::convert::TryInto;
3333
use std::iter;
34+
use std::lazy::Lazy;
3435
use std::ops::ControlFlow;
3536

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

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

1724+
// Lazily calculated because it is only needed in case of an error.
1725+
let explicitly_bounded_params = Lazy::new(|| {
1726+
let icx = crate::collect::ItemCtxt::new(tcx, item.def_id.to_def_id());
1727+
hir_generics
1728+
.where_clause
1729+
.predicates
1730+
.iter()
1731+
.filter_map(|predicate| match predicate {
1732+
hir::WherePredicate::BoundPredicate(predicate) => {
1733+
match icx.to_ty(predicate.bounded_ty).kind() {
1734+
ty::Param(data) => Some(Parameter(data.index)),
1735+
_ => None,
1736+
}
1737+
}
1738+
_ => None,
1739+
})
1740+
.collect::<FxHashSet<_>>()
1741+
});
1742+
17231743
for (index, _) in variances.iter().enumerate() {
1724-
if constrained_parameters.contains(&Parameter(index as u32)) {
1744+
let parameter = Parameter(index as u32);
1745+
1746+
if constrained_parameters.contains(&parameter) {
17251747
continue;
17261748
}
17271749

@@ -1730,13 +1752,19 @@ fn check_variances_for_type_defn<'tcx>(
17301752
match param.name {
17311753
hir::ParamName::Error => {}
17321754
_ => {
1733-
report_bivariance(tcx, param);
1755+
let has_explicit_bounds =
1756+
!param.bounds.is_empty() || explicitly_bounded_params.contains(&parameter);
1757+
report_bivariance(tcx, param, has_explicit_bounds);
17341758
}
17351759
}
17361760
}
17371761
}
17381762

1739-
fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) -> ErrorReported {
1763+
fn report_bivariance(
1764+
tcx: TyCtxt<'_>,
1765+
param: &rustc_hir::GenericParam<'_>,
1766+
has_explicit_bounds: bool,
1767+
) -> ErrorReported {
17401768
let span = param.span;
17411769
let param_name = param.name.ident().name;
17421770
let mut err = error_392(tcx, span, param_name);
@@ -1754,7 +1782,7 @@ fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) -> Er
17541782
};
17551783
err.help(&msg);
17561784

1757-
if matches!(param.kind, rustc_hir::GenericParamKind::Type { .. }) {
1785+
if matches!(param.kind, hir::GenericParamKind::Type { .. }) && !has_explicit_bounds {
17581786
err.help(&format!(
17591787
"if you intended `{0}` to be a const parameter, use `const {0}: usize` instead",
17601788
param_name

compiler/rustc_typeck/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ This API is completely unstable and subject to change.
6868
#![feature(slice_partition_dedup)]
6969
#![feature(control_flow_enum)]
7070
#![feature(hash_drain_filter)]
71+
#![feature(once_cell)]
7172
#![recursion_limit = "256"]
7273
#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
7374

src/test/ui/issues/issue-17904-2.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ LL | struct Foo<T> where T: Copy;
55
| ^ unused parameter
66
|
77
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
8-
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
98

109
error: aborting due to previous error
1110

src/test/ui/issues/issue-37534.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ LL | struct Foo<T: ?Hash> { }
2222
| ^ unused parameter
2323
|
2424
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
25-
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
2625

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

src/test/ui/variance/variance-unused-type-param.rs

+9
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,13 @@ enum ListCell<T> {
1616
Nil
1717
}
1818

19+
struct WithBounds<T: Sized> {}
20+
//~^ ERROR parameter `T` is never used
21+
22+
struct WithWhereBounds<T> where T: Sized {}
23+
//~^ ERROR parameter `T` is never used
24+
25+
struct WithOutlivesBounds<T: 'static> {}
26+
//~^ ERROR parameter `T` is never used
27+
1928
fn main() {}

src/test/ui/variance/variance-unused-type-param.stderr

+25-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,30 @@ LL | enum ListCell<T> {
2525
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
2626
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
2727

28-
error: aborting due to 3 previous errors
28+
error[E0392]: parameter `T` is never used
29+
--> $DIR/variance-unused-type-param.rs:19:19
30+
|
31+
LL | struct WithBounds<T: Sized> {}
32+
| ^ unused parameter
33+
|
34+
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
35+
36+
error[E0392]: parameter `T` is never used
37+
--> $DIR/variance-unused-type-param.rs:22:24
38+
|
39+
LL | struct WithWhereBounds<T> where T: Sized {}
40+
| ^ unused parameter
41+
|
42+
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
43+
44+
error[E0392]: parameter `T` is never used
45+
--> $DIR/variance-unused-type-param.rs:25:27
46+
|
47+
LL | struct WithOutlivesBounds<T: 'static> {}
48+
| ^ unused parameter
49+
|
50+
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
51+
52+
error: aborting due to 6 previous errors
2953

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

0 commit comments

Comments
 (0)