Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand Down
16 changes: 14 additions & 2 deletions compiler/rustc_hir_typeck/src/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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)]

Expand Down Expand Up @@ -62,6 +63,7 @@ impl<'a, T> Clone for OuterAliasRef<'a, T> {
impl<'a, T> Copy for OuterAliasRef<'a, T> {}

impl<'a, T> CoerceShared<OuterAliasRef<'a, T>> 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>,
Expand All @@ -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<OuterProjectionRef<'a, T>> 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)
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/reborrow/coerce-shared-alias-projection.stderr
Original file line number Diff line number Diff line change
@@ -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<OuterAliasRef<'a, T>> 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<OuterProjectionRef<'a, T>> for OuterMut<'a, T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

Original file line number Diff line number Diff line change
@@ -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)]

Expand Down Expand Up @@ -27,6 +28,7 @@ impl<'a, T> Clone for ImbrisRef<'a, T> {
impl<'a, T> Copy for ImbrisRef<'a, T> {}

impl<'a, T> CoerceShared<ImbrisRef<'a, T>> for ImbrisMut<'a, T> {}
//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced

fn ptr(value: ImbrisRef<'_, i32>) -> NonNull<i32> {
value.ptr
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/reborrow/coerce-shared-different-layout.stderr
Original file line number Diff line number Diff line change
@@ -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<ImbrisRef<'a, T>> for ImbrisMut<'a, T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -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<MyRef<'a>> for MyMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -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<MyRef<'a>> for MyMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

29 changes: 29 additions & 0 deletions tests/ui/reborrow/coerce-shared-invalid-consteval-issue-158149.rs
Original file line number Diff line number Diff line change
@@ -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<MyRef<'a>> 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() {}
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -10,12 +11,11 @@ struct CustomMarkerRef;

impl<'a> Reborrow for CustomMarker<'a> {}
impl<'a> CoerceShared<CustomMarkerRef> 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
}
Original file line number Diff line number Diff line change
@@ -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<CustomMarkerRef> for CustomMarker<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//@ known-bug: unknown
// Multi-field `CoerceShared` impls must be rejected without reaching malformed reborrow MIR.

#![feature(reborrow)]
#![allow(dead_code)]

Expand Down Expand Up @@ -34,6 +35,7 @@ impl<'a, T> Clone for MatRef<'a, T> {
impl<'a, T> Copy for MatRef<'a, T> {}

impl<'a, T> CoerceShared<MatRef<'a, T>> for MatMut<'a, T> {}
//~^ ERROR implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced

fn dims<T>(mat: MatRef<'_, T>) -> (usize, usize, usize, usize) {
let _ = mat.ptr;
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/reborrow/coerce-shared-multi-field.stderr
Original file line number Diff line number Diff line change
@@ -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<MatRef<'a, T>> for MatMut<'a, T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//@ known-bug: unknown
// Invalid nested multi-field `CoerceShared` impls must be rejected without an ICE.

#![feature(reborrow)]
#![allow(dead_code)]

Expand Down Expand Up @@ -45,6 +46,7 @@ impl<'a, T> Clone for OuterRef<'a, T> {
impl<'a, T> Copy for OuterRef<'a, T> {}

impl<'a, T> CoerceShared<OuterRef<'a, T>> 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)
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/reborrow/coerce-shared-nested.stderr
Original file line number Diff line number Diff line change
@@ -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<OuterRef<'a, T>> for OuterMut<'a, T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,5 @@ error: implementing `CoerceShared` does not allow multiple lifetimes or fields t
LL | impl<'a, T> CoerceShared<OmitRef<'a, T>> 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`.
Original file line number Diff line number Diff line change
@@ -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)]

Expand Down Expand Up @@ -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<InterleavedRef<'a, T, U>> 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
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/reborrow/coerce-shared-tuple-phantom-position.stderr
Original file line number Diff line number Diff line change
@@ -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<InterleavedRef<'a, T, U>> for InterleavedMut<'a, T, U> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//@ known-bug: unknown
// An invalid `CoerceShared` field relation must report an error instead of causing an ICE.

#![feature(reborrow)]

Expand All @@ -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<CustomRef<'a, T>> for CustomMut<'a, T> {}
//~^ ERROR the trait bound `&'a mut T: CoerceShared<&'a CustomMut<'a, T>>` is not satisfied

fn method(_a: CustomRef<'_, ()>) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<CustomRef<'a, T>> 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`.
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -14,7 +15,6 @@ impl<'a, T> CoerceShared<CustomRef<'a, T>> for CustomMut<'a, T> {}
struct CustomRef<'a, T>(&'a CustomMut);
//~^ ERROR
//~| ERROR
//~| ERROR

fn method(_a: CustomRef<'_, ()>) {}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<T>);
| +++

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0106, E0107.
For more information about an error, try `rustc --explain E0106`.
Loading