More
This commit is contained in:
parent
7c1661f945
commit
f943f73db4
19 changed files with 189 additions and 187 deletions
|
|
@ -967,7 +967,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
|
||||
debug_assert!(!self.next_trait_solver());
|
||||
match self.typing_mode() {
|
||||
TypingMode::Analysis { defining_opaque_types, stalled_generators: _ }
|
||||
TypingMode::Analysis {
|
||||
defining_opaque_types_and_generators: defining_opaque_types,
|
||||
}
|
||||
| TypingMode::Borrowck { defining_opaque_types } => {
|
||||
id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
|
||||
}
|
||||
|
|
@ -1262,7 +1264,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// to handle them without proper canonicalization. This means we may cause cycle
|
||||
// errors and fail to reveal opaques while inside of bodies. We should rename this
|
||||
// function and require explicit comments on all use-sites in the future.
|
||||
ty::TypingMode::Analysis { defining_opaque_types: _, stalled_generators: _ }
|
||||
ty::TypingMode::Analysis { defining_opaque_types_and_generators: _ }
|
||||
| ty::TypingMode::Borrowck { defining_opaque_types: _ } => {
|
||||
TypingMode::non_body_analysis()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ rustc_queries! {
|
|||
key: LocalDefId
|
||||
) -> &'tcx ty::List<LocalDefId> {
|
||||
desc {
|
||||
|tcx| "computing the opaque types defined by `{}`",
|
||||
|tcx| "computing the coroutines defined within `{}`",
|
||||
tcx.def_path_str(key.to_def_id())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -366,11 +366,11 @@ macro_rules! define_callbacks {
|
|||
|
||||
pub type Storage<'tcx> = <$($K)* as keys::Key>::Cache<Erase<$V>>;
|
||||
|
||||
// Ensure that keys grow no larger than 96 bytes by accident.
|
||||
// Ensure that keys grow no larger than 88 bytes by accident.
|
||||
// Increase this limit if necessary, but do try to keep the size low if possible
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const _: () = {
|
||||
if size_of::<Key<'static>>() > 96 {
|
||||
if size_of::<Key<'static>>() > 88 {
|
||||
panic!("{}", concat!(
|
||||
"the query `",
|
||||
stringify!($name),
|
||||
|
|
|
|||
|
|
@ -678,11 +678,18 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
self.opaque_types_defined_by(defining_anchor)
|
||||
}
|
||||
|
||||
fn stalled_generators_within(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds {
|
||||
fn opaque_types_and_generators_defined_by(
|
||||
self,
|
||||
defining_anchor: Self::LocalDefId,
|
||||
) -> Self::LocalDefIds {
|
||||
if self.next_trait_solver_globally() {
|
||||
self.stalled_generators_within(defining_anchor)
|
||||
self.mk_local_def_ids_from_iter(
|
||||
self.opaque_types_defined_by(defining_anchor)
|
||||
.iter()
|
||||
.chain(self.stalled_generators_within(defining_anchor)),
|
||||
)
|
||||
} else {
|
||||
ty::List::empty()
|
||||
self.opaque_types_defined_by(defining_anchor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2914,11 +2921,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.interners.intern_clauses(clauses)
|
||||
}
|
||||
|
||||
pub fn mk_local_def_ids(self, clauses: &[LocalDefId]) -> &'tcx List<LocalDefId> {
|
||||
pub fn mk_local_def_ids(self, def_ids: &[LocalDefId]) -> &'tcx List<LocalDefId> {
|
||||
// FIXME consider asking the input slice to be sorted to avoid
|
||||
// re-interning permutations, in which case that would be asserted
|
||||
// here.
|
||||
self.intern_local_def_ids(clauses)
|
||||
self.intern_local_def_ids(def_ids)
|
||||
}
|
||||
|
||||
pub fn mk_local_def_ids_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
|
|
|
|||
|
|
@ -329,10 +329,7 @@ where
|
|||
TypingMode::Coherence | TypingMode::PostAnalysis => false,
|
||||
// During analysis, opaques are rigid unless they may be defined by
|
||||
// the current body.
|
||||
TypingMode::Analysis {
|
||||
defining_opaque_types: non_rigid_opaques,
|
||||
stalled_generators: _,
|
||||
}
|
||||
TypingMode::Analysis { defining_opaque_types_and_generators: non_rigid_opaques }
|
||||
| TypingMode::Borrowck { defining_opaque_types: non_rigid_opaques }
|
||||
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: non_rigid_opaques } => {
|
||||
!def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id))
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@ where
|
|||
);
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||
}
|
||||
TypingMode::Analysis { defining_opaque_types, stalled_generators: _ } => {
|
||||
TypingMode::Analysis { defining_opaque_types_and_generators } => {
|
||||
let Some(def_id) = opaque_ty
|
||||
.def_id
|
||||
.as_local()
|
||||
.filter(|&def_id| defining_opaque_types.contains(&def_id))
|
||||
.filter(|&def_id| defining_opaque_types_and_generators.contains(&def_id))
|
||||
else {
|
||||
self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
|
||||
return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
|
||||
|
|
|
|||
|
|
@ -208,20 +208,9 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// TODO:
|
||||
if let ty::CoroutineWitness(def_id, _) = goal.predicate.self_ty().kind() {
|
||||
match ecx.typing_mode() {
|
||||
TypingMode::Analysis { stalled_generators, defining_opaque_types: _ } => {
|
||||
if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
|
||||
{
|
||||
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
|
||||
}
|
||||
}
|
||||
TypingMode::Coherence
|
||||
| TypingMode::PostAnalysis
|
||||
| TypingMode::Borrowck { defining_opaque_types: _ }
|
||||
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
|
||||
}
|
||||
// We need to make sure to stall any coroutines we are inferring to avoid query cycles.
|
||||
if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
|
||||
return cand;
|
||||
}
|
||||
|
||||
ecx.probe_and_evaluate_goal_for_constituent_tys(
|
||||
|
|
@ -275,20 +264,9 @@ where
|
|||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
if let ty::CoroutineWitness(def_id, _) = goal.predicate.self_ty().kind() {
|
||||
match ecx.typing_mode() {
|
||||
TypingMode::Analysis { stalled_generators, defining_opaque_types: _ } => {
|
||||
if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
|
||||
{
|
||||
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
|
||||
}
|
||||
}
|
||||
TypingMode::Coherence
|
||||
| TypingMode::PostAnalysis
|
||||
| TypingMode::Borrowck { defining_opaque_types: _ }
|
||||
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
|
||||
}
|
||||
// We need to make sure to stall any coroutines we are inferring to avoid query cycles.
|
||||
if let Some(cand) = ecx.try_stall_coroutine_witness(goal.predicate.self_ty()) {
|
||||
return cand;
|
||||
}
|
||||
|
||||
ecx.probe_and_evaluate_goal_for_constituent_tys(
|
||||
|
|
@ -1400,4 +1378,28 @@ where
|
|||
let candidates = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All);
|
||||
self.merge_trait_candidates(goal, candidates)
|
||||
}
|
||||
|
||||
fn try_stall_coroutine_witness(
|
||||
&mut self,
|
||||
self_ty: I::Ty,
|
||||
) -> Option<Result<Candidate<I>, NoSolution>> {
|
||||
if let ty::CoroutineWitness(def_id, _) = self_ty.kind() {
|
||||
match self.typing_mode() {
|
||||
TypingMode::Analysis {
|
||||
defining_opaque_types_and_generators: stalled_generators,
|
||||
} => {
|
||||
if def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id))
|
||||
{
|
||||
return Some(self.forced_ambiguity(MaybeCause::Ambiguity));
|
||||
}
|
||||
}
|
||||
TypingMode::Coherence
|
||||
| TypingMode::PostAnalysis
|
||||
| TypingMode::Borrowck { defining_opaque_types: _ }
|
||||
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use rustc_middle::ty::{
|
|||
};
|
||||
use rustc_next_trait_solver::solve::{GenerateProofTree, HasChanged, SolverDelegateEvalExt as _};
|
||||
use rustc_span::Span;
|
||||
use rustc_type_ir::data_structures::DelayedSet;
|
||||
use tracing::instrument;
|
||||
|
||||
use self::derive_errors::*;
|
||||
|
|
@ -217,26 +218,30 @@ where
|
|||
&mut self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
) -> PredicateObligations<'tcx> {
|
||||
self.obligations.drain_pending(|obl| {
|
||||
let stalled_generators = match infcx.typing_mode() {
|
||||
TypingMode::Analysis { defining_opaque_types: _, stalled_generators } => {
|
||||
stalled_generators
|
||||
}
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Borrowck { defining_opaque_types: _ }
|
||||
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ }
|
||||
| TypingMode::PostAnalysis => return false,
|
||||
};
|
||||
|
||||
if stalled_generators.is_empty() {
|
||||
return false;
|
||||
let stalled_generators = match infcx.typing_mode() {
|
||||
TypingMode::Analysis { defining_opaque_types_and_generators } => {
|
||||
defining_opaque_types_and_generators
|
||||
}
|
||||
TypingMode::Coherence
|
||||
| TypingMode::Borrowck { defining_opaque_types: _ }
|
||||
| TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ }
|
||||
| TypingMode::PostAnalysis => return Default::default(),
|
||||
};
|
||||
|
||||
if stalled_generators.is_empty() {
|
||||
return Default::default();
|
||||
}
|
||||
|
||||
self.obligations.drain_pending(|obl| {
|
||||
infcx.probe(|_| {
|
||||
infcx
|
||||
.visit_proof_tree(
|
||||
obl.as_goal(),
|
||||
&mut StalledOnCoroutines { stalled_generators, span: obl.cause.span },
|
||||
&mut StalledOnCoroutines {
|
||||
stalled_generators,
|
||||
span: obl.cause.span,
|
||||
cache: Default::default(),
|
||||
},
|
||||
)
|
||||
.is_break()
|
||||
})
|
||||
|
|
@ -244,10 +249,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Detect if a goal is stalled on a coroutine that is owned by the current typeck root.
|
||||
///
|
||||
/// This function can (erroneously) fail to detect a predicate, i.e. it doesn't need to
|
||||
/// be complete. However, this will lead to ambiguity errors, so we want to make it
|
||||
/// accurate.
|
||||
///
|
||||
/// This function can be also return false positives, which will lead to poor diagnostics
|
||||
/// so we want to keep this visitor *precise* too.
|
||||
struct StalledOnCoroutines<'tcx> {
|
||||
stalled_generators: &'tcx ty::List<LocalDefId>,
|
||||
span: Span,
|
||||
// TODO: Cache
|
||||
cache: DelayedSet<Ty<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> inspect::ProofTreeVisitor<'tcx> for StalledOnCoroutines<'tcx> {
|
||||
|
|
@ -272,6 +285,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for StalledOnCoroutines<'tcx> {
|
|||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
||||
if !self.cache.insert(ty) {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
if let ty::CoroutineWitness(def_id, _) = *ty.kind()
|
||||
&& def_id.as_local().is_some_and(|def_id| self.stalled_generators.contains(&def_id))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
|
|
@ -60,7 +59,8 @@ where
|
|||
/// entered before passing `value` to the function. This is currently needed for
|
||||
/// `normalize_erasing_regions`, which skips binders as it walks through a type.
|
||||
///
|
||||
/// TODO: doc
|
||||
/// This returns a set of stalled obligations if the typing mode of the underlying infcx
|
||||
/// has any stalled coroutine def ids.
|
||||
pub fn deeply_normalize_with_skipped_universes_and_ambiguous_goals<'tcx, T, E>(
|
||||
at: At<'_, 'tcx>,
|
||||
value: T,
|
||||
|
|
@ -72,16 +72,10 @@ where
|
|||
{
|
||||
let fulfill_cx = FulfillmentCtxt::new(at.infcx);
|
||||
let mut folder =
|
||||
NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData };
|
||||
NormalizationFolder { at, fulfill_cx, depth: 0, universes, stalled_goals: vec![] };
|
||||
let value = value.try_fold_with(&mut folder)?;
|
||||
let goals = folder
|
||||
.fulfill_cx
|
||||
.drain_stalled_obligations_for_coroutines(at.infcx)
|
||||
.into_iter()
|
||||
.map(|obl| obl.as_goal())
|
||||
.collect();
|
||||
let errors = folder.fulfill_cx.select_all_or_error(at.infcx);
|
||||
if errors.is_empty() { Ok((value, goals)) } else { Err(errors) }
|
||||
if errors.is_empty() { Ok((value, folder.stalled_goals)) } else { Err(errors) }
|
||||
}
|
||||
|
||||
struct NormalizationFolder<'me, 'tcx, E> {
|
||||
|
|
@ -89,7 +83,7 @@ struct NormalizationFolder<'me, 'tcx, E> {
|
|||
fulfill_cx: FulfillmentCtxt<'tcx, E>,
|
||||
depth: usize,
|
||||
universes: Vec<Option<UniverseIndex>>,
|
||||
_errors: PhantomData<E>,
|
||||
stalled_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
|
||||
|
|
@ -130,10 +124,7 @@ where
|
|||
);
|
||||
|
||||
self.fulfill_cx.register_predicate_obligation(infcx, obligation);
|
||||
let errors = self.fulfill_cx.select_where_possible(infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
self.select_all_and_stall_coroutine_predicates()?;
|
||||
|
||||
// Alias is guaranteed to be fully structurally resolved,
|
||||
// so we can super fold here.
|
||||
|
|
@ -184,6 +175,27 @@ where
|
|||
self.depth -= 1;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn select_all_and_stall_coroutine_predicates(&mut self) -> Result<(), Vec<E>> {
|
||||
let errors = self.fulfill_cx.select_where_possible(self.at.infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
|
||||
self.stalled_goals.extend(
|
||||
self.fulfill_cx
|
||||
.drain_stalled_obligations_for_coroutines(self.at.infcx)
|
||||
.into_iter()
|
||||
.map(|obl| obl.as_goal()),
|
||||
);
|
||||
|
||||
let errors = self.fulfill_cx.collect_remaining_errors(self.at.infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, E> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx, E>
|
||||
|
|
|
|||
|
|
@ -1498,7 +1498,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
// However, if we disqualify *all* goals from being cached, perf suffers.
|
||||
// This is likely fixed by better caching in general in the new solver.
|
||||
// See: <https://github.com/rust-lang/rust/issues/132064>.
|
||||
TypingMode::Analysis { defining_opaque_types, stalled_generators: _ }
|
||||
TypingMode::Analysis {
|
||||
defining_opaque_types_and_generators: defining_opaque_types,
|
||||
}
|
||||
| TypingMode::Borrowck { defining_opaque_types } => {
|
||||
defining_opaque_types.is_empty() || !pred.has_opaque_types()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ mod needs_drop;
|
|||
mod opaque_types;
|
||||
mod representability;
|
||||
pub mod sig_types;
|
||||
mod stalled_generators;
|
||||
mod structural_match;
|
||||
mod ty;
|
||||
|
||||
|
|
@ -50,4 +51,5 @@ pub fn provide(providers: &mut Providers) {
|
|||
ty::provide(providers);
|
||||
instance::provide(providers);
|
||||
structural_match::provide(providers);
|
||||
stalled_generators::provide(providers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_middle::query::Providers;
|
||||
|
|
@ -356,51 +355,6 @@ fn opaque_types_defined_by<'tcx>(
|
|||
tcx.mk_local_def_ids(&collector.opaques)
|
||||
}
|
||||
|
||||
// TODO: Move this out of `opaque_types`
|
||||
fn stalled_generators_within<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: LocalDefId,
|
||||
) -> &'tcx ty::List<LocalDefId> {
|
||||
if !tcx.next_trait_solver_globally() {
|
||||
return ty::List::empty();
|
||||
}
|
||||
|
||||
let body = tcx.hir_body_owned_by(item);
|
||||
let mut collector =
|
||||
StalledGeneratorVisitor { tcx, root_def_id: item.to_def_id(), stalled_coroutines: vec![] };
|
||||
collector.visit_body(body);
|
||||
tcx.mk_local_def_ids(&collector.stalled_coroutines)
|
||||
}
|
||||
|
||||
struct StalledGeneratorVisitor<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
root_def_id: DefId,
|
||||
stalled_coroutines: Vec<LocalDefId>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for StalledGeneratorVisitor<'tcx> {
|
||||
fn visit_nested_body(&mut self, id: hir::BodyId) {
|
||||
if self.tcx.typeck_root_def_id(self.tcx.hir_body_owner_def_id(id).to_def_id())
|
||||
== self.root_def_id
|
||||
{
|
||||
let body = self.tcx.hir_body(id);
|
||||
self.visit_body(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::ExprKind::Closure(&hir::Closure {
|
||||
def_id,
|
||||
kind: hir::ClosureKind::Coroutine(_),
|
||||
..
|
||||
}) = ex.kind
|
||||
{
|
||||
self.stalled_coroutines.push(def_id);
|
||||
}
|
||||
intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { opaque_types_defined_by, stalled_generators_within, ..*providers };
|
||||
*providers = Providers { opaque_types_defined_by, ..*providers };
|
||||
}
|
||||
|
|
|
|||
54
compiler/rustc_ty_utils/src/stalled_generators.rs
Normal file
54
compiler/rustc_ty_utils/src/stalled_generators.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::intravisit;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
||||
fn stalled_generators_within<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
item: LocalDefId,
|
||||
) -> &'tcx ty::List<LocalDefId> {
|
||||
if !tcx.next_trait_solver_globally() {
|
||||
return ty::List::empty();
|
||||
}
|
||||
|
||||
let body = tcx.hir_body_owned_by(item);
|
||||
let mut collector =
|
||||
StalledGeneratorVisitor { tcx, root_def_id: item.to_def_id(), stalled_coroutines: vec![] };
|
||||
collector.visit_body(body);
|
||||
tcx.mk_local_def_ids(&collector.stalled_coroutines)
|
||||
}
|
||||
|
||||
struct StalledGeneratorVisitor<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
root_def_id: DefId,
|
||||
stalled_coroutines: Vec<LocalDefId>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for StalledGeneratorVisitor<'tcx> {
|
||||
fn visit_nested_body(&mut self, id: hir::BodyId) {
|
||||
if self.tcx.typeck_root_def_id(self.tcx.hir_body_owner_def_id(id).to_def_id())
|
||||
== self.root_def_id
|
||||
{
|
||||
let body = self.tcx.hir_body(id);
|
||||
self.visit_body(body);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::ExprKind::Closure(&hir::Closure {
|
||||
def_id,
|
||||
kind: hir::ClosureKind::Coroutine(_),
|
||||
..
|
||||
}) = ex.kind
|
||||
{
|
||||
self.stalled_coroutines.push(def_id);
|
||||
}
|
||||
intravisit::walk_expr(self, ex);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { stalled_generators_within, ..*providers };
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ pub enum TypingMode<I: Interner> {
|
|||
/// let x: <() as Assoc>::Output = true;
|
||||
/// }
|
||||
/// ```
|
||||
Analysis { defining_opaque_types: I::LocalDefIds, stalled_generators: I::LocalDefIds },
|
||||
Analysis { defining_opaque_types_and_generators: I::LocalDefIds },
|
||||
/// The behavior during MIR borrowck is identical to `TypingMode::Analysis`
|
||||
/// except that the initial value for opaque types is the type computed during
|
||||
/// HIR typeck with unique unconstrained region inference variables.
|
||||
|
|
@ -94,25 +94,24 @@ pub enum TypingMode<I: Interner> {
|
|||
impl<I: Interner> TypingMode<I> {
|
||||
/// Analysis outside of a body does not define any opaque types.
|
||||
pub fn non_body_analysis() -> TypingMode<I> {
|
||||
TypingMode::Analysis {
|
||||
defining_opaque_types: Default::default(),
|
||||
stalled_generators: Default::default(),
|
||||
}
|
||||
TypingMode::Analysis { defining_opaque_types_and_generators: Default::default() }
|
||||
}
|
||||
|
||||
pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
|
||||
TypingMode::Analysis {
|
||||
defining_opaque_types: cx.opaque_types_defined_by(body_def_id),
|
||||
stalled_generators: cx.stalled_generators_within(body_def_id),
|
||||
defining_opaque_types_and_generators: cx
|
||||
.opaque_types_and_generators_defined_by(body_def_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// While typechecking a body, we need to be able to define the opaque
|
||||
/// types defined by that body.
|
||||
///
|
||||
/// FIXME: This will be removed because it's generally not correct to define
|
||||
/// opaques outside of HIR typeck.
|
||||
pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
|
||||
TypingMode::Analysis {
|
||||
defining_opaque_types: cx.opaque_types_defined_by(body_def_id),
|
||||
stalled_generators: Default::default(),
|
||||
defining_opaque_types_and_generators: cx.opaque_types_defined_by(body_def_id),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -332,7 +332,10 @@ pub trait Interner:
|
|||
|
||||
fn opaque_types_defined_by(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds;
|
||||
|
||||
fn stalled_generators_within(self, defining_anchor: Self::LocalDefId) -> Self::LocalDefIds;
|
||||
fn opaque_types_and_generators_defined_by(
|
||||
self,
|
||||
defining_anchor: Self::LocalDefId,
|
||||
) -> Self::LocalDefIds;
|
||||
}
|
||||
|
||||
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to return `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
|
||||
error[E0271]: type mismatch resolving `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25} == ()`
|
||||
--> $DIR/is-not-fn.rs:8:14
|
||||
|
|
||||
LL | needs_fn(async || {});
|
||||
| -------- ^^^^^^^^^^^ expected `()`, found `async` closure body
|
||||
| -------- ^^^^^^^^^^^ types differ
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found `async` closure body `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
|
||||
note: required by a bound in `needs_fn`
|
||||
--> $DIR/is-not-fn.rs:7:25
|
||||
|
|
||||
|
|
|
|||
|
|
@ -6,5 +6,6 @@
|
|||
fn main() {
|
||||
fn needs_fn(x: impl FnOnce()) {}
|
||||
needs_fn(async || {});
|
||||
//~^ ERROR expected `{async closure@is-not-fn.rs:8:14}` to return `()`
|
||||
//[current]~^ ERROR expected `{async closure@is-not-fn.rs:8:14}` to return `()`
|
||||
//[next]~^^ ERROR type mismatch resolving `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25} == ()`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
error[E0391]: cycle detected when type-checking `foo`
|
||||
--> $DIR/clone-rpit.rs:13:1
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>() -> impl Clone {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires coroutine witness types for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires building MIR for `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires match-checking `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
note: ...which requires type-checking `foo::{closure#0}`...
|
||||
--> $DIR/clone-rpit.rs:15:5
|
||||
|
|
||||
LL | move |_: ()| {
|
||||
| ^^^^^^^^^^^^
|
||||
= note: ...which again requires type-checking `foo`, completing the cycle
|
||||
note: cycle used when match-checking `foo`
|
||||
--> $DIR/clone-rpit.rs:13:1
|
||||
|
|
||||
LL | pub fn foo<'a, 'b>() -> impl Clone {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[current] check-pass
|
||||
//@[next] known-bug: trait-system-refactor-initiative#82
|
||||
//@ check-pass
|
||||
|
||||
#![feature(coroutines, coroutine_trait, coroutine_clone)]
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue