Change:
Given the following code: The current output is: Ideally, the diagnostic shouldn't suggest relaxing an explicit bound in the where clause. (There is already code that skips the suggestion for type parameters that have an explicit bound.) I can work on this in an in-progress pull request where I'm making other improvements to unsized suggestions. claim label +A-traits +A-typesystem +D-papercut <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --

Discussion:
pub bounds: GenericBounds<'hir>, } <ins> impl WhereBoundPredicate<'hir> { /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate. pub fn is_param_bound(&self, param_def_id: DefId) -> bool { let path = match self.bounded_ty.kind { TyKind::Path(QPath::Resolved(None, path)) => path, _ => return false, }; match path.res { Res::Def(DefKind::TyParam, def_id) | Res::SelfTy(Some(def_id), None) => { def_id == param_def_id } _ => false, } } } </ins> /// A lifetime predicate (e.g., `'a: 'b + 'c`). #[derive(Debug, HashStable_Generic)] pub struct WhereRegionPredicate<'hir> {

Some(param) => param, _ => return, }; <ins> let param_def_id = self.tcx.hir().local_def_id(param.hir_id).to_def_id(); let preds = generics.where_clause.predicates.iter(); let explicitly_sized = preds .filter_map(|pred| match pred { hir::WherePredicate::BoundPredicate(bp) => Some(bp), _ => None, }) .filter(|bp| bp.is_param_bound(param_def_id)) .flat_map(|bp| bp.bounds) .any(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) == sized_trait); if explicitly_sized { return; } </ins> debug!("maybe_suggest_unsized_generics: param={:?}", param); match node { hir::Node::Item(

use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; <del> use rustc_hir::def::{CtorKind, DefKind, Res}; </del> <ins> use rustc_hir::def::{CtorKind, DefKind}; </ins> use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::weak_lang_items;

}) .flat_map(|b| predicates_from_bound(self, ty, b)); <ins> let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id(); </ins> let from_where_clauses = ast_generics .where_clause .predicates

_ => None, }) .flat_map(|bp| { <del> let bt = if is_param(self.tcx, bp.bounded_ty, param_id) { </del> <ins> let bt = if bp.is_param_bound(param_def_id) { </ins> Some(ty) } else if !only_self_bounds.0 { Some(self.to_ty(bp.bounded_ty))

} } <del> /// Tests whether this is the AST for a reference to the type /// parameter with ID `param_id`. We use this so as to avoid running /// `ast_ty_to_ty`, because we want to avoid triggering an all-out /// conversion of the type to avoid inducing unnecessary cycles. fn is_param(tcx: TyCtxt<'_>, ast_ty: &hir::Ty<'_>, param_id: hir::HirId) -> bool { if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ast_ty.kind { match path.res { Res::SelfTy(Some(def_id), None) | Res::Def(DefKind::TyParam, def_id) => { def_id == tcx.hir().local_def_id(param_id).to_def_id() } _ => false, } } else { false } } </del> fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir().item(item_id); debug!("convert: item {} with id {}", it.ident, it.hir_id());

<ins> // Regression test for #85945: Don't suggest `?Sized` bound if an explicit // `Sized` bound is already in a `where` clause. fn foo<T>(_: &T) where T: Sized {} fn bar() { foo(""); } //~^ERROR the size for values of type pub fn main() { } </ins>

<ins> error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:4:16 | LL | fn bar() { foo(""); } |            --- ^^ doesn't have a size known at compile-time |            | |            required by a bound introduced by this call | = help: the trait `Sized` is not implemented for `str` note: required by a bound in `foo` --> $DIR/issue-85945-check-where-clause-before-suggesting-unsized.rs:3:8 | LL | fn foo<T>(_: &T) where T: Sized {} |        ^ required by this bound in `foo` error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. </ins>