@@ -31,6 +31,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode,
31
31
32
32
use std:: convert:: TryInto ;
33
33
use std:: iter;
34
+ use std:: lazy:: Lazy ;
34
35
use std:: ops:: ControlFlow ;
35
36
36
37
/// Helper type of a temporary returned by `.for_item(...)`.
@@ -1720,8 +1721,29 @@ fn check_variances_for_type_defn<'tcx>(
1720
1721
1721
1722
identify_constrained_generic_params ( tcx, ty_predicates, None , & mut constrained_parameters) ;
1722
1723
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
+
1723
1743
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) {
1725
1747
continue ;
1726
1748
}
1727
1749
@@ -1730,13 +1752,19 @@ fn check_variances_for_type_defn<'tcx>(
1730
1752
match param. name {
1731
1753
hir:: ParamName :: Error => { }
1732
1754
_ => {
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) ;
1734
1758
}
1735
1759
}
1736
1760
}
1737
1761
}
1738
1762
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 {
1740
1768
let span = param. span ;
1741
1769
let param_name = param. name . ident ( ) . name ;
1742
1770
let mut err = error_392 ( tcx, span, param_name) ;
@@ -1754,7 +1782,7 @@ fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) -> Er
1754
1782
} ;
1755
1783
err. help ( & msg) ;
1756
1784
1757
- if matches ! ( param. kind, rustc_hir :: GenericParamKind :: Type { .. } ) {
1785
+ if matches ! ( param. kind, hir :: GenericParamKind :: Type { .. } ) && !has_explicit_bounds {
1758
1786
err. help ( & format ! (
1759
1787
"if you intended `{0}` to be a const parameter, use `const {0}: usize` instead" ,
1760
1788
param_name
0 commit comments