Skip to content

Commit 1c44fb3

Browse files
Deduplicate CoerceUnsized and DispatchFromDyn impl errors
1 parent 38a608e commit 1c44fb3

File tree

3 files changed

+19
-49
lines changed

3 files changed

+19
-49
lines changed

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,7 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E
195195
// Just compute this for the side-effects, in particular reporting
196196
// errors; other parts of the code may demand it for the info of
197197
// course.
198-
let span = tcx.def_span(impl_did);
199-
tcx.at(span).ensure_ok().coerce_unsized_info(impl_did)
198+
tcx.ensure_ok().coerce_unsized_info(impl_did)
200199
}
201200

202201
fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool {
@@ -218,13 +217,24 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
218217
let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
219218

220219
let source = trait_ref.self_ty();
221-
assert!(!source.has_escaping_bound_vars());
222220
let target = {
223221
assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
224222

225223
trait_ref.args.type_at(1)
226224
};
227225

226+
// Check `CoercePointee` impl is WF -- if not, then there's no reason to report
227+
// redundant errors for `DispatchFromDyn`. This is best effort, though.
228+
let mut res = Ok(());
229+
tcx.for_each_relevant_impl(
230+
tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
231+
source,
232+
|impl_def_id| {
233+
res = res.and(tcx.ensure_ok().coerce_unsized_info(impl_def_id));
234+
},
235+
);
236+
res?;
237+
228238
debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
229239

230240
let param_env = tcx.param_env(impl_did);

tests/ui/deriving/deriving-coerce-pointee-neg.rs

-3
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,13 @@ struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
145145
#[repr(transparent)]
146146
#[derive(CoercePointee)]
147147
//~^ ERROR for `RcWithId<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
148-
//~| ERROR for `RcWithId<T>` to have a valid implementation of `DispatchFromDyn`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
149148
struct RcWithId<T: ?Sized> {
150149
inner: std::rc::Rc<(i32, Box<T>)>,
151150
}
152151

153152
#[repr(transparent)]
154153
#[derive(CoercePointee)]
155154
//~^ ERROR implementing `CoerceUnsized` does not allow multiple fields to be coerced
156-
//~| ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced
157155
struct MoreThanOneField<T: ?Sized> {
158156
//~^ ERROR transparent struct needs at most one field with non-trivial size or alignment, but has 2
159157
inner1: Box<T>,
@@ -165,7 +163,6 @@ struct NotCoercePointeeData<T: ?Sized>(T);
165163
#[repr(transparent)]
166164
#[derive(CoercePointee)]
167165
//~^ ERROR for `UsingNonCoercePointeeData<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
168-
//~| ERROR for `UsingNonCoercePointeeData<T>` to have a valid implementation of `DispatchFromDyn`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
169166
struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
170167

171168
fn main() {}

tests/ui/deriving/deriving-coerce-pointee-neg.stderr

+6-43
Original file line numberDiff line numberDiff line change
@@ -118,43 +118,6 @@ error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(
118118
LL | struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
119119
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
120120

121-
error: for `RcWithId<T>` to have a valid implementation of `DispatchFromDyn`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
122-
--> $DIR/deriving-coerce-pointee-neg.rs:146:10
123-
|
124-
LL | #[derive(CoercePointee)]
125-
| ^^^^^^^^^^^^^
126-
...
127-
LL | inner: std::rc::Rc<(i32, Box<T>)>,
128-
| --------------------------------- `Rc<(i32, Box<T>)>` must be a pointer, reference, or smart pointer that is allowed to be unsized
129-
|
130-
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
131-
132-
error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced
133-
--> $DIR/deriving-coerce-pointee-neg.rs:154:10
134-
|
135-
LL | #[derive(CoercePointee)]
136-
| ^^^^^^^^^^^^^
137-
|
138-
note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced
139-
--> $DIR/deriving-coerce-pointee-neg.rs:159:5
140-
|
141-
LL | inner1: Box<T>,
142-
| ^^^^^^^^^^^^^^
143-
LL | inner2: Box<T>,
144-
| ^^^^^^^^^^^^^^
145-
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
146-
147-
error: for `UsingNonCoercePointeeData<T>` to have a valid implementation of `DispatchFromDyn`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
148-
--> $DIR/deriving-coerce-pointee-neg.rs:166:10
149-
|
150-
LL | #[derive(CoercePointee)]
151-
| ^^^^^^^^^^^^^
152-
...
153-
LL | struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
154-
| ----------------------- `NotCoercePointeeData<T>` must be a pointer, reference, or smart pointer that is allowed to be unsized
155-
|
156-
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
157-
158121
error: for `RcWithId<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
159122
--> $DIR/deriving-coerce-pointee-neg.rs:146:10
160123
|
@@ -167,13 +130,13 @@ LL | inner: std::rc::Rc<(i32, Box<T>)>,
167130
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
168131

169132
error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced
170-
--> $DIR/deriving-coerce-pointee-neg.rs:154:10
133+
--> $DIR/deriving-coerce-pointee-neg.rs:153:10
171134
|
172135
LL | #[derive(CoercePointee)]
173136
| ^^^^^^^^^^^^^
174137
|
175138
note: the trait `CoerceUnsized` may only be implemented when a single field is being coerced
176-
--> $DIR/deriving-coerce-pointee-neg.rs:159:5
139+
--> $DIR/deriving-coerce-pointee-neg.rs:157:5
177140
|
178141
LL | inner1: Box<T>,
179142
| ^^^^^^^^^^^^^^
@@ -182,18 +145,18 @@ LL | inner2: Box<T>,
182145
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
183146

184147
error: for `UsingNonCoercePointeeData<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
185-
--> $DIR/deriving-coerce-pointee-neg.rs:166:10
148+
--> $DIR/deriving-coerce-pointee-neg.rs:164:10
186149
|
187150
LL | #[derive(CoercePointee)]
188151
| ^^^^^^^^^^^^^
189-
...
152+
LL |
190153
LL | struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
191154
| ----------------------- `NotCoercePointeeData<T>` must be a pointer, reference, or smart pointer that is allowed to be unsized
192155
|
193156
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
194157

195158
error[E0690]: transparent struct needs at most one field with non-trivial size or alignment, but has 2
196-
--> $DIR/deriving-coerce-pointee-neg.rs:157:1
159+
--> $DIR/deriving-coerce-pointee-neg.rs:155:1
197160
|
198161
LL | struct MoreThanOneField<T: ?Sized> {
199162
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs at most one field with non-trivial size or alignment, but has 2
@@ -203,7 +166,7 @@ LL | inner1: Box<T>,
203166
LL | inner2: Box<T>,
204167
| -------------- this field has non-zero size or requires alignment
205168

206-
error: aborting due to 24 previous errors
169+
error: aborting due to 21 previous errors
207170

208171
Some errors have detailed explanations: E0375, E0392, E0690, E0802.
209172
For more information about an error, try `rustc --explain E0375`.

0 commit comments

Comments
 (0)