diff options
| -rw-r--r-- | compiler/rustc_typeck/src/check/wfcheck.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/lib.rs | 1 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-17904-2.stderr | 1 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-37534.stderr | 1 | ||||
| -rw-r--r-- | src/test/ui/variance/variance-unused-type-param.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/variance/variance-unused-type-param.stderr | 26 |
6 files changed, 67 insertions, 7 deletions
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 4ab654560ea..a42ed9eab64 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -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(...)`. @@ -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(¶meter) { continue; } @@ -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(¶meter); + 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); @@ -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 diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 40904c1dfd6..f0289fd505a 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -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"] #![allow(rustc::potential_query_instability)] diff --git a/src/test/ui/issues/issue-17904-2.stderr b/src/test/ui/issues/issue-17904-2.stderr index 259e029113d..62b7b79538c 100644 --- a/src/test/ui/issues/issue-17904-2.stderr +++ b/src/test/ui/issues/issue-17904-2.stderr @@ -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 diff --git a/src/test/ui/issues/issue-37534.stderr b/src/test/ui/issues/issue-37534.stderr index 82bb51028c9..895479986f1 100644 --- a/src/test/ui/issues/issue-37534.stderr +++ b/src/test/ui/issues/issue-37534.stderr @@ -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 diff --git a/src/test/ui/variance/variance-unused-type-param.rs b/src/test/ui/variance/variance-unused-type-param.rs index 1e0e403ebce..d1114064364 100644 --- a/src/test/ui/variance/variance-unused-type-param.rs +++ b/src/test/ui/variance/variance-unused-type-param.rs @@ -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() {} diff --git a/src/test/ui/variance/variance-unused-type-param.stderr b/src/test/ui/variance/variance-unused-type-param.stderr index 270233c0c97..e612da118f0 100644 --- a/src/test/ui/variance/variance-unused-type-param.stderr +++ b/src/test/ui/variance/variance-unused-type-param.stderr @@ -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`. |
