]> git.lizzy.rs Git - rust.git/commitdiff
Do not suggest using a const parameter when there are bounds on an unused type parameter
authorChayim Refael Friedman <chayimfr@gmail.com>
Fri, 25 Feb 2022 05:44:33 +0000 (05:44 +0000)
committerGitHub <noreply@github.com>
Fri, 25 Feb 2022 05:44:33 +0000 (05:44 +0000)
The user wrote the bound, so it's obvious they want a type.

compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/lib.rs
src/test/ui/issues/issue-17904-2.stderr
src/test/ui/issues/issue-37534.stderr
src/test/ui/variance/variance-unused-type-param.rs
src/test/ui/variance/variance-unused-type-param.stderr

index 4ab654560ea0d70373b60cfa7d64433717636834..a42ed9eab64367f9eb8dbd86503c49bcbd9771f9 100644 (file)
@@ -31,6 +31,7 @@
 
 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(&parameter) {
             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(&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);
@@ -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
index d415e37ff0116435c67d6a0acf30a6c5d762c9d1..bbfe5295fe107f6ec9e1ad223120a7402968ec2b 100644 (file)
@@ -68,6 +68,7 @@
 #![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))]
 
index 259e029113d5097cf0a14e0ad6ab74de17c66c50..62b7b79538c612c9ff3a8767acf1bcc8172bf652 100644 (file)
@@ -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
 
index 82bb51028c9774d84dd478fc43268fe6cf2cbcaf..895479986f1d1a0323d5ee3cd305ed33f2ce2f74 100644 (file)
@@ -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
 
index 1e0e403ebcee201f92748e240db4175209952dfd..d111406436478372eb2d350f4bae42f8f19548b6 100644 (file)
@@ -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() {}
index 270233c0c97723acc8b785e842141c1596a86b4a..e612da118f058e2625650cb8964e8a5bf9255e58 100644 (file)
@@ -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`.