diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 8f353cae0bebf..7a14859088188 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -477,7 +477,7 @@ pub enum RegionOriginNote<'a> { impl Subdiagnostic for RegionOriginNote<'_> { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - let mut label_or_note = |span, msg: DiagMessage| { + let label_or_note = |diag: &mut Diag<'_, G>, span, msg: DiagMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span); @@ -491,22 +491,26 @@ impl Subdiagnostic for RegionOriginNote<'_> { }; match self { RegionOriginNote::Plain { span, msg } => { - label_or_note(span, msg); + label_or_note(diag, span, msg); } RegionOriginNote::WithName { span, msg, name, continues } => { - label_or_note(span, msg); diag.arg("name", name); diag.arg("continues", continues); + label_or_note(diag, span, msg); } RegionOriginNote::WithRequirement { span, requirement, expected_found: Some((expected, found)), } => { - label_or_note( - span, - msg!( - "...so that the {$requirement -> + // `RegionOriginNote` can appear multiple times on one diagnostic with different + // `requirement` values. Scope args per-note and eagerly translate to avoid + // cross-note arg collisions. + // See https://github.com/rust-lang/rust/issues/143872 for details. + diag.store_args(); + diag.arg("requirement", requirement); + let msg = diag.eagerly_translate(msg!( + "...so that the {$requirement -> [method_compat] method type is compatible with trait [type_compat] associated type is compatible with trait [const_compat] const is compatible with trait @@ -519,9 +523,9 @@ impl Subdiagnostic for RegionOriginNote<'_> { [method_correct_type] method receiver has the correct type *[other] types are compatible }" - ), - ); - diag.arg("requirement", requirement); + )); + diag.restore_args(); + label_or_note(diag, span, msg); diag.note_expected_found("", expected, "", found); } @@ -529,10 +533,10 @@ impl Subdiagnostic for RegionOriginNote<'_> { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is // *terrible*. - label_or_note( - span, - msg!( - "...so that {$requirement -> + diag.store_args(); + diag.arg("requirement", requirement); + let msg = diag.eagerly_translate(msg!( + "...so that {$requirement -> [method_compat] method type is compatible with trait [type_compat] associated type is compatible with trait [const_compat] const is compatible with trait @@ -545,9 +549,9 @@ impl Subdiagnostic for RegionOriginNote<'_> { [method_correct_type] method receiver has the correct type *[other] types are compatible }" - ), - ); - diag.arg("requirement", requirement); + )); + diag.restore_args(); + label_or_note(diag, span, msg); } }; } diff --git a/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.rs b/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.rs new file mode 100644 index 0000000000000..5cf5dcc34d6d4 --- /dev/null +++ b/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.rs @@ -0,0 +1,23 @@ +//@ compile-flags: --crate-type=lib +// Regression test for https://github.com/rust-lang/rust/issues/143872 + +trait Project { + type Ty; +} + +impl Project for &'_ &'static () { + type Ty = (); +} + +trait Trait { + fn get<'s>(s: &'s str, _: ()) -> &'_ str; +} + +impl Trait for () { + fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + //~^ ERROR cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements + //~| ERROR mismatched types + //~| ERROR lifetime may not live long enough + s + } +} diff --git a/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.stderr b/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.stderr new file mode 100644 index 0000000000000..f6ae851430cd8 --- /dev/null +++ b/tests/ui/traits/compare-impl-item-conflicting-lifetime-requirements.stderr @@ -0,0 +1,55 @@ +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter 's in generic type due to conflicting requirements + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the lifetime `'s` as defined here... + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:13:12 + | +LL | fn get<'s>(s: &'s str, _: ()) -> &'_ str; + | ^^ +note: ...so that the method type is compatible with trait + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `fn(&'s _, ()) -> &'s _` + found `fn(&_, ()) -> &'static _` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the types are compatible + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `<&&() as Project>` + found `<&&'static () as Project>` + +error[E0308]: mismatched types + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:31 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected trait `<&&'s () as Project>` + found trait `<&&'static () as Project>` +note: the lifetime `'s` as defined here... + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:12 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^ + = note: ...does not necessarily outlive the static lifetime + +error: lifetime may not live long enough + --> $DIR/compare-impl-item-conflicting-lifetime-requirements.rs:17:5 + | +LL | fn get<'s>(s: &'s str, _: <&&'s () as Project>::Ty) -> &'static str { + | ^^^^^^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | lifetime `'s` defined here + | requires that `'s` must outlive `'static` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0803. +For more information about an error, try `rustc --explain E0308`.