diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-01-05 20:39:52 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-05 20:39:52 +0100 |
| commit | 8309063e0a92c5602cb17da3135b8fda870360d2 (patch) | |
| tree | 2fb53485c91faf8f79bf8b67e7543caa42f1a3e1 | |
| parent | ea6129084eff284ea730d89eb9866b5af76e1b47 (diff) | |
| parent | 6a2bd5acd664e6bd118563ea9033245c624fec2e (diff) | |
| download | rust-8309063e0a92c5602cb17da3135b8fda870360d2.tar.gz rust-8309063e0a92c5602cb17da3135b8fda870360d2.zip | |
Rollup merge of #119506 - compiler-errors:visibilities-for-object-safety-error, r=Nilstrieb
Use `resolutions(()).effective_visiblities` to avoid cycle errors in `report_object_error` Inside of `report_object_error`, using the `effective_visibilities` query causes cycles since it calls `type_of`, which itself may call `typeck`, which may end up reporting its own object-safety errors. Fixes #119346 Fixes #119502
3 files changed, 110 insertions, 1 deletions
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 4aabe5c2922..e91411ffc7a 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -152,7 +152,10 @@ pub fn report_object_safety_error<'tcx>( }; let externally_visible = if !impls.is_empty() && let Some(def_id) = trait_def_id.as_local() - && tcx.effective_visibilities(()).is_exported(def_id) + // We may be executing this during typeck, which would result in cycle + // if we used effective_visibilities query, which looks into opaque types + // (and therefore calls typeck). + && tcx.resolutions(()).effective_visibilities.is_exported(def_id) { true } else { diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs new file mode 100644 index 00000000000..650cb3870d5 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs @@ -0,0 +1,28 @@ +trait Marker {} +impl Marker for u32 {} + +trait MyTrait { + fn foo(&self) -> impl Marker; +} + +struct Outer; + +impl MyTrait for Outer { + fn foo(&self) -> impl Marker { + 42 + } +} + +impl dyn MyTrait { + //~^ ERROR the trait `MyTrait` cannot be made into an object + fn other(&self) -> impl Marker { + //~^ ERROR the trait `MyTrait` cannot be made into an object + MyTrait::foo(&self) + //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied + //~| ERROR the trait `MyTrait` cannot be made into an object + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr new file mode 100644 index 00000000000..01de3e53195 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr @@ -0,0 +1,78 @@ +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:22 + | +LL | MyTrait::foo(&self) + | ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | | + | required by a bound introduced by this call + | + = help: the trait `MyTrait` is implemented for `Outer` + +error[E0038]: the trait `MyTrait` cannot be made into an object + --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^ `MyTrait` cannot be made into an object + | +note: for a trait to be "object safe" 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/cycle-effective-visibilities-during-object-safety.rs:5:22 + | +LL | trait MyTrait { + | ------- this trait cannot be made into an object... +LL | fn foo(&self) -> impl Marker; + | ^^^^^^^^^^^ ...because method `foo` references an `impl Trait` type in its return type + = help: consider moving `foo` to another trait + = help: only type `Outer` implements the trait, consider using it directly instead + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied + --> $DIR/cycle-effective-visibilities-during-object-safety.rs:20:9 + | +LL | MyTrait::foo(&self) + | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` + | + = help: the trait `MyTrait` is implemented for `Outer` + +error[E0038]: the trait `MyTrait` cannot be made into an object + --> $DIR/cycle-effective-visibilities-during-object-safety.rs:16:6 + | +LL | impl dyn MyTrait { + | ^^^^^^^^^^^ `MyTrait` cannot be made into an object + | +note: for a trait to be "object safe" 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/cycle-effective-visibilities-during-object-safety.rs:5:22 + | +LL | trait MyTrait { + | ------- this trait cannot be made into an object... +LL | fn foo(&self) -> impl Marker; + | ^^^^^^^^^^^ ...because method `foo` references an `impl Trait` type in its return type + = help: consider moving `foo` to another trait + = help: only type `Outer` implements the trait, consider using it directly instead + +error[E0038]: the trait `MyTrait` cannot be made into an object + --> $DIR/cycle-effective-visibilities-during-object-safety.rs:18:15 + | +LL | fn other(&self) -> impl Marker { + | ^^^^ `MyTrait` cannot be made into an object + | +note: for a trait to be "object safe" 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/cycle-effective-visibilities-during-object-safety.rs:5:22 + | +LL | trait MyTrait { + | ------- this trait cannot be made into an object... +LL | fn foo(&self) -> impl Marker; + | ^^^^^^^^^^^ ...because method `foo` references an `impl Trait` type in its return type + = help: consider moving `foo` to another trait + = help: only type `Outer` implements the trait, consider using it directly instead + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. |
