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
830 changes: 722 additions & 108 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs

Large diffs are not rendered by default.

101 changes: 100 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,112 @@ 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,
#[label("source reborrow lifetime")]
pub source_lifetime_span: Option<Span>,
#[label("target reborrow lifetime")]
pub target_lifetime_span: Option<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,
#[label("required by this `CoerceShared` implementation")]
pub impl_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]
#[label("target field `{$field_name}` has no corresponding source field")]
pub span: Span,
#[label("source type `{$source_ty_name}` does not contain field `{$field_name}`")]
pub source_ty_span: Span,
pub trait_name: &'static str,
pub source_ty_name: Symbol,
pub field_name: Symbol,
}

#[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 {$role} type fields to be accessible from the impl"
)]
pub(crate) struct CoerceSharedInaccessibleField {
#[primary_span]
pub span: Span,
#[label("{$role} type `{$type_name}` has inaccessible reborrow data fields")]
pub type_span: Span,
pub trait_name: &'static str,
pub role: &'static str,
pub type_name: Symbol,
}

#[derive(Diagnostic)]
#[diag(
"implementing `{$trait_name}` currently requires source and target to have at most one \
non-ZST reborrow data field"
)]
#[note(
"this is a temporary restriction until `CoerceShared` lowering supports non-trivially \
memcpy-compatible field layouts"
)]
pub(crate) struct CoerceSharedMultipleNonZstFields {
#[primary_span]
#[label("in this `CoerceShared` implementation")]
pub span: Span,
#[label("source type has {$source_count} non-ZST reborrow data fields")]
pub source_ty_span: Span,
#[label("target type has {$target_count} non-ZST reborrow data fields")]
pub target_ty_span: Span,
pub trait_name: &'static str,
pub source_count: usize,
pub target_count: usize,
}

#[derive(Diagnostic)]
#[diag("the trait `{$trait_name}` may only be implemented for a coercion between structures", code = E0377)]
pub(crate) struct CoerceUnsizedNonStruct {
Expand Down
12 changes: 9 additions & 3 deletions tests/ui/reborrow/coerce-shared-associated-type-field.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced
--> $DIR/coerce-shared-associated-type-field.rs:27:10
error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field
--> $DIR/coerce-shared-associated-type-field.rs:27:1
|
LL | impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^---------^^^^^^---------^^^
| | | |
| | | source type has 2 non-ZST reborrow data fields
| | target type has 2 non-ZST reborrow data fields
| in this `CoerceShared` implementation
|
= note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts

error: aborting due to 1 previous error

11 changes: 8 additions & 3 deletions tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced
--> $DIR/coerce-shared-decl-macro-hygiene.rs:20:14
error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field
--> $DIR/coerce-shared-decl-macro-hygiene.rs:20:5
|
LL | impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^---------^^^^^^---------^^^
| | | |
| | | source type has 2 non-ZST reborrow data fields
| | target type has 2 non-ZST reborrow data fields
| in this `CoerceShared` implementation
...
LL | my_macro!(field);
| ---------------- in this macro invocation
|
= note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts
= note: this error originates in the macro `my_macro` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error
Expand Down
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() {}
12 changes: 9 additions & 3 deletions tests/ui/reborrow/coerce-shared-field-lifetime-swap.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
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
Comment thread
P8L1 marked this conversation as resolved.
--> $DIR/coerce-shared-field-lifetime-swap.rs:14:5
|
LL | x: &'static (),
| -------------- source field `x` has type `&'static ()`
...
LL | x: &'a (),
| ^^^^^^^^^ target field `x` has type `&'a ()`
...
LL | impl<'a> CoerceShared<MyRef<'a>> for MyMut<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^
| ------------------------------------------------- required by this `CoerceShared` implementation

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
24 changes: 19 additions & 5 deletions tests/ui/reborrow/coerce-shared-field-relations.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
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 | target: &'a T,
| ^^^^^^^^^^^^^ target field `target` has no corresponding source field
...
LL | impl<'a, T> CoerceShared<RenamedRef<'a, T>> for RenamedMut<'a, T> {}
| ----------------- source type `RenamedMut` does not contain field `target`

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`
...
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`
| ------------------------------------------------------------ required by this `CoerceShared` implementation

error: aborting due to 1 previous error
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() {}
10 changes: 10 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,10 @@
error: implementing `CoerceShared` requires all target type 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> {}
| ^^^^^^^^^^^^^^^^^^^^^^--------------^^^^^^^^^^^^^^^^^^^^^
| |
| target type `ForeignRef` has inaccessible reborrow data fields

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() {}
10 changes: 10 additions & 0 deletions tests/ui/reborrow/coerce-shared-foreign-private-tuple-field.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: implementing `CoerceShared` requires all target type 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> {}
| ^^^^^^^^^^^^^^^^^^^^^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
| |
| target type `ForeignPtrRef` has inaccessible reborrow data fields

error: aborting due to 1 previous error

18 changes: 14 additions & 4 deletions tests/ui/reborrow/coerce-shared-generics.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
error: implementing `CoerceShared` does not allow multiple lifetimes or fields to be coerced
--> $DIR/coerce-shared-generics.rs:26:38
error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field
--> $DIR/coerce-shared-generics.rs:26:1
|
LL | impl<'a, T, U: Copy, const N: usize> CoerceShared<BufferRef<'a, T, U, N>>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl<'a, T, U: Copy, const N: usize> CoerceShared<BufferRef<'a, T, U, N>>
| ^ ---------------------- target type has 2 non-ZST reborrow data fields
| _|
| |
LL | |
LL | | for BufferMut<'a, T, U, N>
| | ---------------------- source type has 2 non-ZST reborrow data fields
LL | | {
LL | | }
| |_^ in this `CoerceShared` implementation
|
= note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts

error: aborting due to 1 previous error

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
12 changes: 10 additions & 2 deletions tests/ui/reborrow/coerce-shared-lifetime-mismatch.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
error: implementing `CoerceShared` requires source and target to use the same reborrow lifetime argument
Comment thread
P8L1 marked this conversation as resolved.
--> $DIR/coerce-shared-lifetime-mismatch.rs:15:10
|
LL | impl<'a> CoerceShared<StaticMarkerRef<'static>> for CustomMarker<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^ -- source reborrow lifetime
| |
| target reborrow lifetime

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 +20,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() {}
9 changes: 6 additions & 3 deletions tests/ui/reborrow/coerce-shared-missing-target-field.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-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 | len: usize,
| ^^^^^^^^^^ target field `len` has no corresponding source field
...
LL | impl<'a, T> CoerceShared<MissingSourceRef<'a, T>> for MissingSourceMut<'a, T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ----------------------- source type `MissingSourceMut` does not contain field `len`

error: aborting due to 1 previous error

22 changes: 22 additions & 0 deletions tests/ui/reborrow/coerce-shared-multi-non-zst.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#![feature(reborrow)]
#![allow(dead_code)]

use std::marker::{CoerceShared, Reborrow};

struct Source<'a> {
a: &'a mut u8,
b: u8,
}

#[derive(Copy, Clone)]
struct Target<'a> {
a: &'a u8,
b: u8,
}

impl Reborrow for Source<'_> {}

impl<'a> CoerceShared<Target<'a>> for Source<'a> {}
//~^ ERROR

fn main() {}
14 changes: 14 additions & 0 deletions tests/ui/reborrow/coerce-shared-multi-non-zst.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field
--> $DIR/coerce-shared-multi-non-zst.rs:19:1
|
LL | impl<'a> CoerceShared<Target<'a>> for Source<'a> {}
| ^^^^^^^^^^^^^^^^^^^^^^----------^^^^^^----------^^^
| | | |
| | | source type has 2 non-ZST reborrow data fields
| | target type has 2 non-ZST reborrow data fields
| in this `CoerceShared` implementation
|
= note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts

error: aborting due to 1 previous error

Loading
Loading