nice_region_error: Include lifetime placeholders in error output

As you can see in src/test/ui/traits/self-without-lifetime-constraint.stderr
you can get very confusing type names if you don't have this.

Fixes #87763
This commit is contained in:
Michael Howell 2021-09-30 22:47:41 -07:00
parent 01198792a6
commit 98ed5548d7
8 changed files with 76 additions and 39 deletions

View File

@ -9,10 +9,13 @@
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::RegionHighlightMode;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor};
use rustc_span::{MultiSpan, Span, Symbol}; use rustc_span::{MultiSpan, Span, Symbol};
use std::ops::ControlFlow;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`. /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> { pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
@ -69,6 +72,47 @@ fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id:
.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");
// Mark all unnamed regions in the type with a number.
// This diagnostic is called in response to lifetime errors, so be informative.
struct HighlightBuilder<'tcx> {
highlight: RegionHighlightMode,
tcx: TyCtxt<'tcx>,
counter: usize,
}
impl HighlightBuilder<'tcx> {
fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode {
let mut builder =
HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1, tcx };
builder.visit_ty(ty);
builder.highlight
}
}
impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder<'tcx> {
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
Some(self.tcx)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if !r.has_name() && self.counter <= 3 {
self.highlight.highlighting_region(r, self.counter);
self.counter += 1;
}
r.super_visit_with(self)
}
}
let expected_highlight = HighlightBuilder::build(self.tcx(), expected);
let expected = self
.infcx
.extract_inference_diagnostics_data(expected.into(), Some(expected_highlight))
.name;
let found_highlight = HighlightBuilder::build(self.tcx(), found);
let found =
self.infcx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
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));
@ -96,15 +140,8 @@ fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id:
); );
} }
if let Some((expected, found)) = err.note(&format!("expected `{}`\n found `{}`", expected, found));
self.infcx.expected_found_str_ty(ExpectedFound { expected, found })
{
// Highlighted the differences when showing the "expected/found" note.
err.note_expected_found(&"", expected, &"", found);
} else {
// This fallback shouldn't be necessary, but let's keep it in just in case.
err.note(&format!("expected `{}`\n found `{}`", expected, found));
}
err.span_help( err.span_help(
type_param_span, type_param_span,
"the lifetime requirements from the `impl` do not correspond to the requirements in \ "the lifetime requirements from the `impl` do not correspond to the requirements in \

View File

@ -2,15 +2,15 @@ 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(&'1 Struct) -> &'1 (dyn Trait + '1)`
| |
::: $SRC_DIR/core/src/ops/deref.rs:LL:COL ::: $SRC_DIR/core/src/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(&'1 Struct) -> &'1 (dyn Trait + 'static)`
| |
= note: expected `fn(&Struct) -> &(dyn Trait + 'static)` = note: expected `fn(&'1 Struct) -> &'1 (dyn Trait + 'static)`
found `fn(&Struct) -> &dyn Trait` found `fn(&'1 Struct) -> &'1 (dyn Trait + '1)`
= help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
= help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output

View File

@ -2,13 +2,13 @@ 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(&'1 i32, &'a u32, &'2 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(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32`
| |
= note: expected `fn(&i32, &'a u32, &u32) -> &'a u32` = note: expected `fn(&'1 i32, &'a u32, &'2 u32) -> &'a u32`
found `fn(&i32, &u32, &u32) -> &u32` found `fn(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32`
= help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
= help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output

View File

@ -2,13 +2,13 @@ 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(&'1 i32, &'a u32, &'2 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(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32`
| |
= note: expected `fn(&i32, &'a u32, &u32) -> &'a u32` = note: expected `fn(&'1 i32, &'a u32, &'2 u32) -> &'a u32`
found `fn(&i32, &u32, &u32) -> &u32` found `fn(&'1 i32, &'2 u32, &'3 u32) -> &'3 u32`
= help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
= help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output

View File

@ -2,13 +2,13 @@ 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(&'1 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(&'1 i32, &'1 i32) -> &'1 i32`
| |
= note: expected `fn(&i32, &'a i32) -> &'a i32` = note: expected `fn(&'1 i32, &'a i32) -> &'a i32`
found `fn(&i32, &i32) -> &i32` found `fn(&'1 i32, &'1 i32) -> &'1 i32`
= help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
= help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output

View File

@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature
--> $DIR/issue-75361-mismatched-impl.rs:18:3 --> $DIR/issue-75361-mismatched-impl.rs:18:3
| |
LL | fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType>>; LL | fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType>>;
| --------------------------------------------------------------------- expected `fn(&T) -> Box<(dyn MyTrait<Item = &T> + 'static)>` | --------------------------------------------------------------------- expected `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + 'static)>`
... ...
LL | fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType> + '_> { LL | fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType> + '_> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&T) -> Box<dyn MyTrait<Item = &T>>` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + '1)>`
| |
= note: expected `fn(&T) -> Box<(dyn MyTrait<Item = &T> + 'static)>` = note: expected `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + 'static)>`
found `fn(&T) -> Box<dyn MyTrait<Item = &T>>` found `fn(&'1 T) -> Box<(dyn MyTrait<Item = &'1 T> + '1)>`
help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
--> $DIR/issue-75361-mismatched-impl.rs:12:55 --> $DIR/issue-75361-mismatched-impl.rs:12:55
| |

View File

@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature
--> $DIR/param-without-lifetime-constraint.rs:14:5 --> $DIR/param-without-lifetime-constraint.rs:14:5
| |
LL | fn get_relation(&self) -> To; LL | fn get_relation(&self) -> To;
| ----------------------------- expected `fn(&Article) -> &ProofReader` | ----------------------------- expected `fn(&'1 Article) -> &'2 ProofReader`
... ...
LL | fn get_relation(&self) -> &ProofReader { LL | fn get_relation(&self) -> &ProofReader {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Article) -> &ProofReader` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader`
| |
= note: expected `fn(&Article) -> &ProofReader` = note: expected `fn(&'1 Article) -> &'2 ProofReader`
found `fn(&Article) -> &ProofReader` found `fn(&'1 Article) -> &'1 ProofReader`
help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
--> $DIR/param-without-lifetime-constraint.rs:10:31 --> $DIR/param-without-lifetime-constraint.rs:10:31
| |

View File

@ -2,13 +2,13 @@ error: `impl` item signature doesn't match `trait` item signature
--> $DIR/self-without-lifetime-constraint.rs:45:5 --> $DIR/self-without-lifetime-constraint.rs:45:5
| |
LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>; LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>;
| -------------------------------------------------------------------- expected `fn(ValueRef<'_>) -> Result<(&str, &&str), FromSqlError>` | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>`
... ...
LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'_>) -> Result<(&str, &&str), FromSqlError>` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>`
| |
= note: expected `fn(ValueRef<'_>) -> Result<(&str, &&str), _>` = note: expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>`
found `fn(ValueRef<'_>) -> Result<(&str, &&str), _>` found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>`
help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
--> $DIR/self-without-lifetime-constraint.rs:41:60 --> $DIR/self-without-lifetime-constraint.rs:41:60
| |