1
Fork 0

Modify wording

This commit is contained in:
Esteban Küber 2020-02-16 17:59:29 -08:00
parent d0d30b0a3e
commit 2b35247d7a
5 changed files with 84 additions and 20 deletions

View file

@ -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);
}
_ => {}
},
_ => {}
}
}
}

View file

@ -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`

View file

@ -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`

View file

@ -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`

View file

@ -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`