mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 14:02:57 +00:00
Rollup merge of #112825 - compiler-errors:tait-defining-cycle, r=lcnr
Don't call `type_of` on TAIT in defining scope in new solver It's *never* productive to call `consider_auto_trait_candidate` on a TAIT in the defining scope, since it will always lead to a query cycle since we call `type_of` on the TAIT. So let's just don't. I've reserved this behavior just to `SolverMode::Normal` just to avoid any future problems, since this is *technically* incomplete since we're discarding a candidate that could *theoretically* apply. But given such candidate assembly *always* leads to a query cycle, I think it's relatively low risk, and I could be convinced otherwise and make this apply to both solver mode. I assume it's far less likely to be encountered in coherence, though. This is much more likely to encounter in the new solver, though it can also be encountered in the old solver too, so I'm happy to discuss whether this new behavior we even want in the first place... I encountered this in a couple of failing UI tests: * `tests/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs` * `tests/ui/type-alias-impl-trait/issue-93411.rs` r? `@lcnr`
This commit is contained in:
commit
de49a9f2f5
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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, U> = T`, but instead, `Foo<B, A> = B`, so that
|
||||
|
@ -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<T: Send, U> = impl NeedsSend<T>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires borrow-checking `define`...
|
||||
--> $DIR/dont-remap-tait-substs.rs:15:1
|
||||
|
|
||||
LL | fn define<A, B: Send>(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<T: Send, U> = impl NeedsSend<T>;
|
||||
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<T: Send, U> = impl NeedsSend<T>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires borrow-checking `define`...
|
||||
--> $DIR/dont-remap-tait-substs.rs:15:1
|
||||
|
|
||||
LL | fn define<A, B: Send>(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<T: Send, U> = impl NeedsSend<T>;
|
||||
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<T: Send, U> = impl NeedsSend<T>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires borrow-checking `define`...
|
||||
--> $DIR/dont-remap-tait-substs.rs:15:1
|
||||
|
|
||||
LL | fn define<A, B: Send>(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<T: Send, U> = impl NeedsSend<T>;
|
||||
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<T: Send, U> = impl NeedsSend<T>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires borrow-checking `define`...
|
||||
--> $DIR/dont-remap-tait-substs.rs:15:1
|
||||
|
|
||||
LL | fn define<A, B: Send>(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<T: Send, U> = impl NeedsSend<T>;
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
@ -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::<Foo>();
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= 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<T: Send>() {}
|
||||
| ^^^^ required by this bound in `needs_send`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
@ -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<T: Send>() {}
|
||||
|
||||
fn test() {
|
||||
needs_send::<Foo>();
|
||||
//[not_send]~^ ERROR type annotations needed: cannot satisfy `Foo: Send`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: Foo = ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user