mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 04:08:40 +00:00
Rollup merge of #86455 - tlyu:check-where-before-suggesting-unsized, r=estebank
check where-clause for explicit `Sized` before suggesting `?Sized` Fixes #85945. Based on #86454. ``@rustbot`` label +A-diagnostics +A-traits +A-typesystem +D-papercut +T-compiler
This commit is contained in:
commit
ebef3ce25b
@ -647,6 +647,22 @@ pub struct WhereBoundPredicate<'hir> {
|
|||||||
pub bounds: GenericBounds<'hir>,
|
pub bounds: GenericBounds<'hir>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A lifetime predicate (e.g., `'a: 'b + 'c`).
|
/// A lifetime predicate (e.g., `'a: 'b + 'c`).
|
||||||
#[derive(Debug, HashStable_Generic)]
|
#[derive(Debug, HashStable_Generic)]
|
||||||
pub struct WhereRegionPredicate<'hir> {
|
pub struct WhereRegionPredicate<'hir> {
|
||||||
|
@ -2009,6 +2009,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
Some(param) => param,
|
Some(param) => param,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
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;
|
||||||
|
}
|
||||||
debug!("maybe_suggest_unsized_generics: param={:?}", param);
|
debug!("maybe_suggest_unsized_generics: param={:?}", param);
|
||||||
match node {
|
match node {
|
||||||
hir::Node::Item(
|
hir::Node::Item(
|
||||||
|
@ -28,7 +28,7 @@ use rustc_data_structures::captures::Captures;
|
|||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||||
use rustc_errors::{struct_span_err, Applicability};
|
use rustc_errors::{struct_span_err, Applicability};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
use rustc_hir::def::{CtorKind, DefKind};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
|
||||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::weak_lang_items;
|
use rustc_hir::weak_lang_items;
|
||||||
@ -668,6 +668,7 @@ impl ItemCtxt<'tcx> {
|
|||||||
})
|
})
|
||||||
.flat_map(|b| predicates_from_bound(self, ty, b));
|
.flat_map(|b| predicates_from_bound(self, ty, b));
|
||||||
|
|
||||||
|
let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
|
||||||
let from_where_clauses = ast_generics
|
let from_where_clauses = ast_generics
|
||||||
.where_clause
|
.where_clause
|
||||||
.predicates
|
.predicates
|
||||||
@ -677,7 +678,7 @@ impl ItemCtxt<'tcx> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.flat_map(|bp| {
|
.flat_map(|bp| {
|
||||||
let bt = if is_param(self.tcx, bp.bounded_ty, param_id) {
|
let bt = if bp.is_param_bound(param_def_id) {
|
||||||
Some(ty)
|
Some(ty)
|
||||||
} else if !only_self_bounds.0 {
|
} else if !only_self_bounds.0 {
|
||||||
Some(self.to_ty(bp.bounded_ty))
|
Some(self.to_ty(bp.bounded_ty))
|
||||||
@ -714,23 +715,6 @@ impl ItemCtxt<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
||||||
let it = tcx.hir().item(item_id);
|
let it = tcx.hir().item(item_id);
|
||||||
debug!("convert: item {} with id {}", it.ident, it.hir_id());
|
debug!("convert: item {} with id {}", it.ident, it.hir_id());
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
// 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() {
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
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`.
|
Loading…
Reference in New Issue
Block a user