Skip to content

Commit 94ad084

Browse files
committed
Safe Transmute: Fix propagation of errors
- Make sure that the most specific Reason is the one that bubbles up when we are folding over the `Answer` tree. `Reason::DstIsBitIncompatible` is the least specific, so that should be used only when there isn't anything else available. - Small fixes where we used the wrong Reason variant. - Tiny cleanups
1 parent 263a4f2 commit 94ad084

File tree

12 files changed

+67
-52
lines changed

12 files changed

+67
-52
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,7 +2751,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
27512751
rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, trait_ref.substs.const_at(3)) else {
27522752
span_bug!(span, "Unable to construct rustc_transmute::Assume where it was previously possible");
27532753
};
2754-
// FIXME(bryangarza): Need to flatten here too
2754+
// FIXME(bryangarza): Is this enough, or should we resolve all nested
2755+
// obligations like we do for `confirm_transmutability_candidate(...)?`
27552756
match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
27562757
obligation.cause,
27572758
src_and_dst,
@@ -2780,7 +2781,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
27802781
rustc_transmute::Reason::DstIsPrivate => format!(
27812782
"`{dst}` is or contains a type or field that is not visible in that scope"
27822783
),
2783-
// FIXME(bryangarza): Include the number of bytes of src and dst
27842784
rustc_transmute::Reason::DstIsTooBig => {
27852785
format!("The size of `{src}` is smaller than the size of `{dst}`")
27862786
}

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
329329
)
330330
};
331331

332-
// // FIXME(bryangarza): Check src.mutability or dst.mutability to know whether dst -> src obligation is needed
332+
// FIXME(bryangarza): Check src.mutability or dst.mutability to know whether dst -> src obligation is needed
333333
Ok(vec![make_obl(src.ty, dst.ty), make_obl(dst.ty, src.ty)])
334334
}
335335
}

compiler/rustc_transmute/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(alloc_layout_extra, decl_macro, iterator_try_reduce, never_type)]
1+
#![feature(alloc_layout_extra, decl_macro, iterator_try_reduce, never_type, let_chains)]
22
#![allow(dead_code, unused_variables)]
33
#![deny(rustc::untranslatable_diagnostic)]
44
#![deny(rustc::diagnostic_outside_of_impl)]

compiler/rustc_transmute/src/maybe_transmutable/mod.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,12 @@ mod rustc {
7878
match (src, dst) {
7979
// Answer `Ok(None)` here, because 'unknown layout' and type errors will already
8080
// be reported by rustc. No need to spam the user with more errors.
81-
(Err(Err::TypeError(_)), _) | (_, Err(Err::TypeError(_))) => Err(Ok(None)),
82-
(Err(Err::Unknown), _) | (_, Err(Err::Unknown)) => Err(Ok(None)),
83-
(Err(Err::Unspecified), _) | (_, Err(Err::Unspecified)) => {
84-
Err(Err(Reason::SrcIsUnspecified))
85-
}
81+
(Err(Err::TypeError(_)), _)
82+
| (_, Err(Err::TypeError(_)))
83+
| (Err(Err::Unknown), _)
84+
| (_, Err(Err::Unknown)) => Err(Ok(None)),
85+
(Err(Err::Unspecified), _) => Err(Err(Reason::SrcIsUnspecified)),
86+
(_, Err(Err::Unspecified)) => Err(Err(Reason::DstIsUnspecified)),
8687
(Ok(src), Ok(dst)) => Ok((src, dst)),
8788
}
8889
});
@@ -316,12 +317,19 @@ where
316317
}
317318
}
318319

319-
fn and<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R> {
320-
// Should propagate errors on the right side, because the initial value
321-
// used in `apply` is on the left side.
322-
let rhs = rhs?;
323-
let lhs = lhs?;
324-
Ok(match (lhs, rhs) {
320+
fn and<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R>
321+
where
322+
R: PartialEq,
323+
{
324+
// If both are errors, then we should return the more specific one
325+
if lhs.is_err() && rhs.is_err() {
326+
if lhs == Err(Reason::DstIsBitIncompatible) {
327+
return rhs;
328+
} else {
329+
return lhs;
330+
}
331+
}
332+
Ok(match (lhs?, rhs?) {
325333
// If only one side has a condition, pass it along
326334
(None, other) | (other, None) => other,
327335
// If both sides have IfAll conditions, merge them
@@ -340,10 +348,17 @@ fn and<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R> {
340348
})
341349
}
342350

343-
fn or<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R> {
344-
// If both are errors, then we should return the one on the right
351+
fn or<R>(lhs: Answer<R>, rhs: Answer<R>) -> Answer<R>
352+
where
353+
R: PartialEq,
354+
{
355+
// If both are errors, then we should return the more specific one
345356
if lhs.is_err() && rhs.is_err() {
346-
return rhs;
357+
if lhs == Err(Reason::DstIsBitIncompatible) {
358+
return rhs;
359+
} else {
360+
return lhs;
361+
}
347362
}
348363
// Otherwise, errors can be ignored for the rest of the pattern matching
349364
let lhs = lhs.unwrap_or(None);

tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ error[E0277]: `u128` cannot be safely transmuted into `[String; 0]` in the defin
2323
--> $DIR/should_require_well_defined_layout.rs:27:47
2424
|
2525
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
26-
| ^^^^^^^^^ `u128` does not have a well-specified layout
26+
| ^^^^^^^^^ `[String; 0]` does not have a well-specified layout
2727
|
2828
note: required by a bound in `is_maybe_transmutable`
2929
--> $DIR/should_require_well_defined_layout.rs:13:14
@@ -65,7 +65,7 @@ error[E0277]: `u128` cannot be safely transmuted into `[String; 1]` in the defin
6565
--> $DIR/should_require_well_defined_layout.rs:33:47
6666
|
6767
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
68-
| ^^^^^^^^^ `u128` does not have a well-specified layout
68+
| ^^^^^^^^^ `[String; 1]` does not have a well-specified layout
6969
|
7070
note: required by a bound in `is_maybe_transmutable`
7171
--> $DIR/should_require_well_defined_layout.rs:13:14
@@ -107,7 +107,7 @@ error[E0277]: `u128` cannot be safely transmuted into `[String; 2]` in the defin
107107
--> $DIR/should_require_well_defined_layout.rs:39:47
108108
|
109109
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
110-
| ^^^^^^^^^ `u128` does not have a well-specified layout
110+
| ^^^^^^^^^ `[String; 2]` does not have a well-specified layout
111111
|
112112
note: required by a bound in `is_maybe_transmutable`
113113
--> $DIR/should_require_well_defined_layout.rs:13:14

tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ error[E0277]: `V0i8` cannot be safely transmuted into `u16` in the defining scop
2424
--> $DIR/primitive_reprs_should_have_correct_length.rs:50:44
2525
|
2626
LL | assert::is_transmutable::<Current, Larger, Context>();
27-
| ^^^^^^ At least one value of `V0i8` isn't a bit-valid value of `u16`
27+
| ^^^^^^ The size of `V0i8` is smaller than the size of `u16`
2828
|
2929
note: required by a bound in `is_transmutable`
3030
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -68,7 +68,7 @@ error[E0277]: `V0u8` cannot be safely transmuted into `u16` in the defining scop
6868
--> $DIR/primitive_reprs_should_have_correct_length.rs:58:44
6969
|
7070
LL | assert::is_transmutable::<Current, Larger, Context>();
71-
| ^^^^^^ At least one value of `V0u8` isn't a bit-valid value of `u16`
71+
| ^^^^^^ The size of `V0u8` is smaller than the size of `u16`
7272
|
7373
note: required by a bound in `is_transmutable`
7474
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -90,7 +90,7 @@ error[E0277]: `u8` cannot be safely transmuted into `V0i16` in the defining scop
9090
--> $DIR/primitive_reprs_should_have_correct_length.rs:72:44
9191
|
9292
LL | assert::is_transmutable::<Smaller, Current, Context>();
93-
| ^^^^^^^ At least one value of `u8` isn't a bit-valid value of `V0i16`
93+
| ^^^^^^^ The size of `u8` is smaller than the size of `V0i16`
9494
|
9595
note: required by a bound in `is_transmutable`
9696
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -112,7 +112,7 @@ error[E0277]: `V0i16` cannot be safely transmuted into `u32` in the defining sco
112112
--> $DIR/primitive_reprs_should_have_correct_length.rs:74:44
113113
|
114114
LL | assert::is_transmutable::<Current, Larger, Context>();
115-
| ^^^^^^ At least one value of `V0i16` isn't a bit-valid value of `u32`
115+
| ^^^^^^ The size of `V0i16` is smaller than the size of `u32`
116116
|
117117
note: required by a bound in `is_transmutable`
118118
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -134,7 +134,7 @@ error[E0277]: `u8` cannot be safely transmuted into `V0u16` in the defining scop
134134
--> $DIR/primitive_reprs_should_have_correct_length.rs:80:44
135135
|
136136
LL | assert::is_transmutable::<Smaller, Current, Context>();
137-
| ^^^^^^^ At least one value of `u8` isn't a bit-valid value of `V0u16`
137+
| ^^^^^^^ The size of `u8` is smaller than the size of `V0u16`
138138
|
139139
note: required by a bound in `is_transmutable`
140140
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -156,7 +156,7 @@ error[E0277]: `V0u16` cannot be safely transmuted into `u32` in the defining sco
156156
--> $DIR/primitive_reprs_should_have_correct_length.rs:82:44
157157
|
158158
LL | assert::is_transmutable::<Current, Larger, Context>();
159-
| ^^^^^^ At least one value of `V0u16` isn't a bit-valid value of `u32`
159+
| ^^^^^^ The size of `V0u16` is smaller than the size of `u32`
160160
|
161161
note: required by a bound in `is_transmutable`
162162
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -178,7 +178,7 @@ error[E0277]: `u16` cannot be safely transmuted into `V0i32` in the defining sco
178178
--> $DIR/primitive_reprs_should_have_correct_length.rs:96:44
179179
|
180180
LL | assert::is_transmutable::<Smaller, Current, Context>();
181-
| ^^^^^^^ At least one value of `u16` isn't a bit-valid value of `V0i32`
181+
| ^^^^^^^ The size of `u16` is smaller than the size of `V0i32`
182182
|
183183
note: required by a bound in `is_transmutable`
184184
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -200,7 +200,7 @@ error[E0277]: `V0i32` cannot be safely transmuted into `u64` in the defining sco
200200
--> $DIR/primitive_reprs_should_have_correct_length.rs:98:44
201201
|
202202
LL | assert::is_transmutable::<Current, Larger, Context>();
203-
| ^^^^^^ At least one value of `V0i32` isn't a bit-valid value of `u64`
203+
| ^^^^^^ The size of `V0i32` is smaller than the size of `u64`
204204
|
205205
note: required by a bound in `is_transmutable`
206206
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -222,7 +222,7 @@ error[E0277]: `u16` cannot be safely transmuted into `V0u32` in the defining sco
222222
--> $DIR/primitive_reprs_should_have_correct_length.rs:104:44
223223
|
224224
LL | assert::is_transmutable::<Smaller, Current, Context>();
225-
| ^^^^^^^ At least one value of `u16` isn't a bit-valid value of `V0u32`
225+
| ^^^^^^^ The size of `u16` is smaller than the size of `V0u32`
226226
|
227227
note: required by a bound in `is_transmutable`
228228
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -244,7 +244,7 @@ error[E0277]: `V0u32` cannot be safely transmuted into `u64` in the defining sco
244244
--> $DIR/primitive_reprs_should_have_correct_length.rs:106:44
245245
|
246246
LL | assert::is_transmutable::<Current, Larger, Context>();
247-
| ^^^^^^ At least one value of `V0u32` isn't a bit-valid value of `u64`
247+
| ^^^^^^ The size of `V0u32` is smaller than the size of `u64`
248248
|
249249
note: required by a bound in `is_transmutable`
250250
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -266,7 +266,7 @@ error[E0277]: `u32` cannot be safely transmuted into `V0i64` in the defining sco
266266
--> $DIR/primitive_reprs_should_have_correct_length.rs:120:44
267267
|
268268
LL | assert::is_transmutable::<Smaller, Current, Context>();
269-
| ^^^^^^^ At least one value of `u32` isn't a bit-valid value of `V0i64`
269+
| ^^^^^^^ The size of `u32` is smaller than the size of `V0i64`
270270
|
271271
note: required by a bound in `is_transmutable`
272272
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -288,7 +288,7 @@ error[E0277]: `V0i64` cannot be safely transmuted into `u128` in the defining sc
288288
--> $DIR/primitive_reprs_should_have_correct_length.rs:122:44
289289
|
290290
LL | assert::is_transmutable::<Current, Larger, Context>();
291-
| ^^^^^^ At least one value of `V0i64` isn't a bit-valid value of `u128`
291+
| ^^^^^^ The size of `V0i64` is smaller than the size of `u128`
292292
|
293293
note: required by a bound in `is_transmutable`
294294
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -310,7 +310,7 @@ error[E0277]: `u32` cannot be safely transmuted into `V0u64` in the defining sco
310310
--> $DIR/primitive_reprs_should_have_correct_length.rs:128:44
311311
|
312312
LL | assert::is_transmutable::<Smaller, Current, Context>();
313-
| ^^^^^^^ At least one value of `u32` isn't a bit-valid value of `V0u64`
313+
| ^^^^^^^ The size of `u32` is smaller than the size of `V0u64`
314314
|
315315
note: required by a bound in `is_transmutable`
316316
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -332,7 +332,7 @@ error[E0277]: `V0u64` cannot be safely transmuted into `u128` in the defining sc
332332
--> $DIR/primitive_reprs_should_have_correct_length.rs:130:44
333333
|
334334
LL | assert::is_transmutable::<Current, Larger, Context>();
335-
| ^^^^^^ At least one value of `V0u64` isn't a bit-valid value of `u128`
335+
| ^^^^^^ The size of `V0u64` is smaller than the size of `u128`
336336
|
337337
note: required by a bound in `is_transmutable`
338338
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -354,7 +354,7 @@ error[E0277]: `u8` cannot be safely transmuted into `V0isize` in the defining sc
354354
--> $DIR/primitive_reprs_should_have_correct_length.rs:144:44
355355
|
356356
LL | assert::is_transmutable::<Smaller, Current, Context>();
357-
| ^^^^^^^ At least one value of `u8` isn't a bit-valid value of `V0isize`
357+
| ^^^^^^^ The size of `u8` is smaller than the size of `V0isize`
358358
|
359359
note: required by a bound in `is_transmutable`
360360
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -376,7 +376,7 @@ error[E0277]: `V0isize` cannot be safely transmuted into `[usize; 2]` in the def
376376
--> $DIR/primitive_reprs_should_have_correct_length.rs:146:44
377377
|
378378
LL | assert::is_transmutable::<Current, Larger, Context>();
379-
| ^^^^^^ At least one value of `V0isize` isn't a bit-valid value of `[usize; 2]`
379+
| ^^^^^^ The size of `V0isize` is smaller than the size of `[usize; 2]`
380380
|
381381
note: required by a bound in `is_transmutable`
382382
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -398,7 +398,7 @@ error[E0277]: `u8` cannot be safely transmuted into `V0usize` in the defining sc
398398
--> $DIR/primitive_reprs_should_have_correct_length.rs:152:44
399399
|
400400
LL | assert::is_transmutable::<Smaller, Current, Context>();
401-
| ^^^^^^^ At least one value of `u8` isn't a bit-valid value of `V0usize`
401+
| ^^^^^^^ The size of `u8` is smaller than the size of `V0usize`
402402
|
403403
note: required by a bound in `is_transmutable`
404404
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14
@@ -420,7 +420,7 @@ error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` in the def
420420
--> $DIR/primitive_reprs_should_have_correct_length.rs:154:44
421421
|
422422
LL | assert::is_transmutable::<Current, Larger, Context>();
423-
| ^^^^^^ At least one value of `V0usize` isn't a bit-valid value of `[usize; 2]`
423+
| ^^^^^^ The size of `V0usize` is smaller than the size of `[usize; 2]`
424424
|
425425
note: required by a bound in `is_transmutable`
426426
--> $DIR/primitive_reprs_should_have_correct_length.rs:12:14

tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ error[E0277]: `u128` cannot be safely transmuted into `void::repr_rust` in the d
2424
--> $DIR/should_require_well_defined_layout.rs:29:47
2525
|
2626
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
27-
| ^^^^^^^^^ `u128` does not have a well-specified layout
27+
| ^^^^^^^^^ `void::repr_rust` does not have a well-specified layout
2828
|
2929
note: required by a bound in `is_maybe_transmutable`
3030
--> $DIR/should_require_well_defined_layout.rs:14:14
@@ -68,7 +68,7 @@ error[E0277]: `u128` cannot be safely transmuted into `singleton::repr_rust` in
6868
--> $DIR/should_require_well_defined_layout.rs:35:47
6969
|
7070
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
71-
| ^^^^^^^^^ `u128` does not have a well-specified layout
71+
| ^^^^^^^^^ `singleton::repr_rust` does not have a well-specified layout
7272
|
7373
note: required by a bound in `is_maybe_transmutable`
7474
--> $DIR/should_require_well_defined_layout.rs:14:14
@@ -112,7 +112,7 @@ error[E0277]: `u128` cannot be safely transmuted into `duplex::repr_rust` in the
112112
--> $DIR/should_require_well_defined_layout.rs:41:47
113113
|
114114
LL | assert::is_maybe_transmutable::<u128, repr_rust>();
115-
| ^^^^^^^^^ `u128` does not have a well-specified layout
115+
| ^^^^^^^^^ `duplex::repr_rust` does not have a well-specified layout
116116
|
117117
note: required by a bound in `is_maybe_transmutable`
118118
--> $DIR/should_require_well_defined_layout.rs:14:14

tests/ui/transmutability/enums/should_pad_variants.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope
22
--> $DIR/should_pad_variants.rs:44:36
33
|
44
LL | assert::is_transmutable::<Src, Dst, Context>();
5-
| ^^^ At least one value of `Src` isn't a bit-valid value of `Dst`
5+
| ^^^ The size of `Src` is smaller than the size of `Dst`
66
|
77
note: required by a bound in `is_transmutable`
88
--> $DIR/should_pad_variants.rs:13:14

0 commit comments

Comments
 (0)