@@ -31,6 +31,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode,
3131
3232use std:: convert:: TryInto ;
3333use std:: iter;
34+ use std:: lazy:: Lazy ;
3435use 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
0 commit comments