Modify wording
This commit is contained in:
parent
d0d30b0a3e
commit
2b35247d7a
5 changed files with 84 additions and 20 deletions
|
@ -2,15 +2,17 @@
|
||||||
|
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||||
use crate::infer::{Subtype, ValuePairs};
|
use crate::infer::{Subtype, TyCtxtInferExt, ValuePairs};
|
||||||
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
|
use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_errors::ErrorReported;
|
use rustc_errors::ErrorReported;
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_hir::intravisit::Visitor;
|
||||||
use rustc_hir::ItemKind;
|
use rustc_hir::ItemKind;
|
||||||
use rustc_middle::ty::error::ExpectedFound;
|
use rustc_middle::ty::error::ExpectedFound;
|
||||||
use rustc_middle::ty::fold::TypeFoldable;
|
use rustc_middle::ty::fold::TypeFoldable;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
|
@ -59,8 +61,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
.tcx()
|
.tcx()
|
||||||
.sess
|
.sess
|
||||||
.struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
|
.struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
|
||||||
err.span_label(sp, &format!("found {:?}", found));
|
err.span_label(sp, &format!("found `{:?}`", found));
|
||||||
err.span_label(trait_sp, &format!("expected {:?}", expected));
|
err.span_label(trait_sp, &format!("expected `{:?}`", expected));
|
||||||
let trait_fn_sig = tcx.fn_sig(trait_def_id);
|
let trait_fn_sig = tcx.fn_sig(trait_def_id);
|
||||||
|
|
||||||
// Check the `trait`'s method's output to look for type parameters that might have
|
// Check the `trait`'s method's output to look for type parameters that might have
|
||||||
|
@ -73,7 +75,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
struct AssocTypeFinder(FxIndexSet<ty::ParamTy>);
|
struct AssocTypeFinder(FxIndexSet<ty::ParamTy>);
|
||||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for AssocTypeFinder {
|
impl<'tcx> ty::fold::TypeVisitor<'tcx> for AssocTypeFinder {
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
|
||||||
debug!("assoc type finder ty {:?} {:?}", ty, ty.kind);
|
|
||||||
if let ty::Param(param) = ty.kind {
|
if let ty::Param(param) = ty.kind {
|
||||||
self.0.insert(param);
|
self.0.insert(param);
|
||||||
}
|
}
|
||||||
|
@ -86,18 +87,40 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
let parent_id = tcx.hir().get_parent_item(id);
|
let parent_id = tcx.hir().get_parent_item(id);
|
||||||
let trait_item = tcx.hir().expect_item(parent_id);
|
let trait_item = tcx.hir().expect_item(parent_id);
|
||||||
if let ItemKind::Trait(_, _, generics, _, _) = &trait_item.kind {
|
if let ItemKind::Trait(_, _, generics, _, _) = &trait_item.kind {
|
||||||
for param_ty in visitor.0 {
|
for param_ty in &visitor.0 {
|
||||||
if let Some(generic) = generics.get_named(param_ty.name) {
|
if let Some(generic) = generics.get_named(param_ty.name) {
|
||||||
err.span_label(generic.span, &format!(
|
err.span_label(
|
||||||
"for `impl` items to implement the method, this type parameter might \
|
generic.span,
|
||||||
need a lifetime restriction like `{}: 'a`",
|
"this type parameter might not have a lifetime compatible with the \
|
||||||
param_ty.name,
|
`impl`",
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the span of all the used type parameters in the method.
|
||||||
|
let assoc_item = self.tcx().associated_item(trait_def_id);
|
||||||
|
let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
|
||||||
|
match assoc_item.kind {
|
||||||
|
ty::AssocKind::Method => {
|
||||||
|
let hir = self.tcx().hir();
|
||||||
|
if let Some(hir_id) = hir.as_local_hir_id(assoc_item.def_id) {
|
||||||
|
if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
|
||||||
|
visitor.visit_fn_decl(decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
for span in visitor.types {
|
||||||
|
err.span_label(
|
||||||
|
span,
|
||||||
|
"you might want to borrow this type parameter in the trait to make it match the \
|
||||||
|
`impl`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some((expected, found)) = tcx
|
if let Some((expected, found)) = tcx
|
||||||
.infer_ctxt()
|
.infer_ctxt()
|
||||||
.enter(|infcx| infcx.expected_found_str_ty(&ExpectedFound { expected, found }))
|
.enter(|infcx| infcx.expected_found_str_ty(&ExpectedFound { expected, found }))
|
||||||
|
@ -116,3 +139,41 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TypeParamSpanVisitor<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
types: Vec<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
|
||||||
|
type Map = hir::intravisit::Map<'tcx>;
|
||||||
|
|
||||||
|
fn nested_visit_map<'this>(
|
||||||
|
&'this mut self,
|
||||||
|
) -> hir::intravisit::NestedVisitorMap<'this, Self::Map> {
|
||||||
|
hir::intravisit::NestedVisitorMap::OnlyBodies(&self.tcx.hir())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
|
||||||
|
match arg.kind {
|
||||||
|
hir::TyKind::Slice(_) | hir::TyKind::Tup(_) | hir::TyKind::Array(..) => {
|
||||||
|
hir::intravisit::walk_ty(self, arg);
|
||||||
|
}
|
||||||
|
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
|
||||||
|
[segment]
|
||||||
|
if segment
|
||||||
|
.res
|
||||||
|
.map(|res| match res {
|
||||||
|
hir::def::Res::Def(hir::def::DefKind::TyParam, _) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.unwrap_or(false) =>
|
||||||
|
{
|
||||||
|
self.types.push(path.span);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@ error: `impl` item signature doesn't match `trait` item signature
|
||||||
--> $DIR/mismatched_trait_impl-2.rs:8:5
|
--> $DIR/mismatched_trait_impl-2.rs:8:5
|
||||||
|
|
|
|
||||||
LL | fn deref(&self) -> &dyn Trait {
|
LL | fn deref(&self) -> &dyn Trait {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Struct) -> &dyn Trait`
|
||||||
|
|
|
|
||||||
::: $SRC_DIR/libcore/ops/deref.rs:LL:COL
|
::: $SRC_DIR/libcore/ops/deref.rs:LL:COL
|
||||||
|
|
|
|
||||||
LL | fn deref(&self) -> &Self::Target;
|
LL | fn deref(&self) -> &Self::Target;
|
||||||
| --------------------------------- expected fn(&Struct) -> &(dyn Trait + 'static)
|
| --------------------------------- expected `fn(&Struct) -> &(dyn Trait + 'static)`
|
||||||
|
|
|
|
||||||
= note: expected `fn(&Struct) -> &(dyn Trait + 'static)`
|
= note: expected `fn(&Struct) -> &(dyn Trait + 'static)`
|
||||||
found `fn(&Struct) -> &dyn Trait`
|
found `fn(&Struct) -> &dyn Trait`
|
||||||
|
|
|
@ -2,10 +2,10 @@ error: `impl` item signature doesn't match `trait` item signature
|
||||||
--> $DIR/mismatched_trait_impl.rs:9:5
|
--> $DIR/mismatched_trait_impl.rs:9:5
|
||||||
|
|
|
|
||||||
LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
|
LL | fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
|
||||||
| ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
|
| ---------------------------------------------- expected `fn(&i32, &'a u32, &u32) -> &'a u32`
|
||||||
...
|
...
|
||||||
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
|
LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &u32, &u32) -> &u32`
|
||||||
|
|
|
|
||||||
= note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
|
= note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
|
||||||
found `fn(&i32, &u32, &u32) -> &u32`
|
found `fn(&i32, &u32, &u32) -> &u32`
|
||||||
|
|
|
@ -2,10 +2,10 @@ error: `impl` item signature doesn't match `trait` item signature
|
||||||
--> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5
|
--> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5
|
||||||
|
|
|
|
||||||
LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
|
LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
|
||||||
| ------------------------------------------- expected fn(&i32, &'a i32) -> &'a i32
|
| ------------------------------------------- expected `fn(&i32, &'a i32) -> &'a i32`
|
||||||
...
|
...
|
||||||
LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
|
LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &i32) -> &i32
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &i32) -> &i32`
|
||||||
|
|
|
|
||||||
= note: expected `fn(&i32, &'a i32) -> &'a i32`
|
= note: expected `fn(&i32, &'a i32) -> &'a i32`
|
||||||
found `fn(&i32, &i32) -> &i32`
|
found `fn(&i32, &i32) -> &i32`
|
||||||
|
|
|
@ -2,12 +2,15 @@ error: `impl` item signature doesn't match `trait` item signature
|
||||||
--> $DIR/trait-param-without-lifetime-constraint.rs:14:5
|
--> $DIR/trait-param-without-lifetime-constraint.rs:14:5
|
||||||
|
|
|
|
||||||
LL | pub trait HaveRelationship<To> {
|
LL | pub trait HaveRelationship<To> {
|
||||||
| -- for `impl` items to implement the method, this type parameter might need a lifetime restriction like `To: 'a`
|
| -- this type parameter might not have a lifetime compatible with the `impl`
|
||||||
LL | fn get_relation(&self) -> To;
|
LL | fn get_relation(&self) -> To;
|
||||||
| ----------------------------- expected fn(&Article) -> &ProofReader
|
| -----------------------------
|
||||||
|
| | |
|
||||||
|
| | you might want to borrow this type parameter in the trait to make it match the `impl`
|
||||||
|
| expected `fn(&Article) -> &ProofReader`
|
||||||
...
|
...
|
||||||
LL | fn get_relation(&self) -> &ProofReader {
|
LL | fn get_relation(&self) -> &ProofReader {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Article) -> &ProofReader
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Article) -> &ProofReader`
|
||||||
|
|
|
|
||||||
= note: expected `fn(&Article) -> &ProofReader`
|
= note: expected `fn(&Article) -> &ProofReader`
|
||||||
found `fn(&Article) -> &ProofReader`
|
found `fn(&Article) -> &ProofReader`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue