From 03e9effaf773e497fcdcfef213eaa479483922b3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 4 Jan 2024 01:48:39 +0000 Subject: [PATCH] Use `resolutions(()).effective_visiblities` to avoid cycle errors --- .../src/traits/error_reporting/mod.rs | 5 +- ...ctive-visibilities-during-object-safety.rs | 28 +++++++ ...e-visibilities-during-object-safety.stderr | 78 +++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.rs create mode 100644 tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index d89c205da3f52..34163111d3c78 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -132,7 +132,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 0000000000000..650cb3870d581 --- /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 0000000000000..ceba7b4550db8 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-object-safety.stderr @@ -0,0 +1,78 @@ +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 + --> $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 + --> $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: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 + --> $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: aborting due to 6 previous errors + +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`.