Report diagnostics at the actually actionable site

This commit is contained in:
Oli Scherer 2022-09-23 08:00:02 +00:00
parent e237aaef25
commit 59e285ff34
5 changed files with 43 additions and 21 deletions

View File

@ -2314,7 +2314,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&self, &self,
generic_param_scope: LocalDefId, generic_param_scope: LocalDefId,
span: Span, span: Span,
mut origin: Option<SubregionOrigin<'tcx>>, origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>, bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>, sub: Region<'tcx>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> { ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
@ -2349,14 +2349,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
None None
} }
} }
GenericKind::Opaque(def_id, _substs) => {
// Avoid emitting a `... so that the type` message at the error site.
// It would be out of order for return position impl trait
origin = None;
// Make sure the lifetime suggestion is on the RPIT instead of proposing
// to add a bound for opaque types (which isn't possible)
Some((self.tcx.def_span(def_id).shrink_to_hi(), true))
}
_ => None, _ => None,
}; };

View File

@ -336,6 +336,7 @@ where
GenericKind::Opaque(def_id, substs), GenericKind::Opaque(def_id, substs),
def_id, def_id,
substs, substs,
true,
|ty| match *ty.kind() { |ty| match *ty.kind() {
ty::Opaque(def_id, substs) => (def_id, substs), ty::Opaque(def_id, substs) => (def_id, substs),
_ => bug!("expected only projection types from env, not {:?}", ty), _ => bug!("expected only projection types from env, not {:?}", ty),
@ -356,6 +357,7 @@ where
GenericKind::Projection(projection_ty), GenericKind::Projection(projection_ty),
projection_ty.item_def_id, projection_ty.item_def_id,
projection_ty.substs, projection_ty.substs,
false,
|ty| match ty.kind() { |ty| match ty.kind() {
ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs), ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs),
_ => bug!("expected only projection types from env, not {:?}", ty), _ => bug!("expected only projection types from env, not {:?}", ty),
@ -371,6 +373,7 @@ where
generic: GenericKind<'tcx>, generic: GenericKind<'tcx>,
def_id: DefId, def_id: DefId,
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
is_opaque: bool,
filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>), filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>),
) { ) {
// An optimization for a common case with opaque types. // An optimization for a common case with opaque types.
@ -437,7 +440,7 @@ where
// inference variables, we use a verify constraint instead of adding // inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition. // edges, which winds up enforcing the same condition.
let needs_infer = substs.needs_infer(); let needs_infer = substs.needs_infer();
if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer { if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) {
debug!("no declared bounds"); debug!("no declared bounds");
self.substs_must_outlive(substs, origin, region); self.substs_must_outlive(substs, origin, region);

View File

@ -0,0 +1,25 @@
// run-rustfix
pub trait Trait {}
pub struct Foo;
impl Trait for Foo {}
fn foo<'x, P>(
_post: P,
x: &'x Foo,
) -> &'x impl Trait {
x
}
pub fn bar<'t, T: 't>(
//~^ HELP: consider adding an explicit lifetime bound...
post: T,
x: &'t Foo,
) -> &'t impl Trait {
foo(post, x)
//~^ ERROR: the parameter type `T` may not live long enough
}
fn main() {}

View File

@ -1,23 +1,25 @@
trait Trait {} // run-rustfix
struct Foo; pub trait Trait {}
pub struct Foo;
impl Trait for Foo {} impl Trait for Foo {}
fn foo<'x, P>( fn foo<'x, P>(
post: P, _post: P,
x: &'x Foo, x: &'x Foo,
) -> &'x impl Trait { ) -> &'x impl Trait {
//~^ HELP: consider adding an explicit lifetime bound...
x x
} }
fn bar<'t, T>( pub fn bar<'t, T>(
//~^ HELP: consider adding an explicit lifetime bound...
post: T, post: T,
x: &'t Foo, x: &'t Foo,
) -> &'t impl Trait { ) -> &'t impl Trait {
foo(post, x) foo(post, x)
//~^ ERROR: the opaque type `foo<T>::{opaque#0}` may not live long enough //~^ ERROR: the parameter type `T` may not live long enough
} }
fn main() {} fn main() {}

View File

@ -1,13 +1,13 @@
error[E0309]: the opaque type `foo<T>::{opaque#0}` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/unactionable_diagnostic.rs:19:5 --> $DIR/unactionable_diagnostic.rs:21:5
| |
LL | foo(post, x) LL | foo(post, x)
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
| |
help: consider adding an explicit lifetime bound... help: consider adding an explicit lifetime bound...
| |
LL | ) -> &'x impl Trait + 't { LL | pub fn bar<'t, T: 't>(
| ++++ | ++++
error: aborting due to previous error error: aborting due to previous error