Rollup merge of #136073 - compiler-errors:recursive-coro-always, r=oli-obk
Always compute coroutine layout for eagerly emitting recursive layout errors Detect recursive coroutine layouts even if we don't detect opaque type recursion in the new solver. This is for two reasons: 1. It helps us detect (bad) recursive async function calls in the new solver, which due to its approach to normalization causes us to not detect this via a recursive RPIT (since the opaques are more eagerly revealed in the opaque body). * Fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/137. 2. It helps us detect (bad) recursive async functions behind AFITs. See the AFIT test that changed for the old solver too. 3. It also greatly simplifies the recursive impl trait check, since I can remove some jankness around how it handles coroutines.
This commit is contained in:
commit
7ca29360a7
12 changed files with 37 additions and 95 deletions
|
@ -777,7 +777,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self,
|
||||
def_id: DefId,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
inspect_coroutine_fields: InspectCoroutineFields,
|
||||
) -> Result<Ty<'tcx>, Ty<'tcx>> {
|
||||
let mut visitor = OpaqueTypeExpander {
|
||||
seen_opaque_tys: FxHashSet::default(),
|
||||
|
@ -786,9 +785,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
found_recursion: false,
|
||||
found_any_recursion: false,
|
||||
check_recursion: true,
|
||||
expand_coroutines: true,
|
||||
tcx: self,
|
||||
inspect_coroutine_fields,
|
||||
};
|
||||
|
||||
let expanded_type = visitor.expand_opaque_ty(def_id, args).unwrap();
|
||||
|
@ -965,19 +962,11 @@ struct OpaqueTypeExpander<'tcx> {
|
|||
primary_def_id: Option<DefId>,
|
||||
found_recursion: bool,
|
||||
found_any_recursion: bool,
|
||||
expand_coroutines: bool,
|
||||
/// Whether or not to check for recursive opaque types.
|
||||
/// This is `true` when we're explicitly checking for opaque type
|
||||
/// recursion, and 'false' otherwise to avoid unnecessary work.
|
||||
check_recursion: bool,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
inspect_coroutine_fields: InspectCoroutineFields,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum InspectCoroutineFields {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeExpander<'tcx> {
|
||||
|
@ -1009,41 +998,6 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn expand_coroutine(&mut self, def_id: DefId, args: GenericArgsRef<'tcx>) -> Option<Ty<'tcx>> {
|
||||
if self.found_any_recursion {
|
||||
return None;
|
||||
}
|
||||
let args = args.fold_with(self);
|
||||
if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
|
||||
let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
|
||||
Some(expanded_ty) => *expanded_ty,
|
||||
None => {
|
||||
if matches!(self.inspect_coroutine_fields, InspectCoroutineFields::Yes) {
|
||||
for bty in self.tcx.bound_coroutine_hidden_types(def_id) {
|
||||
let hidden_ty = self.tcx.instantiate_bound_regions_with_erased(
|
||||
bty.instantiate(self.tcx, args),
|
||||
);
|
||||
self.fold_ty(hidden_ty);
|
||||
}
|
||||
}
|
||||
let expanded_ty = Ty::new_coroutine_witness(self.tcx, def_id, args);
|
||||
self.expanded_cache.insert((def_id, args), expanded_ty);
|
||||
expanded_ty
|
||||
}
|
||||
};
|
||||
if self.check_recursion {
|
||||
self.seen_opaque_tys.remove(&def_id);
|
||||
}
|
||||
Some(expanded_ty)
|
||||
} else {
|
||||
// If another opaque type that we contain is recursive, then it
|
||||
// will report the error, so we don't have to.
|
||||
self.found_any_recursion = true;
|
||||
self.found_recursion = def_id == *self.primary_def_id.as_ref().unwrap();
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
|
||||
|
@ -1052,19 +1006,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
|
|||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let mut t = if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
|
||||
if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) = *t.kind() {
|
||||
self.expand_opaque_ty(def_id, args).unwrap_or(t)
|
||||
} else if t.has_opaque_types() || t.has_coroutines() {
|
||||
} else if t.has_opaque_types() {
|
||||
t.super_fold_with(self)
|
||||
} else {
|
||||
t
|
||||
};
|
||||
if self.expand_coroutines {
|
||||
if let ty::CoroutineWitness(def_id, args) = *t.kind() {
|
||||
t = self.expand_coroutine(def_id, args).unwrap_or(t);
|
||||
}
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
|
||||
|
@ -1753,9 +1701,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
|
|||
found_recursion: false,
|
||||
found_any_recursion: false,
|
||||
check_recursion: false,
|
||||
expand_coroutines: false,
|
||||
tcx,
|
||||
inspect_coroutine_fields: InspectCoroutineFields::No,
|
||||
};
|
||||
val.fold_with(&mut visitor)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue