better ObligationCause for normalization errors in can_type_implement_copy
This commit is contained in:
parent
3d127e2040
commit
8ba74369c2
8 changed files with 71 additions and 22 deletions
|
@ -51,7 +51,7 @@ use rustc_span::source_map::Spanned;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{BytePos, InnerSpan, MultiSpan, Span};
|
use rustc_span::{BytePos, InnerSpan, MultiSpan, Span};
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
use rustc_trait_selection::traits::misc::can_type_implement_copy;
|
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
|
||||||
|
|
||||||
use crate::nonstandard_style::{method_context, MethodLateContext};
|
use crate::nonstandard_style::{method_context, MethodLateContext};
|
||||||
|
|
||||||
|
@ -764,7 +764,14 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
|
||||||
if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) {
|
if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if can_type_implement_copy(cx.tcx, param_env, ty).is_ok() {
|
if can_type_implement_copy(
|
||||||
|
cx.tcx,
|
||||||
|
param_env,
|
||||||
|
ty,
|
||||||
|
traits::ObligationCause::misc(item.span, item.hir_id()),
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| {
|
cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| {
|
||||||
lint.build(
|
lint.build(
|
||||||
"type could implement `Copy`; consider adding `impl \
|
"type could implement `Copy`; consider adding `impl \
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub fn can_type_implement_copy<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
self_type: Ty<'tcx>,
|
self_type: Ty<'tcx>,
|
||||||
|
cause: ObligationCause<'tcx>,
|
||||||
) -> Result<(), CopyImplementationError<'tcx>> {
|
) -> Result<(), CopyImplementationError<'tcx>> {
|
||||||
// FIXME: (@jroesch) float this code up
|
// FIXME: (@jroesch) float this code up
|
||||||
tcx.infer_ctxt().enter(|infcx| {
|
tcx.infer_ctxt().enter(|infcx| {
|
||||||
|
@ -49,9 +50,8 @@ pub fn can_type_implement_copy<'tcx>(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let span = tcx.def_span(field.did);
|
let span = tcx.def_span(field.did);
|
||||||
let cause = ObligationCause::dummy_with_span(span);
|
|
||||||
let ctx = traits::FulfillmentContext::new();
|
let ctx = traits::FulfillmentContext::new();
|
||||||
match traits::fully_normalize(&infcx, ctx, cause, param_env, ty) {
|
match traits::fully_normalize(&infcx, ctx, cause.clone(), param_env, ty) {
|
||||||
Ok(ty) => {
|
Ok(ty) => {
|
||||||
if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
|
if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
|
||||||
infringing.push(field);
|
infringing.push(field);
|
||||||
|
|
|
@ -74,7 +74,8 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||||
|
|
||||||
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
|
debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
|
||||||
|
|
||||||
match can_type_implement_copy(tcx, param_env, self_type) {
|
let cause = traits::ObligationCause::misc(span, impl_hir_id);
|
||||||
|
match can_type_implement_copy(tcx, param_env, self_type, cause) {
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(CopyImplementationError::InfrigingFields(fields)) => {
|
Err(CopyImplementationError::InfrigingFields(fields)) => {
|
||||||
let item = tcx.hir().expect_item(impl_did);
|
let item = tcx.hir().expect_item(impl_did);
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
//~^ ERROR the trait `Copy` may not be implemented for this type
|
//~^ ERROR the trait `Copy` may not be implemented for this type
|
||||||
|
//~| ERROR `i32` is not an iterator
|
||||||
struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
//~^ ERROR cannot find type `NotDefined` in this scope
|
//~^ ERROR cannot find type `NotDefined` in this scope
|
||||||
//~| ERROR cannot find type `NotDefined` in this scope
|
//~| ERROR cannot find type `NotDefined` in this scope
|
||||||
//~| ERROR cannot find type `N` in this scope
|
//~| ERROR cannot find type `N` in this scope
|
||||||
//~| ERROR cannot find type `N` in this scope
|
//~| ERROR cannot find type `N` in this scope
|
||||||
//~| ERROR `i32` is not an iterator
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
//~^ ERROR the trait `Copy` may not be implemented for this type
|
//~^ ERROR the trait `Copy` may not be implemented for this type
|
||||||
|
//~| ERROR `i32` is not an iterator
|
||||||
struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
//~^ ERROR cannot find type `NotDefined` in this scope
|
//~^ ERROR cannot find type `NotDefined` in this scope
|
||||||
//~| ERROR cannot find type `N` in this scope
|
//~| ERROR cannot find type `N` in this scope
|
||||||
//~| ERROR `i32` is not an iterator
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0412]: cannot find type `N` in this scope
|
error[E0412]: cannot find type `N` in this scope
|
||||||
--> $DIR/issue-50480.rs:3:12
|
--> $DIR/issue-50480.rs:4:12
|
||||||
|
|
|
|
||||||
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| -^ not found in this scope
|
| -^ not found in this scope
|
||||||
|
@ -7,13 +7,13 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| help: you might be missing a type parameter: `<N>`
|
| help: you might be missing a type parameter: `<N>`
|
||||||
|
|
||||||
error[E0412]: cannot find type `NotDefined` in this scope
|
error[E0412]: cannot find type `NotDefined` in this scope
|
||||||
--> $DIR/issue-50480.rs:3:15
|
--> $DIR/issue-50480.rs:4:15
|
||||||
|
|
|
|
||||||
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| ^^^^^^^^^^ not found in this scope
|
| ^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0412]: cannot find type `N` in this scope
|
error[E0412]: cannot find type `N` in this scope
|
||||||
--> $DIR/issue-50480.rs:3:12
|
--> $DIR/issue-50480.rs:4:12
|
||||||
|
|
|
|
||||||
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| -^ not found in this scope
|
| -^ not found in this scope
|
||||||
|
@ -21,7 +21,7 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| help: you might be missing a type parameter: `<N>`
|
| help: you might be missing a type parameter: `<N>`
|
||||||
|
|
||||||
error[E0412]: cannot find type `NotDefined` in this scope
|
error[E0412]: cannot find type `NotDefined` in this scope
|
||||||
--> $DIR/issue-50480.rs:3:15
|
--> $DIR/issue-50480.rs:4:15
|
||||||
|
|
|
|
||||||
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| - ^^^^^^^^^^ not found in this scope
|
| - ^^^^^^^^^^ not found in this scope
|
||||||
|
@ -29,7 +29,7 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| help: you might be missing a type parameter: `<NotDefined>`
|
| help: you might be missing a type parameter: `<NotDefined>`
|
||||||
|
|
||||||
error[E0412]: cannot find type `N` in this scope
|
error[E0412]: cannot find type `N` in this scope
|
||||||
--> $DIR/issue-50480.rs:12:18
|
--> $DIR/issue-50480.rs:13:18
|
||||||
|
|
|
|
||||||
LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| - ^
|
| - ^
|
||||||
|
@ -46,26 +46,27 @@ LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, Strin
|
||||||
| +++
|
| +++
|
||||||
|
|
||||||
error[E0412]: cannot find type `NotDefined` in this scope
|
error[E0412]: cannot find type `NotDefined` in this scope
|
||||||
--> $DIR/issue-50480.rs:12:21
|
--> $DIR/issue-50480.rs:13:21
|
||||||
|
|
|
|
||||||
LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| ^^^^^^^^^^ not found in this scope
|
| ^^^^^^^^^^ not found in this scope
|
||||||
|
|
||||||
error[E0277]: `i32` is not an iterator
|
error[E0277]: `i32` is not an iterator
|
||||||
--> $DIR/issue-50480.rs:3:27
|
--> $DIR/issue-50480.rs:1:17
|
||||||
|
|
|
|
||||||
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | #[derive(Clone, Copy)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
|
| ^^^^ `i32` is not an iterator
|
||||||
|
|
|
|
||||||
= help: the trait `Iterator` is not implemented for `i32`
|
= help: the trait `Iterator` is not implemented for `i32`
|
||||||
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
|
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
|
||||||
|
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0204]: the trait `Copy` may not be implemented for this type
|
error[E0204]: the trait `Copy` may not be implemented for this type
|
||||||
--> $DIR/issue-50480.rs:1:17
|
--> $DIR/issue-50480.rs:1:17
|
||||||
|
|
|
|
||||||
LL | #[derive(Clone, Copy)]
|
LL | #[derive(Clone, Copy)]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
LL |
|
...
|
||||||
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| -------- ------ this field does not implement `Copy`
|
| -------- ------ this field does not implement `Copy`
|
||||||
| |
|
| |
|
||||||
|
@ -74,20 +75,21 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0277]: `i32` is not an iterator
|
error[E0277]: `i32` is not an iterator
|
||||||
--> $DIR/issue-50480.rs:12:33
|
--> $DIR/issue-50480.rs:10:17
|
||||||
|
|
|
|
||||||
LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | #[derive(Clone, Copy)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator
|
| ^^^^ `i32` is not an iterator
|
||||||
|
|
|
|
||||||
= help: the trait `Iterator` is not implemented for `i32`
|
= help: the trait `Iterator` is not implemented for `i32`
|
||||||
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
|
= note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
|
||||||
|
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0204]: the trait `Copy` may not be implemented for this type
|
error[E0204]: the trait `Copy` may not be implemented for this type
|
||||||
--> $DIR/issue-50480.rs:10:17
|
--> $DIR/issue-50480.rs:10:17
|
||||||
|
|
|
|
||||||
LL | #[derive(Clone, Copy)]
|
LL | #[derive(Clone, Copy)]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
LL |
|
...
|
||||||
LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
|
||||||
| -------- ------ this field does not implement `Copy`
|
| -------- ------ this field does not implement `Copy`
|
||||||
| |
|
| |
|
||||||
|
|
25
src/test/ui/traits/copy-impl-cannot-normalize.rs
Normal file
25
src/test/ui/traits/copy-impl-cannot-normalize.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
trait TraitFoo {
|
||||||
|
type Bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Foo<T>
|
||||||
|
where
|
||||||
|
T: TraitFoo,
|
||||||
|
{
|
||||||
|
inner: T::Bar,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Clone for Foo<T>
|
||||||
|
where
|
||||||
|
T: TraitFoo,
|
||||||
|
T::Bar: Clone,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self { inner: self.inner.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Copy for Foo<T> {}
|
||||||
|
//~^ ERROR the trait bound `T: TraitFoo` is not satisfied
|
||||||
|
|
||||||
|
fn main() {}
|
14
src/test/ui/traits/copy-impl-cannot-normalize.stderr
Normal file
14
src/test/ui/traits/copy-impl-cannot-normalize.stderr
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
error[E0277]: the trait bound `T: TraitFoo` is not satisfied
|
||||||
|
--> $DIR/copy-impl-cannot-normalize.rs:22:1
|
||||||
|
|
|
||||||
|
LL | impl<T> Copy for Foo<T> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitFoo` is not implemented for `T`
|
||||||
|
|
|
||||||
|
help: consider restricting type parameter `T`
|
||||||
|
|
|
||||||
|
LL | impl<T: TraitFoo> Copy for Foo<T> {}
|
||||||
|
| ++++++++++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -199,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||||
let sugg = |diag: &mut DiagnosticBuilder<'_>| {
|
let sugg = |diag: &mut DiagnosticBuilder<'_>| {
|
||||||
if let ty::Adt(def, ..) = ty.kind() {
|
if let ty::Adt(def, ..) = ty.kind() {
|
||||||
if let Some(span) = cx.tcx.hir().span_if_local(def.did) {
|
if let Some(span) = cx.tcx.hir().span_if_local(def.did) {
|
||||||
if can_type_implement_copy(cx.tcx, cx.param_env, ty).is_ok() {
|
if can_type_implement_copy(cx.tcx, cx.param_env, ty, traits::ObligationCause::dummy_with_span(span)).is_ok() {
|
||||||
diag.span_help(span, "consider marking this type as `Copy`");
|
diag.span_help(span, "consider marking this type as `Copy`");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue