From 388c230cf77c633eeb9eee2e5388ce957c69797b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 28 Jun 2023 17:41:04 +0000 Subject: [PATCH] Don't call type_of on TAIT in defining scope in new solver --- .../src/solve/eval_ctxt.rs | 2 +- .../src/solve/trait_goals.rs | 27 +++++ .../new-solver/dont-remap-tait-substs.rs | 2 +- .../new-solver/dont-remap-tait-substs.stderr | 99 ------------------- ..._of-tait-in-defining-scope.not_send.stderr | 16 +++ .../dont-type_of-tait-in-defining-scope.rs | 22 +++++ 6 files changed, 67 insertions(+), 101 deletions(-) delete mode 100644 tests/ui/traits/new-solver/dont-remap-tait-substs.stderr create mode 100644 tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr create mode 100644 tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index 6fb788e296f..74dfbdddbab 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -837,7 +837,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } - pub(super) fn can_define_opaque_ty(&mut self, def_id: LocalDefId) -> bool { + pub(super) fn can_define_opaque_ty(&self, def_id: LocalDefId) -> bool { self.infcx.opaque_type_origin(def_id).is_some() } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 7ff47295e7c..cd68626bed1 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -7,6 +7,7 @@ use rustc_hir::{LangItem, Movability}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::util::supertraits; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult}; +use rustc_middle::traits::Reveal; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; @@ -118,6 +119,32 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { return result; } + // Don't call `type_of` on a local TAIT that's in the defining scope, + // since that may require calling `typeck` on the same item we're + // currently type checking, which will result in a fatal cycle that + // ideally we want to avoid, since we can make progress on this goal + // via an alias bound or a locally-inferred hidden type instead. + // + // Also, don't call `type_of` on a TAIT in `Reveal::All` mode, since + // we already normalize the self type in + // `assemble_candidates_after_normalizing_self_ty`, and we'd + // just be registering an identical candidate here. + // + // Returning `Err(NoSolution)` here is ok in `SolverMode::Coherence` + // since we'll always be registering an ambiguous candidate in + // `assemble_candidates_after_normalizing_self_ty` due to normalizing + // the TAIT. + if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() { + if matches!(goal.param_env.reveal(), Reveal::All) + || opaque_ty + .def_id + .as_local() + .is_some_and(|def_id| ecx.can_define_opaque_ty(def_id)) + { + return Err(NoSolution); + } + } + ecx.probe_and_evaluate_goal_for_constituent_tys( goal, structural_traits::instantiate_constituent_tys_for_auto_trait, diff --git a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs index 08c08e83076..028222f4e6d 100644 --- a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs +++ b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs @@ -1,5 +1,5 @@ // compile-flags: -Ztrait-solver=next -// known-bug: #112825 +// check-pass // Makes sure we don't prepopulate the MIR typeck of `define` // with `Foo = T`, but instead, `Foo = B`, so that diff --git a/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr b/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr deleted file mode 100644 index 769eea7dfd6..00000000000 --- a/tests/ui/traits/new-solver/dont-remap-tait-substs.stderr +++ /dev/null @@ -1,99 +0,0 @@ -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/dont-remap-tait-substs.rs:10:24 - | -LL | type Foo = impl NeedsSend; - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `define`... - --> $DIR/dont-remap-tait-substs.rs:15:1 - | -LL | fn define(a: A, b: B) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/dont-remap-tait-substs.rs:8:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | type Foo = impl NeedsSend; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/dont-remap-tait-substs.rs:10:24 - | -LL | type Foo = impl NeedsSend; - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `define`... - --> $DIR/dont-remap-tait-substs.rs:15:1 - | -LL | fn define(a: A, b: B) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/dont-remap-tait-substs.rs:8:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | type Foo = impl NeedsSend; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/dont-remap-tait-substs.rs:10:24 - | -LL | type Foo = impl NeedsSend; - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `define`... - --> $DIR/dont-remap-tait-substs.rs:15:1 - | -LL | fn define(a: A, b: B) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/dont-remap-tait-substs.rs:8:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | type Foo = impl NeedsSend; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - -error[E0391]: cycle detected when computing type of `Foo::{opaque#0}` - --> $DIR/dont-remap-tait-substs.rs:10:24 - | -LL | type Foo = impl NeedsSend; - | ^^^^^^^^^^^^^^^^^ - | -note: ...which requires borrow-checking `define`... - --> $DIR/dont-remap-tait-substs.rs:15:1 - | -LL | fn define(a: A, b: B) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle -note: cycle used when checking item types in top-level module - --> $DIR/dont-remap-tait-substs.rs:8:1 - | -LL | / #![feature(type_alias_impl_trait)] -LL | | -LL | | type Foo = impl NeedsSend; -LL | | -... | -LL | | -LL | | fn main() {} - | |____________^ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr new file mode 100644 index 00000000000..ec1c3231abc --- /dev/null +++ b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.not_send.stderr @@ -0,0 +1,16 @@ +error[E0283]: type annotations needed: cannot satisfy `Foo: Send` + --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:5 + | +LL | needs_send::(); + | ^^^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `Foo: Send` +note: required by a bound in `needs_send` + --> $DIR/dont-type_of-tait-in-defining-scope.rs:13:18 + | +LL | fn needs_send() {} + | ^^^^ required by this bound in `needs_send` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs new file mode 100644 index 00000000000..5a0dcd0e8cc --- /dev/null +++ b/tests/ui/traits/new-solver/dont-type_of-tait-in-defining-scope.rs @@ -0,0 +1,22 @@ +// revisions: is_send not_send +// compile-flags: -Ztrait-solver=next +//[is_send] check-pass + +#![feature(type_alias_impl_trait)] + +#[cfg(is_send)] +type Foo = impl Send; + +#[cfg(not_send)] +type Foo = impl Sized; + +fn needs_send() {} + +fn test() { + needs_send::(); + //[not_send]~^ ERROR type annotations needed: cannot satisfy `Foo: Send` +} + +fn main() { + let _: Foo = (); +}