Rollup merge of #135042 - lukas-code:taint-dyn-incompat, r=compiler-errors
taint fcx on selection errors during unsizing With `feature(dyn_compatible_for_dispatch)` we only check for dyn-compatibility by checking the `T: Unsize<dyn Trait>` predicate during the unsizing coercions checks. If the predicate doesn't hold, we emit an error, but pretend the coercion succeeded to prevent further errors. To prevent const eval from attempting to actually perform this coercion, we need to taint the fcx after reporting the trait errors in the coercion check. fixes https://github.com/rust-lang/rust/issues/135021 fixes https://github.com/rust-lang/rust/issues/130521
This commit is contained in:
commit
e0f4dc955a
5 changed files with 119 additions and 14 deletions
|
@ -666,7 +666,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||||
|
|
||||||
// Dyn-compatibility violations or miscellaneous.
|
// Dyn-compatibility violations or miscellaneous.
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
self.err_ctxt().report_selection_error(obligation.clone(), &obligation, &err);
|
let guar = self.err_ctxt().report_selection_error(
|
||||||
|
obligation.clone(),
|
||||||
|
&obligation,
|
||||||
|
&err,
|
||||||
|
);
|
||||||
|
self.fcx.set_tainted_by_errors(guar);
|
||||||
// Treat this like an obligation and follow through
|
// Treat this like an obligation and follow through
|
||||||
// with the unsizing - the lack of a coercion should
|
// with the unsizing - the lack of a coercion should
|
||||||
// be silent, as it causes a type mismatch later.
|
// be silent, as it causes a type mismatch later.
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
//@ known-bug: #130521
|
|
||||||
|
|
||||||
#![feature(dyn_compatible_for_dispatch)]
|
|
||||||
struct Vtable(dyn Cap<'static>);
|
|
||||||
|
|
||||||
trait Cap<'a> {}
|
|
||||||
|
|
||||||
union Transmute {
|
|
||||||
t: u128,
|
|
||||||
u: &'static Vtable,
|
|
||||||
}
|
|
||||||
|
|
||||||
const G: &Copy = unsafe { Transmute { t: 1 }.u };
|
|
71
tests/ui/dyn-compatibility/taint-const-eval.curr.stderr
Normal file
71
tests/ui/dyn-compatibility/taint-const-eval.curr.stderr
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
error[E0038]: the trait `Qux` cannot be made into an object
|
||||||
|
--> $DIR/taint-const-eval.rs:11:15
|
||||||
|
|
|
||||||
|
LL | static FOO: &(dyn Qux + Sync) = "desc";
|
||||||
|
| ^^^^^^^^^^^^^^ `Qux` cannot be made into an object
|
||||||
|
|
|
||||||
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||||
|
--> $DIR/taint-const-eval.rs:8:8
|
||||||
|
|
|
||||||
|
LL | trait Qux {
|
||||||
|
| --- this trait cannot be made into an object...
|
||||||
|
LL | fn bar();
|
||||||
|
| ^^^ ...because associated function `bar` has no `self` parameter
|
||||||
|
help: consider turning `bar` into a method by giving it a `&self` argument
|
||||||
|
|
|
||||||
|
LL | fn bar(&self);
|
||||||
|
| +++++
|
||||||
|
help: alternatively, consider constraining `bar` so it does not apply to trait objects
|
||||||
|
|
|
||||||
|
LL | fn bar() where Self: Sized;
|
||||||
|
| +++++++++++++++++
|
||||||
|
|
||||||
|
error[E0038]: the trait `Qux` cannot be made into an object
|
||||||
|
--> $DIR/taint-const-eval.rs:11:33
|
||||||
|
|
|
||||||
|
LL | static FOO: &(dyn Qux + Sync) = "desc";
|
||||||
|
| ^^^^^^ `Qux` cannot be made into an object
|
||||||
|
|
|
||||||
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||||
|
--> $DIR/taint-const-eval.rs:8:8
|
||||||
|
|
|
||||||
|
LL | trait Qux {
|
||||||
|
| --- this trait cannot be made into an object...
|
||||||
|
LL | fn bar();
|
||||||
|
| ^^^ ...because associated function `bar` has no `self` parameter
|
||||||
|
= note: required for the cast from `&'static str` to `&'static (dyn Qux + Sync + 'static)`
|
||||||
|
help: consider turning `bar` into a method by giving it a `&self` argument
|
||||||
|
|
|
||||||
|
LL | fn bar(&self);
|
||||||
|
| +++++
|
||||||
|
help: alternatively, consider constraining `bar` so it does not apply to trait objects
|
||||||
|
|
|
||||||
|
LL | fn bar() where Self: Sized;
|
||||||
|
| +++++++++++++++++
|
||||||
|
|
||||||
|
error[E0038]: the trait `Qux` cannot be made into an object
|
||||||
|
--> $DIR/taint-const-eval.rs:11:15
|
||||||
|
|
|
||||||
|
LL | static FOO: &(dyn Qux + Sync) = "desc";
|
||||||
|
| ^^^^^^^^^^^^^^ `Qux` cannot be made into an object
|
||||||
|
|
|
||||||
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||||
|
--> $DIR/taint-const-eval.rs:8:8
|
||||||
|
|
|
||||||
|
LL | trait Qux {
|
||||||
|
| --- this trait cannot be made into an object...
|
||||||
|
LL | fn bar();
|
||||||
|
| ^^^ ...because associated function `bar` has no `self` parameter
|
||||||
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||||
|
help: consider turning `bar` into a method by giving it a `&self` argument
|
||||||
|
|
|
||||||
|
LL | fn bar(&self);
|
||||||
|
| +++++
|
||||||
|
help: alternatively, consider constraining `bar` so it does not apply to trait objects
|
||||||
|
|
|
||||||
|
LL | fn bar() where Self: Sized;
|
||||||
|
| +++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0038`.
|
|
@ -0,0 +1,26 @@
|
||||||
|
error[E0038]: the trait `Qux` cannot be made into an object
|
||||||
|
--> $DIR/taint-const-eval.rs:11:33
|
||||||
|
|
|
||||||
|
LL | static FOO: &(dyn Qux + Sync) = "desc";
|
||||||
|
| ^^^^^^ `Qux` cannot be made into an object
|
||||||
|
|
|
||||||
|
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||||
|
--> $DIR/taint-const-eval.rs:8:8
|
||||||
|
|
|
||||||
|
LL | trait Qux {
|
||||||
|
| --- this trait cannot be made into an object...
|
||||||
|
LL | fn bar();
|
||||||
|
| ^^^ ...because associated function `bar` has no `self` parameter
|
||||||
|
= note: required for the cast from `&'static str` to `&'static (dyn Qux + Sync + 'static)`
|
||||||
|
help: consider turning `bar` into a method by giving it a `&self` argument
|
||||||
|
|
|
||||||
|
LL | fn bar(&self);
|
||||||
|
| +++++
|
||||||
|
help: alternatively, consider constraining `bar` so it does not apply to trait objects
|
||||||
|
|
|
||||||
|
LL | fn bar() where Self: Sized;
|
||||||
|
| +++++++++++++++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0038`.
|
16
tests/ui/dyn-compatibility/taint-const-eval.rs
Normal file
16
tests/ui/dyn-compatibility/taint-const-eval.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Test that we do not attempt to create dyn-incompatible trait objects in const eval.
|
||||||
|
|
||||||
|
//@ revisions: curr dyn_compatible_for_dispatch
|
||||||
|
|
||||||
|
#![cfg_attr(dyn_compatible_for_dispatch, feature(dyn_compatible_for_dispatch))]
|
||||||
|
|
||||||
|
trait Qux {
|
||||||
|
fn bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
static FOO: &(dyn Qux + Sync) = "desc";
|
||||||
|
//~^ the trait `Qux` cannot be made into an object
|
||||||
|
//[curr]~| the trait `Qux` cannot be made into an object
|
||||||
|
//[curr]~| the trait `Qux` cannot be made into an object
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Add table
Add a link
Reference in a new issue