Skip to content

Commit 9e7f262

Browse files
committed
Report dropck normalization errors in borrowck
HIR type checking no longer runs dropck, so we may get new errors when we run it in borrowck. If this happens then rerun the query in a local infcx and report errors for it.
1 parent 69482e8 commit 9e7f262

File tree

2 files changed

+86
-22
lines changed

2 files changed

+86
-22
lines changed

compiler/rustc_borrowck/src/type_check/liveness/trace.rs

+44-13
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ use rustc_index::bit_set::DenseBitSet;
33
use rustc_index::interval::IntervalSet;
44
use rustc_infer::infer::canonical::QueryRegionConstraints;
55
use rustc_infer::infer::outlives::for_liveness;
6-
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
6+
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location};
77
use rustc_middle::traits::query::DropckOutlivesResult;
88
use rustc_middle::ty::relate::Relate;
99
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
1010
use rustc_mir_dataflow::ResultsCursor;
1111
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
1212
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
1313
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
14-
use rustc_span::DUMMY_SP;
14+
use rustc_span::{DUMMY_SP, Span};
15+
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
16+
use rustc_trait_selection::traits::ObligationCtxt;
17+
use rustc_trait_selection::traits::query::dropck_outlives;
1518
use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, TypeOpOutput};
1619
use tracing::debug;
1720

@@ -162,9 +165,10 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
162165
fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) {
163166
for local in boring_locals {
164167
let local_ty = self.cx.body.local_decls[local].ty;
168+
let local_span = self.cx.body.local_decls[local].source_info.span;
165169
let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
166170
let typeck = &self.cx.typeck;
167-
move || LivenessContext::compute_drop_data(typeck, local_ty)
171+
move || LivenessContext::compute_drop_data(typeck, local_ty, local_span)
168172
});
169173

170174
drop_data.dropck_result.report_overflows(
@@ -522,9 +526,10 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
522526
values::pretty_print_points(self.location_map, live_at.iter()),
523527
);
524528

529+
let local_span = self.body.local_decls()[dropped_local].source_info.span;
525530
let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
526531
let typeck = &self.typeck;
527-
move || Self::compute_drop_data(typeck, dropped_ty)
532+
move || Self::compute_drop_data(typeck, dropped_ty, local_span)
528533
});
529534

530535
if let Some(data) = &drop_data.region_constraint_data {
@@ -589,19 +594,45 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
589594
}
590595
}
591596

592-
fn compute_drop_data(typeck: &TypeChecker<'_, 'tcx>, dropped_ty: Ty<'tcx>) -> DropData<'tcx> {
593-
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
597+
fn compute_drop_data(
598+
typeck: &TypeChecker<'_, 'tcx>,
599+
dropped_ty: Ty<'tcx>,
600+
span: Span,
601+
) -> DropData<'tcx> {
602+
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty);
603+
604+
let op = typeck.infcx.param_env.and(DropckOutlives { dropped_ty });
594605

595-
match typeck
596-
.infcx
597-
.param_env
598-
.and(DropckOutlives { dropped_ty })
599-
.fully_perform(typeck.infcx, DUMMY_SP)
600-
{
606+
match op.fully_perform(typeck.infcx, DUMMY_SP) {
601607
Ok(TypeOpOutput { output, constraints, .. }) => {
602608
DropData { dropck_result: output, region_constraint_data: constraints }
603609
}
604-
Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
610+
Err(_) => {
611+
// We don't run dropck on HIR, and dropck looks inside fields of
612+
// types, so there's no guarantee that it succeeds. We also
613+
// can't rely on the the `ErrorGuaranteed` from `fully_perform` here
614+
// because it comes from delay_span_bug.
615+
let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
616+
let errors = match dropck_outlives::compute_dropck_outlives_with_errors(
617+
&ocx, op, span, true,
618+
) {
619+
Ok(_) => ocx.select_all_or_error(),
620+
Err(e) => {
621+
if e.is_empty() {
622+
ocx.select_all_or_error()
623+
} else {
624+
e
625+
}
626+
}
627+
};
628+
629+
if !errors.is_empty() {
630+
typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
631+
} else {
632+
rustc_middle::span_bug!(span, "Rerunning drop data query produced no error.");
633+
}
634+
DropData { dropck_result: Default::default(), region_constraint_data: None }
635+
}
605636
}
606637
}
607638
}

compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs

+42-9
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ use rustc_data_structures::fx::FxHashSet;
22
use rustc_infer::traits::query::type_op::DropckOutlives;
33
use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
44
use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
5-
use rustc_span::{DUMMY_SP, Span};
5+
use rustc_span::Span;
66
use tracing::{debug, instrument};
77

8+
use crate::solve::NextSolverError;
89
use crate::traits::query::NoSolution;
910
use crate::traits::query::normalize::QueryNormalizeExt;
10-
use crate::traits::{Normalized, ObligationCause, ObligationCtxt};
11+
use crate::traits::{FromSolverError, Normalized, ObligationCause, ObligationCtxt};
1112

1213
/// This returns true if the type `ty` is "trivial" for
1314
/// dropck-outlives -- that is, if it doesn't require any types to
@@ -93,6 +94,21 @@ pub fn compute_dropck_outlives_inner<'tcx>(
9394
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
9495
span: Span,
9596
) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
97+
match compute_dropck_outlives_with_errors(ocx, goal, span, false) {
98+
Ok(r) => Ok(r),
99+
Err(_) => Err(NoSolution),
100+
}
101+
}
102+
103+
pub fn compute_dropck_outlives_with_errors<'tcx, E>(
104+
ocx: &ObligationCtxt<'_, 'tcx, E>,
105+
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
106+
span: Span,
107+
report_errors: bool,
108+
) -> Result<DropckOutlivesResult<'tcx>, Vec<E>>
109+
where
110+
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
111+
{
96112
let tcx = ocx.infcx.tcx;
97113
let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal;
98114

@@ -146,14 +162,17 @@ pub fn compute_dropck_outlives_inner<'tcx>(
146162
result.overflows.len(),
147163
ty_stack.len()
148164
);
149-
dtorck_constraint_for_ty_inner(
165+
match dtorck_constraint_for_ty_inner(
150166
tcx,
151167
ocx.infcx.typing_env(param_env),
152-
DUMMY_SP,
168+
span,
153169
depth,
154170
ty,
155171
&mut constraints,
156-
)?;
172+
) {
173+
Err(_) => return Err(Vec::new()),
174+
_ => (),
175+
};
157176

158177
// "outlives" represent types/regions that may be touched
159178
// by a destructor.
@@ -173,11 +192,25 @@ pub fn compute_dropck_outlives_inner<'tcx>(
173192
// do not themselves define a destructor", more or less. We have
174193
// to push them onto the stack to be expanded.
175194
for ty in constraints.dtorck_types.drain(..) {
176-
let Normalized { value: ty, obligations } =
177-
ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
178-
ocx.register_obligations(obligations);
195+
let ty = if report_errors {
196+
let normalized_ty = ocx.deeply_normalize(&cause, param_env, ty)?;
179197

180-
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
198+
let errors = ocx.select_where_possible();
199+
if !errors.is_empty() {
200+
debug!("failed to normalize dtorck type: {ty} ~> {errors:#?}");
201+
return Err(errors);
202+
}
203+
normalized_ty
204+
} else if let Ok(Normalized { value: ty, obligations }) =
205+
ocx.infcx.at(&cause, param_env).query_normalize(ty)
206+
{
207+
ocx.register_obligations(obligations);
208+
209+
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
210+
ty
211+
} else {
212+
return Err(Vec::new());
213+
};
181214

182215
match ty.kind() {
183216
// All parameters live for the duration of the

0 commit comments

Comments
 (0)