Skip to content

Commit 8725c5d

Browse files
Don't call type_of on TAIT in defining scope in new solver
1 parent 97279e9 commit 8725c5d

File tree

4 files changed

+66
-1
lines changed

4 files changed

+66
-1
lines changed

compiler/rustc_trait_selection/src/solve/eval_ctxt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
785785
}
786786
}
787787

788-
pub(super) fn can_define_opaque_ty(&mut self, def_id: LocalDefId) -> bool {
788+
pub(super) fn can_define_opaque_ty(&self, def_id: LocalDefId) -> bool {
789789
self.infcx.opaque_type_origin(def_id).is_some()
790790
}
791791

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+27
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_infer::traits::query::NoSolution;
88
use rustc_infer::traits::util::supertraits;
99
use rustc_middle::traits::solve::inspect::CandidateKind;
1010
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
11+
use rustc_middle::traits::Reveal;
1112
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
1213
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
1314
use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
@@ -120,6 +121,32 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
120121
return result;
121122
}
122123

124+
// Don't call `type_of` on a local TAIT that's in the defining scope,
125+
// since that may require calling `typeck` on the same item we're
126+
// currently type checking, which will result in a fatal cycle that
127+
// ideally we want to avoid, since we can make progress on this goal
128+
// via an alias bound or a locally-inferred hidden type instead.
129+
//
130+
// Also, don't call `type_of` on a TAIT in `Reveal::All` mode, since
131+
// we already normalize the self type in
132+
// `assemble_candidates_after_normalizing_self_ty`, and we'd
133+
// just be registering an identical candidate here.
134+
//
135+
// Returning `Err(NoSolution)` here is ok in `SolverMode::Coherence`
136+
// since we'll always be registering an ambiguous candidate in
137+
// `assemble_candidates_after_normalizing_self_ty` due to normalizing
138+
// the TAIT.
139+
if let ty::Alias(ty::Opaque, opaque_ty) = goal.predicate.self_ty().kind() {
140+
if matches!(goal.param_env.reveal(), Reveal::All)
141+
|| opaque_ty
142+
.def_id
143+
.as_local()
144+
.is_some_and(|def_id| ecx.can_define_opaque_ty(def_id))
145+
{
146+
return Err(NoSolution);
147+
}
148+
}
149+
123150
ecx.probe_and_evaluate_goal_for_constituent_tys(
124151
goal,
125152
structural_traits::instantiate_constituent_tys_for_auto_trait,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
2+
--> $DIR/dont-type_of-tait-in-defining-scope.rs:16:5
3+
|
4+
LL | needs_send::<Foo>();
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: cannot satisfy `Foo: Send`
8+
note: required by a bound in `needs_send`
9+
--> $DIR/dont-type_of-tait-in-defining-scope.rs:13:18
10+
|
11+
LL | fn needs_send<T: Send>() {}
12+
| ^^^^ required by this bound in `needs_send`
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0283`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// revisions: is_send not_send
2+
// compile-flags: -Ztrait-solver=next
3+
//[is_send] check-pass
4+
5+
#![feature(type_alias_impl_trait)]
6+
7+
#[cfg(is_send)]
8+
type Foo = impl Send;
9+
10+
#[cfg(not_send)]
11+
type Foo = impl Sized;
12+
13+
fn needs_send<T: Send>() {}
14+
15+
fn test() {
16+
needs_send::<Foo>();
17+
//[not_send]~^ ERROR type annotations needed: cannot satisfy `Foo: Send`
18+
}
19+
20+
fn main() {
21+
let _: Foo = ();
22+
}

0 commit comments

Comments
 (0)