Clean up dropck code a bit
- Remove `Result` that couldn't be Err on valid compilation. - Always compute errors on failure.
This commit is contained in:
parent
87e5969572
commit
49cf00c7c0
4 changed files with 38 additions and 55 deletions
|
@ -4,6 +4,7 @@ use rustc_index::interval::IntervalSet;
|
||||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||||
use rustc_infer::infer::outlives::for_liveness;
|
use rustc_infer::infer::outlives::for_liveness;
|
||||||
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location};
|
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, HasLocalDecls, Local, Location};
|
||||||
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::traits::query::DropckOutlivesResult;
|
use rustc_middle::traits::query::DropckOutlivesResult;
|
||||||
use rustc_middle::ty::relate::Relate;
|
use rustc_middle::ty::relate::Relate;
|
||||||
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
|
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
|
||||||
|
@ -613,9 +614,8 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||||
// can't rely on the the `ErrorGuaranteed` from `fully_perform` here
|
// can't rely on the the `ErrorGuaranteed` from `fully_perform` here
|
||||||
// because it comes from delay_span_bug.
|
// because it comes from delay_span_bug.
|
||||||
let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
|
let ocx = ObligationCtxt::new_with_diagnostics(&typeck.infcx);
|
||||||
let errors = match dropck_outlives::compute_dropck_outlives_with_errors(
|
let errors =
|
||||||
&ocx, op, span, true,
|
match dropck_outlives::compute_dropck_outlives_with_errors(&ocx, op, span) {
|
||||||
) {
|
|
||||||
Ok(_) => ocx.select_all_or_error(),
|
Ok(_) => ocx.select_all_or_error(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.is_empty() {
|
if e.is_empty() {
|
||||||
|
@ -629,7 +629,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
|
typeck.infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||||
} else {
|
} else {
|
||||||
rustc_middle::span_bug!(span, "Rerunning drop data query produced no error.");
|
span_bug!(span, "Rerunning drop data query produced no error.");
|
||||||
}
|
}
|
||||||
DropData { dropck_result: Default::default(), region_constraint_data: None }
|
DropData { dropck_result: Default::default(), region_constraint_data: None }
|
||||||
}
|
}
|
||||||
|
|
|
@ -802,7 +802,7 @@ rustc_queries! {
|
||||||
|
|
||||||
query adt_dtorck_constraint(
|
query adt_dtorck_constraint(
|
||||||
key: DefId
|
key: DefId
|
||||||
) -> Result<&'tcx DropckConstraint<'tcx>, NoSolution> {
|
) -> &'tcx DropckConstraint<'tcx> {
|
||||||
desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "computing drop-check constraints for `{}`", tcx.def_path_str(key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub fn compute_dropck_outlives_inner<'tcx>(
|
||||||
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
|
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
|
) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
|
||||||
match compute_dropck_outlives_with_errors(ocx, goal, span, false) {
|
match compute_dropck_outlives_with_errors(ocx, goal, span) {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
Err(_) => Err(NoSolution),
|
Err(_) => Err(NoSolution),
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,6 @@ pub fn compute_dropck_outlives_with_errors<'tcx, E>(
|
||||||
ocx: &ObligationCtxt<'_, 'tcx, E>,
|
ocx: &ObligationCtxt<'_, 'tcx, E>,
|
||||||
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
|
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
|
||||||
span: Span,
|
span: Span,
|
||||||
report_errors: bool,
|
|
||||||
) -> Result<DropckOutlivesResult<'tcx>, Vec<E>>
|
) -> Result<DropckOutlivesResult<'tcx>, Vec<E>>
|
||||||
where
|
where
|
||||||
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
|
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
|
||||||
|
@ -162,17 +161,14 @@ where
|
||||||
result.overflows.len(),
|
result.overflows.len(),
|
||||||
ty_stack.len()
|
ty_stack.len()
|
||||||
);
|
);
|
||||||
match dtorck_constraint_for_ty_inner(
|
dtorck_constraint_for_ty_inner(
|
||||||
tcx,
|
tcx,
|
||||||
ocx.infcx.typing_env(param_env),
|
ocx.infcx.typing_env(param_env),
|
||||||
span,
|
span,
|
||||||
depth,
|
depth,
|
||||||
ty,
|
ty,
|
||||||
&mut constraints,
|
&mut constraints,
|
||||||
) {
|
);
|
||||||
Err(_) => return Err(Vec::new()),
|
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
// "outlives" represent types/regions that may be touched
|
// "outlives" represent types/regions that may be touched
|
||||||
// by a destructor.
|
// by a destructor.
|
||||||
|
@ -192,16 +188,7 @@ where
|
||||||
// do not themselves define a destructor", more or less. We have
|
// do not themselves define a destructor", more or less. We have
|
||||||
// to push them onto the stack to be expanded.
|
// to push them onto the stack to be expanded.
|
||||||
for ty in constraints.dtorck_types.drain(..) {
|
for ty in constraints.dtorck_types.drain(..) {
|
||||||
let ty = if report_errors {
|
let ty = if let Ok(Normalized { value: ty, obligations }) =
|
||||||
let normalized_ty = ocx.deeply_normalize(&cause, param_env, ty)?;
|
|
||||||
|
|
||||||
let errors = ocx.select_where_possible();
|
|
||||||
if !errors.is_empty() {
|
|
||||||
debug!("failed to normalize dtorck type: {ty} ~> {errors:#?}");
|
|
||||||
return Err(errors);
|
|
||||||
}
|
|
||||||
normalized_ty
|
|
||||||
} else if let Ok(Normalized { value: ty, obligations }) =
|
|
||||||
ocx.infcx.at(&cause, param_env).query_normalize(ty)
|
ocx.infcx.at(&cause, param_env).query_normalize(ty)
|
||||||
{
|
{
|
||||||
ocx.register_obligations(obligations);
|
ocx.register_obligations(obligations);
|
||||||
|
@ -209,7 +196,11 @@ where
|
||||||
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
|
debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
|
||||||
ty
|
ty
|
||||||
} else {
|
} else {
|
||||||
return Err(Vec::new());
|
ocx.deeply_normalize(&cause, param_env, ty)?;
|
||||||
|
|
||||||
|
let errors = ocx.select_where_possible();
|
||||||
|
debug!("normalize errors: {ty} ~> {errors:#?}");
|
||||||
|
return Err(errors);
|
||||||
};
|
};
|
||||||
|
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
|
@ -246,14 +237,14 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
||||||
depth: usize,
|
depth: usize,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
constraints: &mut DropckConstraint<'tcx>,
|
constraints: &mut DropckConstraint<'tcx>,
|
||||||
) -> Result<(), NoSolution> {
|
) {
|
||||||
if !tcx.recursion_limit().value_within_limit(depth) {
|
if !tcx.recursion_limit().value_within_limit(depth) {
|
||||||
constraints.overflows.push(ty);
|
constraints.overflows.push(ty);
|
||||||
return Ok(());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if trivial_dropck_outlives(tcx, ty) {
|
if trivial_dropck_outlives(tcx, ty) {
|
||||||
return Ok(());
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
|
@ -277,22 +268,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
||||||
// single-element containers, behave like their element
|
// single-element containers, behave like their element
|
||||||
rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
||||||
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints)
|
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, *ety, constraints)
|
||||||
})?;
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
||||||
for ty in tys.iter() {
|
for ty in tys.iter() {
|
||||||
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
|
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
|
||||||
}
|
}
|
||||||
Ok::<_, NoSolution>(())
|
}),
|
||||||
})?,
|
|
||||||
|
|
||||||
ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
ty::Closure(_, args) => rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
||||||
for ty in args.as_closure().upvar_tys() {
|
for ty in args.as_closure().upvar_tys() {
|
||||||
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints)?;
|
dtorck_constraint_for_ty_inner(tcx, typing_env, span, depth + 1, ty, constraints);
|
||||||
}
|
}
|
||||||
Ok::<_, NoSolution>(())
|
}),
|
||||||
})?,
|
|
||||||
|
|
||||||
ty::CoroutineClosure(_, args) => {
|
ty::CoroutineClosure(_, args) => {
|
||||||
rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
rustc_data_structures::stack::ensure_sufficient_stack(|| {
|
||||||
|
@ -304,10 +293,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
||||||
depth + 1,
|
depth + 1,
|
||||||
ty,
|
ty,
|
||||||
constraints,
|
constraints,
|
||||||
)?;
|
);
|
||||||
}
|
}
|
||||||
Ok::<_, NoSolution>(())
|
})
|
||||||
})?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Coroutine(_, args) => {
|
ty::Coroutine(_, args) => {
|
||||||
|
@ -346,7 +334,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
||||||
|
|
||||||
ty::Adt(def, args) => {
|
ty::Adt(def, args) => {
|
||||||
let DropckConstraint { dtorck_types, outlives, overflows } =
|
let DropckConstraint { dtorck_types, outlives, overflows } =
|
||||||
tcx.at(span).adt_dtorck_constraint(def.did())?;
|
tcx.at(span).adt_dtorck_constraint(def.did());
|
||||||
// FIXME: we can try to recursively `dtorck_constraint_on_ty`
|
// FIXME: we can try to recursively `dtorck_constraint_on_ty`
|
||||||
// there, but that needs some way to handle cycles.
|
// there, but that needs some way to handle cycles.
|
||||||
constraints
|
constraints
|
||||||
|
@ -379,9 +367,7 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
|
||||||
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
|
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => {
|
||||||
// By the time this code runs, all type variables ought to
|
// By the time this code runs, all type variables ought to
|
||||||
// be fully resolved.
|
// be fully resolved.
|
||||||
return Err(NoSolution);
|
tcx.dcx().span_delayed_bug(span, format!("Unresolved type in dropck: {:?}.", ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,7 @@ fn dropck_outlives<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the dtorck constraint for a type.
|
/// Calculates the dtorck constraint for a type.
|
||||||
pub(crate) fn adt_dtorck_constraint(
|
pub(crate) fn adt_dtorck_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &DropckConstraint<'_> {
|
||||||
tcx: TyCtxt<'_>,
|
|
||||||
def_id: DefId,
|
|
||||||
) -> Result<&DropckConstraint<'_>, NoSolution> {
|
|
||||||
let def = tcx.adt_def(def_id);
|
let def = tcx.adt_def(def_id);
|
||||||
let span = tcx.def_span(def_id);
|
let span = tcx.def_span(def_id);
|
||||||
let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
|
let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
|
||||||
|
@ -52,20 +49,20 @@ pub(crate) fn adt_dtorck_constraint(
|
||||||
overflows: vec![],
|
overflows: vec![],
|
||||||
};
|
};
|
||||||
debug!("dtorck_constraint: {:?} => {:?}", def, result);
|
debug!("dtorck_constraint: {:?} => {:?}", def, result);
|
||||||
return Ok(tcx.arena.alloc(result));
|
return tcx.arena.alloc(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = DropckConstraint::empty();
|
let mut result = DropckConstraint::empty();
|
||||||
for field in def.all_fields() {
|
for field in def.all_fields() {
|
||||||
let fty = tcx.type_of(field.did).instantiate_identity();
|
let fty = tcx.type_of(field.did).instantiate_identity();
|
||||||
dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result)?;
|
dtorck_constraint_for_ty_inner(tcx, typing_env, span, 0, fty, &mut result);
|
||||||
}
|
}
|
||||||
result.outlives.extend(tcx.destructor_constraints(def));
|
result.outlives.extend(tcx.destructor_constraints(def));
|
||||||
dedup_dtorck_constraint(&mut result);
|
dedup_dtorck_constraint(&mut result);
|
||||||
|
|
||||||
debug!("dtorck_constraint: {:?} => {:?}", def, result);
|
debug!("dtorck_constraint: {:?} => {:?}", def, result);
|
||||||
|
|
||||||
Ok(tcx.arena.alloc(result))
|
tcx.arena.alloc(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dedup_dtorck_constraint(c: &mut DropckConstraint<'_>) {
|
fn dedup_dtorck_constraint(c: &mut DropckConstraint<'_>) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue