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
428 changes: 331 additions & 97 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs

Large diffs are not rendered by default.

64 changes: 63 additions & 1 deletion compiler/rustc_hir_analysis/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1347,13 +1347,75 @@ pub(crate) struct CoerceSharedNotSingleLifetimeParam {
}

#[derive(Diagnostic)]
#[diag("implementing `{$trait_name}` does not allow multiple lifetimes or fields to be coerced")]
#[diag(
"implementing `{$trait_name}` requires exactly one lifetime argument in the reborrowed type"
)]
pub(crate) struct CoerceSharedMulti {
#[primary_span]
pub span: Span,
pub trait_name: &'static str,
}

#[derive(Diagnostic)]
#[diag(
"implementing `{$trait_name}` requires source and target to use the same reborrow lifetime \
argument"
)]
pub(crate) struct CoerceSharedLifetimeMismatch {
#[primary_span]
pub span: Span,
pub trait_name: &'static str,
}

#[derive(Diagnostic)]
#[diag(
"implementing `{$trait_name}` requires corresponding fields to match, \
be reborrowable with `CoerceShared`, or coerce a mutable reference field \
to a shared reference field"
)]
pub(crate) struct CoerceSharedFieldMismatch<'tcx> {
#[primary_span]
#[label("target field `{$target_name}` has type `{$target_ty}`")]
pub span: Span,
#[label("source field `{$source_name}` has type `{$source_ty}`")]
pub source_span: Span,
pub source_name: Symbol,
pub source_ty: Ty<'tcx>,
pub target_name: Symbol,
pub target_ty: Ty<'tcx>,
pub trait_name: &'static str,
}

#[derive(Diagnostic)]
#[diag(
"implementing `{$trait_name}` requires every target field to have a corresponding source field"
)]
pub(crate) struct CoerceSharedMissingField {
#[primary_span]
pub span: Span,
pub trait_name: &'static str,
}

#[derive(Diagnostic)]
#[diag(
"implementing `{$trait_name}` requires source and target structs to use the same field style"
)]
pub(crate) struct CoerceSharedFieldStyleMismatch {
#[primary_span]
pub span: Span,
pub trait_name: &'static str,
}

#[derive(Diagnostic)]
#[diag(
"implementing `{$trait_name}` requires all source and target fields to be accessible from the impl"
)]
pub(crate) struct CoerceSharedInaccessibleField {
#[primary_span]
pub span: Span,
pub trait_name: &'static str,
}

#[derive(Diagnostic)]
#[diag("the trait `{$trait_name}` may only be implemented for a coercion between structures", code = E0377)]
pub(crate) struct CoerceUnsizedNonStruct {
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/reborrow/coerce-shared-associated-type-field.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//@ check-pass

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

Expand Down Expand Up @@ -25,6 +27,5 @@ struct MyRef<'a> {
impl Reborrow for MyMut<'_> {}

impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}
//~^ ERROR

fn main() {}
8 changes: 0 additions & 8 deletions tests/ui/reborrow/coerce-shared-associated-type-field.stderr

This file was deleted.

3 changes: 2 additions & 1 deletion tests/ui/reborrow/coerce-shared-decl-macro-hygiene.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//@ check-pass

#![feature(reborrow, decl_macro)]
#![allow(incomplete_features)]

Expand All @@ -18,7 +20,6 @@ macro my_macro($field:ident) {
impl Reborrow for MyMut<'_> {}

impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}
//~^ ERROR
}

my_macro!(field);
Expand Down
13 changes: 0 additions & 13 deletions tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr

This file was deleted.

2 changes: 1 addition & 1 deletion tests/ui/reborrow/coerce-shared-field-lifetime-swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ impl Reborrow for MyMut<'_> {}
#[derive(Copy, Clone)]
struct MyRef<'a> {
x: &'a (),
//~^ ERROR
y: &'static (),
}

impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}
//~^ ERROR

fn main() {}
11 changes: 7 additions & 4 deletions tests/ui/reborrow/coerce-shared-field-lifetime-swap.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced
--> $DIR/coerce-shared-field-lifetime-swap.rs:18:10
error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field
--> $DIR/coerce-shared-field-lifetime-swap.rs:14:5
|
LL | impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^
LL | x: &'static (),
| -------------- source field `x` has type `&'static ()`
...
LL | x: &'a (),
| ^^^^^^^^^ target field `x` has type `&'a ()`

error: aborting due to 1 previous error

3 changes: 2 additions & 1 deletion tests/ui/reborrow/coerce-shared-field-relations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impl<'a, T> Reborrow for RenamedMut<'a, T> {}
#[derive(Clone, Copy)]
struct RenamedRef<'a, T> {
target: &'a T,
//~^ ERROR
}

impl<'a, T> CoerceShared<RenamedRef<'a, T>> for RenamedMut<'a, T> {}
Expand All @@ -37,11 +38,11 @@ impl<'a, T> Reborrow for BadMut<'a, T> {}
#[derive(Clone, Copy)]
struct BadRef<'a, T> {
value: &'a u32,
//~^ ERROR
_marker: std::marker::PhantomData<T>,
}

impl<'a, T> CoerceShared<BadRef<'a, T>> for BadMut<'a, T> {}
//~^ ERROR

fn good(_value: CustomRef<'_, u32>) {}

Expand Down
20 changes: 14 additions & 6 deletions tests/ui/reborrow/coerce-shared-field-relations.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
error[E0277]: the trait bound `&'a mut T: CoerceShared<&'a u32>` is not satisfied
--> $DIR/coerce-shared-field-relations.rs:43:1
error: implementing `CoerceShared` requires every target field to have a corresponding source field
--> $DIR/coerce-shared-field-relations.rs:26:5
|
LL | impl<'a, T> CoerceShared<BadRef<'a, T>> for BadMut<'a, T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `CoerceShared<&'a u32>` is not implemented for `&'a mut T`
LL | target: &'a T,
| ^^^^^^^^^^^^^

error: aborting due to 1 previous error
error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field
--> $DIR/coerce-shared-field-relations.rs:40:5
|
LL | value: &'a mut T,
| ---------------- source field `value` has type `&'a mut T`
...
LL | value: &'a u32,
| ^^^^^^^^^^^^^^ target field `value` has type `&'a u32`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
3 changes: 1 addition & 2 deletions tests/ui/reborrow/coerce-shared-foreign-private-field.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//@ check-pass

//@ aux-build: reborrow_foreign_private.rs

#![feature(reborrow)]
Expand All @@ -16,5 +14,6 @@ struct LocalMut<'a> {
impl<'a> Reborrow for LocalMut<'a> {}

impl<'a> CoerceShared<ForeignRef<'a>> for LocalMut<'a> {}
//~^ ERROR

fn main() {}
8 changes: 8 additions & 0 deletions tests/ui/reborrow/coerce-shared-foreign-private-field.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: implementing `CoerceShared` requires all source and target fields to be accessible from the impl
--> $DIR/coerce-shared-foreign-private-field.rs:16:1
|
LL | impl<'a> CoerceShared<ForeignRef<'a>> for LocalMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//@ check-pass

#![feature(reborrow)]

use std::marker::{CoerceShared, PhantomData, Reborrow};
Expand All @@ -18,5 +16,6 @@ struct LocalPtrMut<'a>(*const i32, PhantomData<&'a ()>);
impl<'a> Reborrow for LocalPtrMut<'a> {}

impl<'a> CoerceShared<ForeignPtrRef<'a>> for LocalPtrMut<'a> {}
//~^ ERROR

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: implementing `CoerceShared` requires all source and target fields to be accessible from the impl
--> $DIR/coerce-shared-foreign-private-tuple-field.rs:18:1
|
LL | impl<'a> CoerceShared<ForeignPtrRef<'a>> for LocalPtrMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

3 changes: 2 additions & 1 deletion tests/ui/reborrow/coerce-shared-generics.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//@ check-pass

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

Expand All @@ -24,7 +26,6 @@ impl<'a, T, U: Copy, const N: usize> Clone for BufferRef<'a, T, U, N> {
impl<'a, T, U: Copy, const N: usize> Copy for BufferRef<'a, T, U, N> {}

impl<'a, T, U: Copy, const N: usize> CoerceShared<BufferRef<'a, T, U, N>>
//~^ ERROR
for BufferMut<'a, T, U, N>
{
}
Expand Down
8 changes: 0 additions & 8 deletions tests/ui/reborrow/coerce-shared-generics.stderr

This file was deleted.

1 change: 1 addition & 0 deletions tests/ui/reborrow/coerce-shared-lifetime-mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ impl<'a> Reborrow for CustomMarker<'a> {}
struct StaticMarkerRef<'a>(PhantomData<&'a ()>);

impl<'a> CoerceShared<StaticMarkerRef<'static>> for CustomMarker<'a> {}
//~^ ERROR

fn method(_a: StaticMarkerRef<'static>) {}

Expand Down
10 changes: 8 additions & 2 deletions tests/ui/reborrow/coerce-shared-lifetime-mismatch.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
error: implementing `CoerceShared` requires source and target to use the same reborrow lifetime argument
--> $DIR/coerce-shared-lifetime-mismatch.rs:15:10
|
LL | impl<'a> CoerceShared<StaticMarkerRef<'static>> for CustomMarker<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0597]: `a` does not live long enough
--> $DIR/coerce-shared-lifetime-mismatch.rs:21:12
--> $DIR/coerce-shared-lifetime-mismatch.rs:22:12
|
LL | let a = CustomMarker(PhantomData);
| - binding `a` declared here
Expand All @@ -12,6 +18,6 @@ LL |
LL | }
| - `a` dropped here while still borrowed

error: aborting due to 1 previous error
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0597`.
2 changes: 1 addition & 1 deletion tests/ui/reborrow/coerce-shared-missing-target-field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ impl<'a, T> Reborrow for MissingSourceMut<'a, T> {}
struct MissingSourceRef<'a, T> {
value: &'a T,
len: usize,
//~^ ERROR
}

impl<'a, T> CoerceShared<MissingSourceRef<'a, T>> for MissingSourceMut<'a, T> {}
//~^ ERROR

fn main() {}
8 changes: 4 additions & 4 deletions tests/ui/reborrow/coerce-shared-missing-target-field.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced
--> $DIR/coerce-shared-missing-target-field.rs:17:13
error: implementing `CoerceShared` requires every target field to have a corresponding source field
--> $DIR/coerce-shared-missing-target-field.rs:14:5
|
LL | impl<'a, T> CoerceShared<MissingSourceRef<'a, T>> for MissingSourceMut<'a, T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | len: usize,
| ^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ struct AliasRef<'a> {
}

impl<'a> CoerceShared<AliasRef<'a>> for AliasMut<'a> {}
//~^ ERROR

struct InnerLifetimeMut<'a> {
value: &'a mut &'static (),
Expand All @@ -36,6 +35,7 @@ impl Reborrow for InnerLifetimeMut<'_> {}
#[derive(Copy, Clone)]
struct InnerLifetimeRef<'a> {
value: &'a &'a (),
//~^ ERROR
}

impl<'a> CoerceShared<InnerLifetimeRef<'a>> for InnerLifetimeMut<'a> {}
Expand Down
12 changes: 7 additions & 5 deletions tests/ui/reborrow/coerce-shared-mut-ref-field-validation.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
error[E0277]: the trait bound `&'a mut u32: CoerceShared<&'a u32>` is not satisfied
--> $DIR/coerce-shared-mut-ref-field-validation.rs:27:1
error: implementing `CoerceShared` requires corresponding fields to match, be reborrowable with `CoerceShared`, or coerce a mutable reference field to a shared reference field
--> $DIR/coerce-shared-mut-ref-field-validation.rs:37:5
|
LL | impl<'a> CoerceShared<AliasRef<'a>> for AliasMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `CoerceShared<&'a u32>` is not implemented for `&'a mut u32`
LL | value: &'a mut &'static (),
| -------------------------- source field `value` has type `&'a mut &'static ()`
...
LL | value: &'a &'a (),
| ^^^^^^^^^^^^^^^^^ target field `value` has type `&'a &'a ()`

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,3 +1,5 @@
//@ check-pass

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

Expand Down Expand Up @@ -29,7 +31,6 @@ impl<'a, T> Clone for OmitRef<'a, T> {
impl<'a, T> Copy for OmitRef<'a, T> {}

impl<'a, T> CoerceShared<OmitRef<'a, T>> for OmitMut<'a, T> {}
//~^ ERROR

fn read(value: OmitRef<'_, i32>) {
assert_eq!(*value.value, 1);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ impl<'a, T> Clone for OmitRef<'a, T> {
impl<'a, T> Copy for OmitRef<'a, T> {}

impl<'a, T> CoerceShared<OmitRef<'a, T>> for OmitMut<'a, T> {}
//~^ ERROR

fn get<'a>(value: OmitRef<'a, i32>) -> &'a i32 {
value.value
Expand Down
Loading
Loading