Suggest #[derive(Clone)]
This commit is contained in:
parent
f19488064a
commit
e1b340195a
6 changed files with 44 additions and 7 deletions
|
|
@ -14,7 +14,7 @@ use rustc_infer::infer;
|
|||
use rustc_infer::traits::{self, StatementAsExpression};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{
|
||||
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, Ty,
|
||||
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
|
||||
};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
use rustc_span::symbol::sym;
|
||||
|
|
@ -1278,15 +1278,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
&& !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..)))
|
||||
// Check that we're in fact trying to clone into the expected type
|
||||
&& self.can_coerce(*pointee_ty, expected_ty)
|
||||
&& let trait_ref = ty::Binder::dummy(self.tcx.mk_trait_ref(clone_trait_did, [expected_ty]))
|
||||
// And the expected type doesn't implement `Clone`
|
||||
&& !self.predicate_must_hold_considering_regions(&traits::Obligation::new(
|
||||
self.tcx,
|
||||
traits::ObligationCause::dummy(),
|
||||
self.param_env,
|
||||
ty::Binder::dummy(self.tcx.mk_trait_ref(
|
||||
clone_trait_did,
|
||||
[expected_ty],
|
||||
)),
|
||||
trait_ref,
|
||||
))
|
||||
{
|
||||
diag.span_note(
|
||||
|
|
@ -1305,6 +1303,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
diag,
|
||||
vec![(param.name.as_str(), "Clone", Some(clone_trait_did))].into_iter(),
|
||||
);
|
||||
} else {
|
||||
self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1848,7 +1848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.suggest_derive(err, &preds);
|
||||
}
|
||||
|
||||
fn suggest_derive(
|
||||
pub fn suggest_derive(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
unsatisfied_predicates: &[(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,14 @@ fn wat<T: Clone>(t: &T) -> T {
|
|||
t.clone() //~ ERROR E0308
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Foo;
|
||||
|
||||
fn wut(t: &Foo) -> Foo {
|
||||
t.clone() //~ ERROR E0308
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wat(&42);
|
||||
wut(&Foo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@ fn wat<T>(t: &T) -> T {
|
|||
t.clone() //~ ERROR E0308
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
fn wut(t: &Foo) -> Foo {
|
||||
t.clone() //~ ERROR E0308
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wat(&42);
|
||||
wut(&Foo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,24 @@ help: consider restricting type parameter `T`
|
|||
LL | fn wat<T: Clone>(t: &T) -> T {
|
||||
| +++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
|
||||
|
|
||||
LL | fn wut(t: &Foo) -> Foo {
|
||||
| --- expected `Foo` because of return type
|
||||
LL | t.clone()
|
||||
| ^^^^^^^^^ expected struct `Foo`, found `&Foo`
|
||||
|
|
||||
note: `Foo` does not implement `Clone`, so `&Foo` was cloned instead
|
||||
--> $DIR/clone-on-unconstrained-borrowed-type-param.rs:9:5
|
||||
|
|
||||
LL | t.clone()
|
||||
| ^
|
||||
help: consider annotating `Foo` with `#[derive(Clone)]`
|
||||
|
|
||||
LL | #[derive(Clone)]
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ note: `NotClone` does not implement `Clone`, so `&NotClone` was cloned instead
|
|||
|
|
||||
LL | nc.clone()
|
||||
| ^^
|
||||
help: consider annotating `NotClone` with `#[derive(Clone)]`
|
||||
|
|
||||
LL | #[derive(Clone)]
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue