diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index ecc7b170818d2..b1c8f750d65d4 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -267,7 +267,7 @@ fn visit_implementation_of_coerce_shared(checker: &Checker<'_>) -> Result<(), Er // Just compute this for the side-effects, in particular reporting // errors; other parts of the code may demand it for the info of // course. - coerce_shared_info(tcx, impl_did) + tcx.ensure_result().coerce_shared_info(impl_did) } fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool { diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 8391a47902e42..d23f1ddaa790d 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -140,7 +140,7 @@ fn enforce_empty_impls_for_marker_traits( /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]. pub(crate) fn provide(providers: &mut Providers) { - use self::builtin::coerce_unsized_info; + use self::builtin::{coerce_shared_info, coerce_unsized_info}; use self::inherent_impls::{ crate_incoherent_impls, crate_inherent_impls, crate_inherent_impls_validity_check, inherent_impls, @@ -155,6 +155,7 @@ pub(crate) fn provide(providers: &mut Providers) { inherent_impls, crate_inherent_impls_validity_check, crate_inherent_impls_overlap_check, + coerce_shared_info, coerce_unsized_info, orphan_check_impl, ..*providers diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 986e127ac6b8b..ca4348fd51fa0 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -997,10 +997,22 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.tcx, ObligationCause::dummy(), self.param_env, - ty::Binder::dummy(coerce_shared_trait_ref), + coerce_shared_trait_ref, ); + + let mut selcx = traits::SelectionContext::new(self); + let Ok(Some(impl_source)) = selcx.select(&obligation) else { + return Err(TypeError::Mismatch); + }; + if let ImplSource::UserDefined(impl_source) = &impl_source + && let Some(impl_def_id) = impl_source.impl_def_id.as_local() + && let Err(guar) = self.tcx.ensure_result().coerce_shared_info(impl_def_id) + { + self.fcx.set_tainted_by_errors(guar); + } + let ocx = ObligationCtxt::new(&self.infcx); - ocx.register_obligation(obligation); + ocx.register_obligations(impl_source.nested_obligations()); let errs = ocx.evaluate_obligations_error_on_ambiguity(); if errs.is_empty() { Ok(InferOk { diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index cbd54ec959c6a..241c3296710e0 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -1205,6 +1205,10 @@ rustc_queries! { separate_provide_extern } + query coerce_shared_info(key: LocalDefId) -> Result<(), ErrorGuaranteed> { + desc { "computing CoerceShared info for `{}`", tcx.def_path_str(key) } + } + query typeck_root(key: LocalDefId) -> &'tcx ty::TypeckResults<'tcx> { desc { "type-checking `{}`", tcx.def_path_str(key) } cache_on_disk diff --git a/tests/crashes/reborrow/coerce-shared-alias-projection.rs b/tests/ui/reborrow/coerce-shared-alias-projection.rs similarity index 89% rename from tests/crashes/reborrow/coerce-shared-alias-projection.rs rename to tests/ui/reborrow/coerce-shared-alias-projection.rs index 8497455de921a..d7185c6dc7324 100644 --- a/tests/crashes/reborrow/coerce-shared-alias-projection.rs +++ b/tests/ui/reborrow/coerce-shared-alias-projection.rs @@ -1,4 +1,5 @@ -//@ known-bug: unknown +// Alias and projection fields in invalid multi-field `CoerceShared` impls must not cause an ICE. + #![feature(reborrow)] #![allow(dead_code)] @@ -62,6 +63,7 @@ impl<'a, T> Clone for OuterAliasRef<'a, T> { impl<'a, T> Copy for OuterAliasRef<'a, T> {} impl<'a, T> CoerceShared> for OuterMut<'a, T> {} +//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced struct OuterProjectionRef<'a, T: 'a> { inner: ProjectedInnerRef<'a, T>, @@ -77,6 +79,7 @@ impl<'a, T: 'a> Clone for OuterProjectionRef<'a, T> { impl<'a, T: 'a> Copy for OuterProjectionRef<'a, T> {} impl<'a, T: 'a> CoerceShared> for OuterMut<'a, T> {} +//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced fn read_alias<'a>(outer: OuterAliasRef<'a, u32>) -> (&'a u32, usize) { (outer.inner.value, outer.tag) diff --git a/tests/ui/reborrow/coerce-shared-alias-projection.stderr b/tests/ui/reborrow/coerce-shared-alias-projection.stderr new file mode 100644 index 0000000000000..ec2ef16c1ef97 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-alias-projection.stderr @@ -0,0 +1,14 @@ +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-alias-projection.rs:65:13 + | +LL | impl<'a, T> CoerceShared> for OuterMut<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-alias-projection.rs:81:17 + | +LL | impl<'a, T: 'a> CoerceShared> for OuterMut<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/crashes/reborrow/coerce-shared-different-layout.rs b/tests/ui/reborrow/coerce-shared-different-layout.rs similarity index 81% rename from tests/crashes/reborrow/coerce-shared-different-layout.rs rename to tests/ui/reborrow/coerce-shared-different-layout.rs index ad285bf0130d1..db47167f126ae 100644 --- a/tests/crashes/reborrow/coerce-shared-different-layout.rs +++ b/tests/ui/reborrow/coerce-shared-different-layout.rs @@ -1,4 +1,5 @@ -//@ known-bug: unknown +// `CoerceShared` impls with incompatible data-field layouts must be rejected without an ICE. + #![feature(reborrow)] #![allow(dead_code)] @@ -27,6 +28,7 @@ impl<'a, T> Clone for ImbrisRef<'a, T> { impl<'a, T> Copy for ImbrisRef<'a, T> {} impl<'a, T> CoerceShared> for ImbrisMut<'a, T> {} +//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced fn ptr(value: ImbrisRef<'_, i32>) -> NonNull { value.ptr diff --git a/tests/ui/reborrow/coerce-shared-different-layout.stderr b/tests/ui/reborrow/coerce-shared-different-layout.stderr new file mode 100644 index 0000000000000..b5d6d8b83794e --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-different-layout.stderr @@ -0,0 +1,8 @@ +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-different-layout.rs:30:13 + | +LL | impl<'a, T> CoerceShared> for ImbrisMut<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.current.stderr b/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.current.stderr new file mode 100644 index 0000000000000..f477a473e7d2c --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.current.stderr @@ -0,0 +1,8 @@ +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-invalid-consteval-issue-158149.rs:19:10 + | +LL | impl<'a> CoerceShared> for MyMut<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.next.stderr b/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.next.stderr new file mode 100644 index 0000000000000..f477a473e7d2c --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.next.stderr @@ -0,0 +1,8 @@ +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-invalid-consteval-issue-158149.rs:19:10 + | +LL | impl<'a> CoerceShared> for MyMut<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.rs b/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.rs new file mode 100644 index 0000000000000..8368a2028f7ce --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.rs @@ -0,0 +1,29 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +// Invalid `CoerceShared` impls must taint type checking before CTFE. + +#![feature(const_block_items)] +#![feature(reborrow)] +#![allow(dead_code, unused_variables)] + +use std::marker::CoerceShared; + +struct MyMut<'a>(&'a u8); +#[derive(Copy, Clone)] +struct MyRef<'a> { + x: &'a (), + y: &'a (), +} + +impl<'a> CoerceShared> for MyMut<'a> {} +//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + +const { + let value = 1; + consume(MyMut(&value)); +} + +const fn consume(_: MyRef<'_>) {} + +fn main() {} diff --git a/tests/crashes/reborrow/coerce-shared-marker-no-target-lifetime.rs b/tests/ui/reborrow/coerce-shared-marker-no-target-lifetime.rs similarity index 66% rename from tests/crashes/reborrow/coerce-shared-marker-no-target-lifetime.rs rename to tests/ui/reborrow/coerce-shared-marker-no-target-lifetime.rs index 3cdbf515371f2..f5ef3827470ca 100644 --- a/tests/crashes/reborrow/coerce-shared-marker-no-target-lifetime.rs +++ b/tests/ui/reborrow/coerce-shared-marker-no-target-lifetime.rs @@ -1,6 +1,7 @@ -//@ known-bug: unknown //@ edition: 2024 +// A `CoerceShared` target without a reborrowed lifetime must be rejected without an ICE. + #![feature(reborrow)] use std::marker::{CoerceShared, PhantomData, Reborrow}; @@ -10,12 +11,11 @@ struct CustomMarkerRef; impl<'a> Reborrow for CustomMarker<'a> {} impl<'a> CoerceShared for CustomMarker<'a> {} -//~^ ERROR +//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced fn method(_a: CustomMarkerRef) {} fn main() { let a = CustomMarker(PhantomData); method(a); - //~^ ERROR } diff --git a/tests/ui/reborrow/coerce-shared-marker-no-target-lifetime.stderr b/tests/ui/reborrow/coerce-shared-marker-no-target-lifetime.stderr new file mode 100644 index 0000000000000..bc0addd2f1cd6 --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-marker-no-target-lifetime.stderr @@ -0,0 +1,8 @@ +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-marker-no-target-lifetime.rs:13:10 + | +LL | impl<'a> CoerceShared for CustomMarker<'a> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/crashes/reborrow/coerce-shared-multi-field.rs b/tests/ui/reborrow/coerce-shared-multi-field.rs similarity index 86% rename from tests/crashes/reborrow/coerce-shared-multi-field.rs rename to tests/ui/reborrow/coerce-shared-multi-field.rs index 3bf5b64064d4a..519c5306a848c 100644 --- a/tests/crashes/reborrow/coerce-shared-multi-field.rs +++ b/tests/ui/reborrow/coerce-shared-multi-field.rs @@ -1,4 +1,5 @@ -//@ known-bug: unknown +// Multi-field `CoerceShared` impls must be rejected without reaching malformed reborrow MIR. + #![feature(reborrow)] #![allow(dead_code)] @@ -34,6 +35,7 @@ impl<'a, T> Clone for MatRef<'a, T> { impl<'a, T> Copy for MatRef<'a, T> {} impl<'a, T> CoerceShared> for MatMut<'a, T> {} +//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced fn dims(mat: MatRef<'_, T>) -> (usize, usize, usize, usize) { let _ = mat.ptr; diff --git a/tests/ui/reborrow/coerce-shared-multi-field.stderr b/tests/ui/reborrow/coerce-shared-multi-field.stderr new file mode 100644 index 0000000000000..61c2a8f4c6a0e --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-multi-field.stderr @@ -0,0 +1,8 @@ +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-multi-field.rs:37:13 + | +LL | impl<'a, T> CoerceShared> for MatMut<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/crashes/reborrow/coerce-shared-nested.rs b/tests/ui/reborrow/coerce-shared-nested.rs similarity index 86% rename from tests/crashes/reborrow/coerce-shared-nested.rs rename to tests/ui/reborrow/coerce-shared-nested.rs index a916dde881ec5..c3f40be89fdad 100644 --- a/tests/crashes/reborrow/coerce-shared-nested.rs +++ b/tests/ui/reborrow/coerce-shared-nested.rs @@ -1,4 +1,5 @@ -//@ known-bug: unknown +// Invalid nested multi-field `CoerceShared` impls must be rejected without an ICE. + #![feature(reborrow)] #![allow(dead_code)] @@ -45,6 +46,7 @@ impl<'a, T> Clone for OuterRef<'a, T> { impl<'a, T> Copy for OuterRef<'a, T> {} impl<'a, T> CoerceShared> for OuterMut<'a, T> {} +//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced fn get<'a>(outer: OuterRef<'a, i32>) -> (&'a i32, usize) { (outer.inner.value, outer.tag) diff --git a/tests/ui/reborrow/coerce-shared-nested.stderr b/tests/ui/reborrow/coerce-shared-nested.stderr new file mode 100644 index 0000000000000..1a435bb3c9bda --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-nested.stderr @@ -0,0 +1,8 @@ +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-nested.rs:48:13 + | +LL | impl<'a, T> CoerceShared> for OuterMut<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.rs b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.rs index ade1890068d76..fb4eb86781a0e 100644 --- a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.rs +++ b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.rs @@ -47,7 +47,6 @@ fn main() { let shared = get(wrapped); *wrapped.extra.value = 3; - //~^ ERROR cannot assign to `*wrapped.extra.value` because it is borrowed let _ = shared; } diff --git a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.stderr b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.stderr index d718103c80e7f..3610bcea23b64 100644 --- a/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.stderr +++ b/tests/ui/reborrow/coerce-shared-omitted-reborrow-field-locked.stderr @@ -4,18 +4,5 @@ error: implementing `CoerceShared` does not allow multiple lifetimes or fields t LL | impl<'a, T> CoerceShared> for OmitMut<'a, T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0506]: cannot assign to `*wrapped.extra.value` because it is borrowed - --> $DIR/coerce-shared-omitted-reborrow-field-locked.rs:49:5 - | -LL | let shared = get(wrapped); - | ------- `*wrapped.extra.value` is borrowed here -LL | -LL | *wrapped.extra.value = 3; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | `*wrapped.extra.value` is assigned to here but it was already borrowed - | borrow later used here - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0506`. diff --git a/tests/crashes/reborrow/coerce-shared-tuple-phantom-position.rs b/tests/ui/reborrow/coerce-shared-tuple-phantom-position.rs similarity index 91% rename from tests/crashes/reborrow/coerce-shared-tuple-phantom-position.rs rename to tests/ui/reborrow/coerce-shared-tuple-phantom-position.rs index 0ada68c9c20f7..5be596ccd6bd9 100644 --- a/tests/crashes/reborrow/coerce-shared-tuple-phantom-position.rs +++ b/tests/ui/reborrow/coerce-shared-tuple-phantom-position.rs @@ -1,4 +1,5 @@ -//@ known-bug: unknown +// `PhantomData` positions must not hide invalid multi-field `CoerceShared` impls or cause an ICE. + #![feature(reborrow)] #![allow(dead_code)] @@ -56,6 +57,7 @@ impl<'a, T, U> Clone for InterleavedRef<'a, T, U> { impl<'a, T, U> Copy for InterleavedRef<'a, T, U> {} impl<'a, T, U> CoerceShared> for InterleavedMut<'a, T, U> {} +//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced fn read_source_leading<'a>(value: SourceLeadingRef<'a, i32>) -> &'a i32 { value.0 diff --git a/tests/ui/reborrow/coerce-shared-tuple-phantom-position.stderr b/tests/ui/reborrow/coerce-shared-tuple-phantom-position.stderr new file mode 100644 index 0000000000000..3e4a4e52e473b --- /dev/null +++ b/tests/ui/reborrow/coerce-shared-tuple-phantom-position.stderr @@ -0,0 +1,8 @@ +error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced + --> $DIR/coerce-shared-tuple-phantom-position.rs:59:16 + | +LL | impl<'a, T, U> CoerceShared> for InterleavedMut<'a, T, U> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/crashes/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.rs b/tests/ui/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.rs similarity index 66% rename from tests/crashes/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.rs rename to tests/ui/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.rs index 59e76ec36ab90..153bb12d5a2ba 100644 --- a/tests/crashes/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.rs +++ b/tests/ui/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.rs @@ -1,4 +1,4 @@ -//@ known-bug: unknown +// An invalid `CoerceShared` field relation must report an error instead of causing an ICE. #![feature(reborrow)] @@ -9,9 +9,9 @@ struct CustomMut<'a, T>(&'a mut T); impl<'a, T> Reborrow for CustomMut<'a, T> {} struct CustomRef<'a, T>(&'a CustomMut<'a, T>); -//~^ ERROR impl<'a, T> CoerceShared> for CustomMut<'a, T> {} +//~^ ERROR the trait bound `&'a mut T: CoerceShared<&'a CustomMut<'a, T>>` is not satisfied fn method(_a: CustomRef<'_, ()>) {} diff --git a/tests/ui/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.stderr b/tests/ui/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.stderr new file mode 100644 index 0000000000000..7eb8d9905cc2b --- /dev/null +++ b/tests/ui/reborrow/corrected-field-mismatch-coerce-shared-issue-156315.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `&'a mut T: CoerceShared<&'a CustomMut<'a, T>>` is not satisfied + --> $DIR/corrected-field-mismatch-coerce-shared-issue-156315.rs:13:1 + | +LL | impl<'a, T> CoerceShared> for CustomMut<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `CoerceShared<&'a CustomMut<'a, T>>` is not implemented for `&'a mut T` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/crashes/reborrow/missing-generic-args-coerce-shared-issue-156315.rs b/tests/ui/reborrow/missing-generic-args-coerce-shared-issue-156315.rs similarity index 86% rename from tests/crashes/reborrow/missing-generic-args-coerce-shared-issue-156315.rs rename to tests/ui/reborrow/missing-generic-args-coerce-shared-issue-156315.rs index d365986901fe3..18a0cb5eb05cb 100644 --- a/tests/crashes/reborrow/missing-generic-args-coerce-shared-issue-156315.rs +++ b/tests/ui/reborrow/missing-generic-args-coerce-shared-issue-156315.rs @@ -1,4 +1,5 @@ -//@ known-bug: unknown +// Missing generic arguments in a `CoerceShared` field must not cause an additional ICE. + #![feature(reborrow)] // Malformed no-ICE regression: this intentionally keeps the missing generic arguments from the @@ -14,7 +15,6 @@ impl<'a, T> CoerceShared> for CustomMut<'a, T> {} struct CustomRef<'a, T>(&'a CustomMut); //~^ ERROR //~| ERROR -//~| ERROR fn method(_a: CustomRef<'_, ()>) {} diff --git a/tests/ui/reborrow/missing-generic-args-coerce-shared-issue-156315.stderr b/tests/ui/reborrow/missing-generic-args-coerce-shared-issue-156315.stderr new file mode 100644 index 0000000000000..01adc64ab2520 --- /dev/null +++ b/tests/ui/reborrow/missing-generic-args-coerce-shared-issue-156315.stderr @@ -0,0 +1,31 @@ +error[E0106]: missing lifetime specifier + --> $DIR/missing-generic-args-coerce-shared-issue-156315.rs:15:29 + | +LL | struct CustomRef<'a, T>(&'a CustomMut); + | ^^^^^^^^^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | struct CustomRef<'a, T>(&'a CustomMut<'a>); + | ++++ + +error[E0107]: missing generics for struct `CustomMut` + --> $DIR/missing-generic-args-coerce-shared-issue-156315.rs:15:29 + | +LL | struct CustomRef<'a, T>(&'a CustomMut); + | ^^^^^^^^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> $DIR/missing-generic-args-coerce-shared-issue-156315.rs:10:8 + | +LL | struct CustomMut<'a, T>(&'a mut T); + | ^^^^^^^^^ - +help: add missing generic argument + | +LL | struct CustomRef<'a, T>(&'a CustomMut); + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0106, E0107. +For more information about an error, try `rustc --explain E0106`.