Rollup merge of #103226 - compiler-errors:delay-if-need-infer, r=lcnr

Check `needs_infer` before `needs_drop` during HIR generator analysis

This is kinda a revival of #103036, but with the understanding that after fallback, a generator-interior type will only have `needs_infer` true if there's an error that prevented int or float variable fallback to occur (modulo region variables, which are erased).

Therefore the best choice here is to delay a bug and skip the `needs_drop` call altogether.

r? `@lcnr` feel free to reassign though
This commit is contained in:
Dylan DPC 2022-10-23 15:20:17 +05:30 committed by GitHub
commit 8440b09d17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 23 additions and 18 deletions

View File

@ -6,8 +6,11 @@
use hir::{def_id::DefId, Body, HirId, HirIdMap};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_middle::hir::place::{PlaceBase, Projection, ProjectionKind};
use rustc_middle::ty::{ParamEnv, TyCtxt};
use rustc_middle::{
hir::place::{PlaceBase, Projection, ProjectionKind},
ty::TypeVisitable,
};
pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
fcx: &'a FnCtxt<'a, 'tcx>,
@ -198,11 +201,13 @@ fn mutate(
// If the type being assigned needs dropped, then the mutation counts as a borrow
// since it is essentially doing `Drop::drop(&mut x); x = new_value;`.
//
// FIXME(drop-tracking): We need to be more responsible about inference
// variables here, since `needs_drop` is a "raw" type query, i.e. it
// basically requires types to have been fully resolved.
if assignee_place.place.base_ty.needs_drop(self.tcx, self.param_env) {
let ty = self.tcx.erase_regions(assignee_place.place.base_ty);
if ty.needs_infer() {
self.tcx.sess.delay_span_bug(
self.tcx.hir().span(assignee_place.hir_id),
&format!("inference variables in {ty}"),
);
} else if ty.needs_drop(self.tcx, self.param_env) {
self.places
.borrowed
.insert(TrackedValue::from_place_with_projections_allowed(assignee_place));

View File

@ -377,15 +377,6 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
debug!("is_borrowed_temporary: {:?}", self.drop_ranges.is_borrowed_temporary(expr));
let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr);
let may_need_drop = |ty: Ty<'tcx>| {
// Avoid ICEs in needs_drop.
let ty = self.fcx.resolve_vars_if_possible(ty);
let ty = self.fcx.tcx.erase_regions(ty);
if ty.needs_infer() {
return true;
}
ty.needs_drop(self.fcx.tcx, self.fcx.param_env)
};
// Typically, the value produced by an expression is consumed by its parent in some way,
// so we only have to check if the parent contains a yield (note that the parent may, for
@ -403,9 +394,18 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
// src/test/ui/generator/drop-tracking-parent-expression.rs.
let scope = if self.drop_ranges.is_borrowed_temporary(expr)
|| ty.map_or(true, |ty| {
let needs_drop = may_need_drop(ty);
debug!(?needs_drop, ?ty);
needs_drop
// Avoid ICEs in needs_drop.
let ty = self.fcx.resolve_vars_if_possible(ty);
let ty = self.fcx.tcx.erase_regions(ty);
if ty.needs_infer() {
self.fcx
.tcx
.sess
.delay_span_bug(expr.span, &format!("inference variables in {ty}"));
true
} else {
ty.needs_drop(self.fcx.tcx, self.fcx.param_env)
}
}) {
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
} else {