Walk through full path in point_at_path_if_possible

This commit is contained in:
Michael Goulet 2023-08-25 18:07:00 +00:00
parent 296c7a683c
commit 055452864e
6 changed files with 57 additions and 34 deletions

View File

@ -1,6 +1,6 @@
use crate::FnCtxt; use crate::FnCtxt;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode}; use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
@ -133,17 +133,16 @@ pub fn adjust_fulfillment_error_for_expr_obligation(
} }
} }
} }
// Notably, we only point to params that are local to the
// item we're checking, since those are the ones we are able for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
// to look in the final `hir::PathSegment` for. Everything else .into_iter()
// would require a deeper search into the `qpath` than I think .flatten()
// is worthwhile.
if let Some(param_to_point_at) = param_to_point_at
&& self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
{ {
if self.point_at_path_if_possible(error, def_id, param, qpath) {
return true; return true;
} }
} }
}
hir::ExprKind::MethodCall(segment, receiver, args, ..) => { hir::ExprKind::MethodCall(segment, receiver, args, ..) => {
for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
.into_iter() .into_iter()
@ -168,10 +167,8 @@ pub fn adjust_fulfillment_error_for_expr_obligation(
} }
} }
hir::ExprKind::Struct(qpath, fields, ..) => { hir::ExprKind::Struct(qpath, fields, ..) => {
if let Res::Def( if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
hir::def::DefKind::Struct | hir::def::DefKind::Variant, self.typeck_results.borrow().qpath_res(qpath, hir_id)
variant_def_id,
) = self.typeck_results.borrow().qpath_res(qpath, hir_id)
{ {
for param in for param in
[param_to_point_at, fallback_param_to_point_at, self_param_to_point_at] [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
@ -193,12 +190,16 @@ pub fn adjust_fulfillment_error_for_expr_obligation(
} }
} }
} }
if let Some(param_to_point_at) = param_to_point_at
&& self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath) for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
.into_iter()
.flatten()
{ {
if self.point_at_path_if_possible(error, def_id, param, qpath) {
return true; return true;
} }
} }
}
_ => {} _ => {}
} }
@ -214,12 +215,15 @@ fn point_at_path_if_possible(
) -> bool { ) -> bool {
match qpath { match qpath {
hir::QPath::Resolved(_, path) => { hir::QPath::Resolved(_, path) => {
if let Some(segment) = path.segments.last() for segment in path.segments.iter().rev() {
if let Res::Def(kind, def_id) = segment.res
&& !matches!(kind, DefKind::Mod | DefKind::ForeignMod)
&& self.point_at_generic_if_possible(error, def_id, param, segment) && self.point_at_generic_if_possible(error, def_id, param, segment)
{ {
return true; return true;
} }
} }
}
hir::QPath::TypeRelative(_, segment) => { hir::QPath::TypeRelative(_, segment) => {
if self.point_at_generic_if_possible(error, def_id, param, segment) { if self.point_at_generic_if_possible(error, def_id, param, segment) {
return true; return true;
@ -618,14 +622,14 @@ fn blame_specific_part_of_expr_corresponding_to_generic_param(
}; };
let variant_def_id = match expr_struct_def_kind { let variant_def_id = match expr_struct_def_kind {
hir::def::DefKind::Struct => { DefKind::Struct => {
if in_ty_adt.did() != expr_struct_def_id { if in_ty_adt.did() != expr_struct_def_id {
// FIXME: Deal with type aliases? // FIXME: Deal with type aliases?
return Err(expr); return Err(expr);
} }
expr_struct_def_id expr_struct_def_id
} }
hir::def::DefKind::Variant => { DefKind::Variant => {
// If this is a variant, its parent is the type definition. // If this is a variant, its parent is the type definition.
if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) { if in_ty_adt.did() != self.tcx.parent(expr_struct_def_id) {
// FIXME: Deal with type aliases? // FIXME: Deal with type aliases?
@ -727,14 +731,14 @@ fn blame_specific_part_of_expr_corresponding_to_generic_param(
}; };
let variant_def_id = match expr_struct_def_kind { let variant_def_id = match expr_struct_def_kind {
hir::def::DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => { DefKind::Ctor(hir::def::CtorOf::Struct, hir::def::CtorKind::Fn) => {
if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) { if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
// FIXME: Deal with type aliases? // FIXME: Deal with type aliases?
return Err(expr); return Err(expr);
} }
self.tcx.parent(expr_ctor_def_id) self.tcx.parent(expr_ctor_def_id)
} }
hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => { DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
// For a typical enum like // For a typical enum like
// `enum Blah<T> { Variant(T) }` // `enum Blah<T> { Variant(T) }`
// we get the following resolutions: // we get the following resolutions:

View File

@ -1,8 +1,8 @@
error[E0277]: the trait bound `(): Foo<N>` is not satisfied error[E0277]: the trait bound `(): Foo<N>` is not satisfied
--> $DIR/exhaustive-value.rs:262:5 --> $DIR/exhaustive-value.rs:262:16
| |
LL | <() as Foo<N>>::test() LL | <() as Foo<N>>::test()
| ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()` | ^ the trait `Foo<N>` is not implemented for `()`
| |
= help: the following other types implement trait `Foo<N>`: = help: the following other types implement trait `Foo<N>`:
<() as Foo<0>> <() as Foo<0>>

View File

@ -27,10 +27,10 @@ LL | Infallible: From<T>;
| ^^^^^^^ required by this bound in `K` | ^^^^^^^ required by this bound in `K`
error[E0277]: the trait bound `Vec<u8>: Copy` is not satisfied error[E0277]: the trait bound `Vec<u8>: Copy` is not satisfied
--> $DIR/unsatisfied-bounds.rs:32:13 --> $DIR/unsatisfied-bounds.rs:32:26
| |
LL | let _ = <() as Trait<Vec<u8>>>::A; LL | let _ = <() as Trait<Vec<u8>>>::A;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Vec<u8>` | ^^^^^^^ the trait `Copy` is not implemented for `Vec<u8>`
| |
note: required by a bound in `Trait::A` note: required by a bound in `Trait::A`
--> $DIR/unsatisfied-bounds.rs:17:12 --> $DIR/unsatisfied-bounds.rs:17:12

View File

@ -0,0 +1,6 @@
// Regression test for one part of issue #105306.
fn main() {
let _ = Option::<[u8]>::None;
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
}

View File

@ -0,0 +1,13 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> $DIR/enum-unit-variant-trait-bound.rs:4:22
|
LL | let _ = Option::<[u8]>::None;
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `None`
--> $SRC_DIR/core/src/option.rs:LL:COL
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -38,10 +38,10 @@ LL + fn check<T: Iterator, U>() {
| |
error[E0277]: the trait bound `u64: From<T>` is not satisfied error[E0277]: the trait bound `u64: From<T>` is not satisfied
--> $DIR/suggest-where-clause.rs:15:5 --> $DIR/suggest-where-clause.rs:15:18
| |
LL | <u64 as From<T>>::from; LL | <u64 as From<T>>::from;
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `u64` | ^ the trait `From<T>` is not implemented for `u64`
| |
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
| |
@ -49,10 +49,10 @@ LL | fn check<T: Iterator, U: ?Sized>() where u64: From<T> {
| ++++++++++++++++++ | ++++++++++++++++++
error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfied error[E0277]: the trait bound `u64: From<<T as Iterator>::Item>` is not satisfied
--> $DIR/suggest-where-clause.rs:18:5 --> $DIR/suggest-where-clause.rs:18:18
| |
LL | <u64 as From<<T as Iterator>::Item>>::from; LL | <u64 as From<<T as Iterator>::Item>>::from;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64` | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<<T as Iterator>::Item>` is not implemented for `u64`
| |
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
| |
@ -60,10 +60,10 @@ LL | fn check<T: Iterator, U: ?Sized>() where u64: From<<T as Iterator>::Item> {
| ++++++++++++++++++++++++++++++++++++++ | ++++++++++++++++++++++++++++++++++++++
error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied error[E0277]: the trait bound `Misc<_>: From<T>` is not satisfied
--> $DIR/suggest-where-clause.rs:23:5 --> $DIR/suggest-where-clause.rs:23:22
| |
LL | <Misc<_> as From<T>>::from; LL | <Misc<_> as From<T>>::from;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<T>` is not implemented for `Misc<_>` | ^ the trait `From<T>` is not implemented for `Misc<_>`
error[E0277]: the size for values of type `[T]` cannot be known at compilation time error[E0277]: the size for values of type `[T]` cannot be known at compilation time
--> $DIR/suggest-where-clause.rs:28:20 --> $DIR/suggest-where-clause.rs:28:20