mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-06 08:36:52 -04:00
-Znext-solver Ignore region constraints from the nested goals in leakcheck
This commit is contained in:
@@ -74,7 +74,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
let assumptions =
|
||||
elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
|
||||
|
||||
for &(constraint, constraint_category) in constraints {
|
||||
for &(constraint, constraint_category, _) in constraints {
|
||||
constraint.iter_outlives().for_each(|predicate| {
|
||||
self.convert(predicate, constraint_category, &assumptions);
|
||||
});
|
||||
@@ -296,7 +296,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
// FIXME(higher_ranked_auto): What should we do with the assumptions here?
|
||||
if let Some(QueryRegionConstraints { constraints, assumptions: _ }) = constraints {
|
||||
next_outlives_predicates.extend(constraints.iter().flat_map(
|
||||
|(constraint, category)| {
|
||||
|(constraint, category, _)| {
|
||||
constraint.iter_outlives().map(|outlives| (outlives, *category))
|
||||
},
|
||||
));
|
||||
|
||||
@@ -728,6 +728,7 @@ fn region_known_to_outlive<'tcx>(
|
||||
SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
|
||||
region_b,
|
||||
region_a,
|
||||
ty::VisibleForLeakCheck::Unreachable,
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -496,7 +496,12 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
||||
}
|
||||
|
||||
(&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
|
||||
infcx.sub_regions(SubregionOrigin::RelateObjectBound(span), r_b, r_a);
|
||||
infcx.sub_regions(
|
||||
SubregionOrigin::RelateObjectBound(span),
|
||||
r_b,
|
||||
r_a,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
);
|
||||
let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
|
||||
let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
|
||||
check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
|
||||
|
||||
@@ -188,14 +188,14 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
let InferOk { value: result_args, obligations } =
|
||||
self.query_response_instantiation(cause, param_env, original_values, query_response)?;
|
||||
|
||||
for (constraint, _category) in &query_response.value.region_constraints.constraints {
|
||||
for (constraint, _category, vis) in &query_response.value.region_constraints.constraints {
|
||||
let constraint = instantiate_value(self.tcx, &result_args, *constraint);
|
||||
match constraint {
|
||||
ty::RegionConstraint::Outlives(predicate) => {
|
||||
self.register_outlives_constraint(predicate, cause);
|
||||
self.register_outlives_constraint(predicate, *vis, cause);
|
||||
}
|
||||
ty::RegionConstraint::Eq(predicate) => {
|
||||
self.register_region_eq_constraint(predicate, cause);
|
||||
self.register_region_eq_constraint(predicate, *vis, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,6 +288,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
output_query_region_constraints.constraints.push((
|
||||
ty::RegionEqPredicate(v_o.into(), v_r).into(),
|
||||
constraint_category,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -586,6 +587,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
SubregionOrigin::RelateRegionParamBound(cause.span, None),
|
||||
v1,
|
||||
v2,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
);
|
||||
}
|
||||
(GenericArgKind::Const(v1), GenericArgKind::Const(v2)) => {
|
||||
@@ -623,20 +625,24 @@ pub fn make_query_region_constraints<'tcx>(
|
||||
| ConstraintKind::RegSubReg => {
|
||||
// Swap regions because we are going from sub (<=) to outlives (>=).
|
||||
let constraint = ty::OutlivesPredicate(c.sup.into(), c.sub).into();
|
||||
(constraint, origin.to_constraint_category())
|
||||
(constraint, origin.to_constraint_category(), c.visible_for_leak_check)
|
||||
}
|
||||
|
||||
ConstraintKind::VarEqVar | ConstraintKind::VarEqReg | ConstraintKind::RegEqReg => {
|
||||
let constraint = ty::RegionEqPredicate(c.sup, c.sub).into();
|
||||
(constraint, origin.to_constraint_category())
|
||||
(constraint, origin.to_constraint_category(), c.visible_for_leak_check)
|
||||
}
|
||||
})
|
||||
.chain(outlives_obligations.into_iter().map(|obl| {
|
||||
(
|
||||
ty::OutlivesPredicate(obl.sup_type.into(), obl.sub_region).into(),
|
||||
obl.origin.to_constraint_category(),
|
||||
)
|
||||
}))
|
||||
.chain(outlives_obligations.into_iter().map(
|
||||
|TypeOutlivesConstraint { sub_region, sup_type, origin }| {
|
||||
(
|
||||
ty::OutlivesPredicate(sup_type.into(), sub_region).into(),
|
||||
origin.to_constraint_category(),
|
||||
// We don't do leak checks for type outlives
|
||||
ty::VisibleForLeakCheck::Unreachable,
|
||||
)
|
||||
},
|
||||
))
|
||||
.collect();
|
||||
|
||||
QueryRegionConstraints { constraints, assumptions }
|
||||
|
||||
@@ -256,19 +256,33 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
||||
self.probe(|_| probe())
|
||||
}
|
||||
|
||||
fn sub_regions(&self, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, span: Span) {
|
||||
fn sub_regions(
|
||||
&self,
|
||||
sub: ty::Region<'tcx>,
|
||||
sup: ty::Region<'tcx>,
|
||||
vis: ty::VisibleForLeakCheck,
|
||||
span: Span,
|
||||
) {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_subregion(
|
||||
SubregionOrigin::RelateRegionParamBound(span, None),
|
||||
sub,
|
||||
sup,
|
||||
vis,
|
||||
);
|
||||
}
|
||||
|
||||
fn equate_regions(&self, a: ty::Region<'tcx>, b: ty::Region<'tcx>, span: Span) {
|
||||
fn equate_regions(
|
||||
&self,
|
||||
a: ty::Region<'tcx>,
|
||||
b: ty::Region<'tcx>,
|
||||
vis: ty::VisibleForLeakCheck,
|
||||
span: Span,
|
||||
) {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
|
||||
SubregionOrigin::RelateRegionParamBound(span, None),
|
||||
a,
|
||||
b,
|
||||
vis,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,11 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||
|
||||
// Deduplicating constraints is shown to have a positive perf impact.
|
||||
let mut seen = UnordSet::default();
|
||||
self.data.constraints.retain(|(constraint, _)| seen.insert(*constraint));
|
||||
self.data.constraints.retain_mut(|(constraint, _)| {
|
||||
// We don't want to discern constraints by leak check visibility here
|
||||
constraint.visible_for_leak_check = ty::VisibleForLeakCheck::Unreachable;
|
||||
seen.insert(*constraint)
|
||||
});
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
self.dump_constraints();
|
||||
|
||||
@@ -698,8 +698,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
origin: SubregionOrigin<'tcx>,
|
||||
a: ty::Region<'tcx>,
|
||||
b: ty::Region<'tcx>,
|
||||
vis: ty::VisibleForLeakCheck,
|
||||
) {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b);
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b, vis);
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
@@ -708,8 +709,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
origin: SubregionOrigin<'tcx>,
|
||||
a: ty::Region<'tcx>,
|
||||
b: ty::Region<'tcx>,
|
||||
vis: ty::VisibleForLeakCheck,
|
||||
) {
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(origin, a, b);
|
||||
self.inner.borrow_mut().unwrap_region_constraints().make_eqregion(origin, a, b, vis);
|
||||
}
|
||||
|
||||
/// Processes a `Coerce` predicate from the fulfillment context.
|
||||
|
||||
@@ -85,11 +85,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn register_outlives_constraint(
|
||||
&self,
|
||||
ty::OutlivesPredicate(arg, r2): ty::ArgOutlivesPredicate<'tcx>,
|
||||
vis: ty::VisibleForLeakCheck,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
) {
|
||||
match arg.kind() {
|
||||
ty::GenericArgKind::Lifetime(r1) => {
|
||||
self.register_region_outlives_constraint(ty::OutlivesPredicate(r1, r2), cause);
|
||||
self.register_region_outlives_constraint(ty::OutlivesPredicate(r1, r2), vis, cause);
|
||||
}
|
||||
ty::GenericArgKind::Type(ty1) => {
|
||||
self.register_type_outlives_constraint(ty1, r2, cause);
|
||||
@@ -101,24 +102,26 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn register_region_eq_constraint(
|
||||
&self,
|
||||
ty::RegionEqPredicate(r_a, r_b): ty::RegionEqPredicate<'tcx>,
|
||||
vis: ty::VisibleForLeakCheck,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
) {
|
||||
let origin = SubregionOrigin::from_obligation_cause(cause, || {
|
||||
SubregionOrigin::RelateRegionParamBound(cause.span, None)
|
||||
});
|
||||
self.equate_regions(origin, r_a, r_b);
|
||||
self.equate_regions(origin, r_a, r_b, vis);
|
||||
}
|
||||
|
||||
pub fn register_region_outlives_constraint(
|
||||
&self,
|
||||
ty::OutlivesPredicate(r_a, r_b): ty::RegionOutlivesPredicate<'tcx>,
|
||||
vis: ty::VisibleForLeakCheck,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
) {
|
||||
let origin = SubregionOrigin::from_obligation_cause(cause, || {
|
||||
SubregionOrigin::RelateRegionParamBound(cause.span, None)
|
||||
});
|
||||
// `'a: 'b` ==> `'b <= 'a`
|
||||
self.sub_regions(origin, r_b, r_a);
|
||||
self.sub_regions(origin, r_b, r_a, vis);
|
||||
}
|
||||
|
||||
/// Registers that the given region obligation must be resolved
|
||||
@@ -577,7 +580,8 @@ impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'tcx> {
|
||||
b: ty::Region<'tcx>,
|
||||
_constraint_category: ConstraintCategory<'tcx>,
|
||||
) {
|
||||
self.sub_regions(origin, a, b)
|
||||
// We don't do leak check in lexical region resolution
|
||||
self.sub_regions(origin, a, b, ty::VisibleForLeakCheck::Unreachable)
|
||||
}
|
||||
|
||||
fn push_verify(
|
||||
|
||||
@@ -392,10 +392,15 @@ impl<'tcx> MiniGraph<'tcx> {
|
||||
{
|
||||
match undo_entry {
|
||||
&AddConstraint(i) => {
|
||||
region_constraints.data().constraints[i]
|
||||
.0
|
||||
.iter_outlives()
|
||||
.for_each(|c| each_edge(c.sub, c.sup));
|
||||
region_constraints.data().constraints[i].0.iter_outlives().for_each(
|
||||
|Constraint { kind: _, sub, sup, visible_for_leak_check }| {
|
||||
match visible_for_leak_check {
|
||||
ty::VisibleForLeakCheck::Yes => each_edge(sub, sup),
|
||||
ty::VisibleForLeakCheck::No => {}
|
||||
ty::VisibleForLeakCheck::Unreachable => unreachable!(),
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
&AddVerify(i) => span_bug!(
|
||||
region_constraints.data().verifys[i].origin.span(),
|
||||
@@ -410,7 +415,13 @@ impl<'tcx> MiniGraph<'tcx> {
|
||||
.constraints
|
||||
.iter()
|
||||
.flat_map(|(c, _)| c.iter_outlives())
|
||||
.for_each(|c| each_edge(c.sub, c.sup))
|
||||
.for_each(|Constraint { kind: _, sub, sup, visible_for_leak_check }| {
|
||||
match visible_for_leak_check {
|
||||
ty::VisibleForLeakCheck::Yes => each_edge(sub, sup),
|
||||
ty::VisibleForLeakCheck::No => {}
|
||||
ty::VisibleForLeakCheck::Unreachable => unreachable!(),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,10 +115,11 @@ pub enum ConstraintKind {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct Constraint<'tcx> {
|
||||
pub kind: ConstraintKind,
|
||||
// If `kind` is `VarSubVar` or `VarSubReg`, this must be a `ReVar`.
|
||||
// If `kind` is `VarSubVar`, `VarSubReg`, `VarEqVar` or `VarEqReg`, this must be a `ReVar`.
|
||||
pub sub: Region<'tcx>,
|
||||
// If `kind` is `VarSubVar` or `RegSubVar`, this must be a `ReVar`.
|
||||
// If `kind` is `VarSubVar`, `RegSubVar` or `VarEqVar`, this must be a `ReVar`.
|
||||
pub sup: Region<'tcx>,
|
||||
pub visible_for_leak_check: ty::VisibleForLeakCheck,
|
||||
}
|
||||
|
||||
impl Constraint<'_> {
|
||||
@@ -127,7 +128,7 @@ impl Constraint<'_> {
|
||||
}
|
||||
|
||||
pub fn iter_outlives(self) -> impl Iterator<Item = Self> {
|
||||
let Constraint { kind, sub, sup } = self;
|
||||
let Constraint { kind, sub, sup, visible_for_leak_check } = self;
|
||||
|
||||
match kind {
|
||||
ConstraintKind::VarSubVar
|
||||
@@ -135,18 +136,42 @@ impl Constraint<'_> {
|
||||
| ConstraintKind::VarSubReg
|
||||
| ConstraintKind::RegSubReg => iter::once(self).chain(None),
|
||||
|
||||
ConstraintKind::VarEqVar => {
|
||||
iter::once(Constraint { kind: ConstraintKind::VarSubVar, sub, sup })
|
||||
.chain(Some(Constraint { kind: ConstraintKind::VarSubVar, sub: sup, sup: sub }))
|
||||
}
|
||||
ConstraintKind::VarEqReg => {
|
||||
iter::once(Constraint { kind: ConstraintKind::VarSubReg, sub, sup })
|
||||
.chain(Some(Constraint { kind: ConstraintKind::RegSubVar, sub: sup, sup: sub }))
|
||||
}
|
||||
ConstraintKind::RegEqReg => {
|
||||
iter::once(Constraint { kind: ConstraintKind::RegSubReg, sub, sup })
|
||||
.chain(Some(Constraint { kind: ConstraintKind::RegSubReg, sub: sup, sup: sub }))
|
||||
}
|
||||
ConstraintKind::VarEqVar => iter::once(Constraint {
|
||||
kind: ConstraintKind::VarSubVar,
|
||||
sub,
|
||||
sup,
|
||||
visible_for_leak_check,
|
||||
})
|
||||
.chain(Some(Constraint {
|
||||
kind: ConstraintKind::VarSubVar,
|
||||
sub: sup,
|
||||
sup: sub,
|
||||
visible_for_leak_check,
|
||||
})),
|
||||
ConstraintKind::VarEqReg => iter::once(Constraint {
|
||||
kind: ConstraintKind::VarSubReg,
|
||||
sub,
|
||||
sup,
|
||||
visible_for_leak_check,
|
||||
})
|
||||
.chain(Some(Constraint {
|
||||
kind: ConstraintKind::RegSubVar,
|
||||
sub: sup,
|
||||
sup: sub,
|
||||
visible_for_leak_check,
|
||||
})),
|
||||
ConstraintKind::RegEqReg => iter::once(Constraint {
|
||||
kind: ConstraintKind::RegSubReg,
|
||||
sub,
|
||||
sup,
|
||||
visible_for_leak_check,
|
||||
})
|
||||
.chain(Some(Constraint {
|
||||
kind: ConstraintKind::RegSubReg,
|
||||
sub: sup,
|
||||
sup: sub,
|
||||
visible_for_leak_check,
|
||||
})),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -457,6 +482,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
origin: SubregionOrigin<'tcx>,
|
||||
a: Region<'tcx>,
|
||||
b: Region<'tcx>,
|
||||
visible_for_leak_check: ty::VisibleForLeakCheck,
|
||||
) {
|
||||
if a != b {
|
||||
// FIXME: We could only emit constraints if `unify_var_{var, value}` fails when
|
||||
@@ -467,7 +493,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
}
|
||||
(ReVar(a_vid), ReVar(b_vid), _, _) => {
|
||||
self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::VarEqVar, sub: a, sup: b },
|
||||
Constraint {
|
||||
kind: ConstraintKind::VarEqVar,
|
||||
sub: a,
|
||||
sup: b,
|
||||
visible_for_leak_check,
|
||||
},
|
||||
origin,
|
||||
);
|
||||
debug!("make_eqregion: unifying {:?} with {:?}", a_vid, b_vid);
|
||||
@@ -479,12 +510,22 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
if reg.is_static() {
|
||||
// all regions are subregions of static, so don't go bidirectional here
|
||||
self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::RegSubVar, sub: reg, sup: var },
|
||||
Constraint {
|
||||
kind: ConstraintKind::RegSubVar,
|
||||
sub: reg,
|
||||
sup: var,
|
||||
visible_for_leak_check,
|
||||
},
|
||||
origin,
|
||||
);
|
||||
} else {
|
||||
self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::VarEqReg, sub: var, sup: reg },
|
||||
Constraint {
|
||||
kind: ConstraintKind::VarEqReg,
|
||||
sub: var,
|
||||
sup: reg,
|
||||
visible_for_leak_check,
|
||||
},
|
||||
origin,
|
||||
);
|
||||
}
|
||||
@@ -500,13 +541,23 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
(ReStatic, _, st, reg) | (_, ReStatic, reg, st) => {
|
||||
// all regions are subregions of static, so don't go bidirectional here
|
||||
self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::RegSubReg, sub: st, sup: reg },
|
||||
Constraint {
|
||||
kind: ConstraintKind::RegSubReg,
|
||||
sub: st,
|
||||
sup: reg,
|
||||
visible_for_leak_check,
|
||||
},
|
||||
origin,
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::RegEqReg, sub: a, sup: b },
|
||||
Constraint {
|
||||
kind: ConstraintKind::RegEqReg,
|
||||
sub: a,
|
||||
sup: b,
|
||||
visible_for_leak_check,
|
||||
},
|
||||
origin,
|
||||
);
|
||||
}
|
||||
@@ -520,6 +571,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
origin: SubregionOrigin<'tcx>,
|
||||
sub: Region<'tcx>,
|
||||
sup: Region<'tcx>,
|
||||
visible_for_leak_check: ty::VisibleForLeakCheck,
|
||||
) {
|
||||
// cannot add constraints once regions are resolved
|
||||
debug!("origin = {:#?}", origin);
|
||||
@@ -534,19 +586,33 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
(ReVar(sub_id), ReVar(sup_id)) => {
|
||||
if sub_id != sup_id {
|
||||
self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::VarSubVar, sub, sup },
|
||||
Constraint {
|
||||
kind: ConstraintKind::VarSubVar,
|
||||
sub,
|
||||
sup,
|
||||
visible_for_leak_check,
|
||||
},
|
||||
origin,
|
||||
);
|
||||
}
|
||||
}
|
||||
(_, ReVar(_)) => self
|
||||
.add_constraint(Constraint { kind: ConstraintKind::RegSubVar, sub, sup }, origin),
|
||||
(ReVar(_), _) => self
|
||||
.add_constraint(Constraint { kind: ConstraintKind::VarSubReg, sub, sup }, origin),
|
||||
(_, ReVar(_)) => self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::RegSubVar, sub, sup, visible_for_leak_check },
|
||||
origin,
|
||||
),
|
||||
(ReVar(_), _) => self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::VarSubReg, sub, sup, visible_for_leak_check },
|
||||
origin,
|
||||
),
|
||||
_ => {
|
||||
if sub != sup {
|
||||
self.add_constraint(
|
||||
Constraint { kind: ConstraintKind::RegSubReg, sub, sup },
|
||||
Constraint {
|
||||
kind: ConstraintKind::RegSubReg,
|
||||
sub,
|
||||
sup,
|
||||
visible_for_leak_check,
|
||||
},
|
||||
origin,
|
||||
)
|
||||
}
|
||||
@@ -655,8 +721,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
let new_r = ty::Region::new_var(tcx, c);
|
||||
for old_r in [a, b] {
|
||||
match t {
|
||||
Glb => self.make_subregion(origin.clone(), new_r, old_r),
|
||||
Lub => self.make_subregion(origin.clone(), old_r, new_r),
|
||||
Glb => {
|
||||
self.make_subregion(origin.clone(), new_r, old_r, ty::VisibleForLeakCheck::Yes)
|
||||
}
|
||||
Lub => {
|
||||
self.make_subregion(origin.clone(), old_r, new_r, ty::VisibleForLeakCheck::Yes)
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("combine_vars() c={:?}", c);
|
||||
|
||||
@@ -223,26 +223,29 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
|
||||
match self.ambient_variance {
|
||||
// Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
|
||||
ty::Covariant => {
|
||||
self.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.make_subregion(origin, b, a);
|
||||
self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(
|
||||
origin,
|
||||
b,
|
||||
a,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
);
|
||||
}
|
||||
// Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
|
||||
ty::Contravariant => {
|
||||
self.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.make_subregion(origin, a, b);
|
||||
self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(
|
||||
origin,
|
||||
a,
|
||||
b,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
);
|
||||
}
|
||||
ty::Invariant => {
|
||||
self.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.make_eqregion(origin, a, b);
|
||||
self.infcx.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
|
||||
origin,
|
||||
a,
|
||||
b,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
);
|
||||
}
|
||||
ty::Bivariant => {
|
||||
unreachable!("Expected bivariance to be handled in relate_with_variance")
|
||||
|
||||
@@ -135,7 +135,9 @@ impl<'tcx, R> QueryResponse<'tcx, R> {
|
||||
}
|
||||
}
|
||||
|
||||
pub type QueryRegionConstraint<'tcx> = (ty::RegionConstraint<'tcx>, ConstraintCategory<'tcx>);
|
||||
// FIXME: Convert this into a struct
|
||||
pub type QueryRegionConstraint<'tcx> =
|
||||
(ty::RegionConstraint<'tcx>, ConstraintCategory<'tcx>, ty::VisibleForLeakCheck);
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CanonicalParamEnvCache<'tcx> {
|
||||
|
||||
@@ -64,7 +64,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
|
||||
)]
|
||||
use rustc_type_ir::inherent;
|
||||
pub use rustc_type_ir::relate::VarianceDiagInfo;
|
||||
pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind};
|
||||
pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind, VisibleForLeakCheck};
|
||||
pub use rustc_type_ir::*;
|
||||
#[allow(hidden_glob_reexports, unused_imports)]
|
||||
use rustc_type_ir::{InferCtxtLike, Interner};
|
||||
|
||||
@@ -25,7 +25,7 @@ use crate::delegate::SolverDelegate;
|
||||
use crate::resolve::eager_resolve_vars;
|
||||
use crate::solve::{
|
||||
CanonicalInput, CanonicalResponse, Certainty, ExternalConstraintsData, Goal,
|
||||
NestedNormalizationGoals, QueryInput, Response, inspect,
|
||||
NestedNormalizationGoals, QueryInput, Response, VisibleForLeakCheck, inspect,
|
||||
};
|
||||
|
||||
pub mod canonicalizer;
|
||||
@@ -99,6 +99,7 @@ pub(super) fn instantiate_and_apply_query_response<D, I>(
|
||||
param_env: I::ParamEnv,
|
||||
original_values: &[I::GenericArg],
|
||||
response: CanonicalResponse<I>,
|
||||
visible_for_leak_check: VisibleForLeakCheck,
|
||||
span: I::Span,
|
||||
) -> (NestedNormalizationGoals<I>, Certainty)
|
||||
where
|
||||
@@ -116,7 +117,11 @@ where
|
||||
let ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } =
|
||||
&*external_constraints;
|
||||
|
||||
register_region_constraints(delegate, region_constraints, span);
|
||||
register_region_constraints(
|
||||
delegate,
|
||||
region_constraints.iter().map(|(c, vis)| (*c, vis.and(visible_for_leak_check))),
|
||||
span,
|
||||
);
|
||||
register_new_opaque_types(delegate, opaque_types, span);
|
||||
|
||||
(normalization_nested_goals.clone(), certainty)
|
||||
@@ -262,21 +267,21 @@ fn unify_query_var_values<D, I>(
|
||||
|
||||
fn register_region_constraints<D, I>(
|
||||
delegate: &D,
|
||||
constraints: &[ty::RegionConstraint<I>],
|
||||
constraints: impl IntoIterator<Item = (ty::RegionConstraint<I>, VisibleForLeakCheck)>,
|
||||
span: I::Span,
|
||||
) where
|
||||
D: SolverDelegate<Interner = I>,
|
||||
I: Interner,
|
||||
{
|
||||
for &constraint in constraints {
|
||||
for (constraint, vis) in constraints {
|
||||
match constraint {
|
||||
ty::RegionConstraint::Outlives(ty::OutlivesPredicate(lhs, rhs)) => match lhs.kind() {
|
||||
ty::GenericArgKind::Lifetime(lhs) => delegate.sub_regions(rhs, lhs, span),
|
||||
ty::GenericArgKind::Lifetime(lhs) => delegate.sub_regions(rhs, lhs, vis, span),
|
||||
ty::GenericArgKind::Type(lhs) => delegate.register_ty_outlives(lhs, rhs, span),
|
||||
ty::GenericArgKind::Const(_) => panic!("const outlives: {lhs:?}: {rhs:?}"),
|
||||
},
|
||||
ty::RegionConstraint::Eq(ty::RegionEqPredicate(lhs, rhs)) => {
|
||||
delegate.equate_regions(lhs, rhs, span)
|
||||
delegate.equate_regions(lhs, rhs, vis, span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_type_ir::solve::{Certainty, Goal, NoSolution};
|
||||
use rustc_type_ir::solve::{Certainty, Goal, NoSolution, VisibleForLeakCheck};
|
||||
use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable};
|
||||
|
||||
pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
|
||||
@@ -45,7 +45,9 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
|
||||
term: <Self::Interner as Interner>::Term,
|
||||
) -> Option<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>>;
|
||||
|
||||
fn make_deduplicated_region_constraints(&self) -> Vec<ty::RegionConstraint<Self::Interner>>;
|
||||
fn make_deduplicated_region_constraints(
|
||||
&self,
|
||||
) -> Vec<(ty::RegionConstraint<Self::Interner>, VisibleForLeakCheck)>;
|
||||
|
||||
fn instantiate_canonical<V>(
|
||||
&self,
|
||||
|
||||
@@ -30,7 +30,8 @@ use crate::solve::ty::may_use_unstable_feature;
|
||||
use crate::solve::{
|
||||
CanonicalInput, CanonicalResponse, Certainty, ExternalConstraintsData, FIXPOINT_STEP_LIMIT,
|
||||
Goal, GoalEvaluation, GoalSource, GoalStalledOn, HasChanged, MaybeCause,
|
||||
NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, Response, inspect,
|
||||
NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, Response, VisibleForLeakCheck,
|
||||
inspect,
|
||||
};
|
||||
|
||||
mod probe;
|
||||
@@ -484,11 +485,29 @@ where
|
||||
let has_changed =
|
||||
if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No };
|
||||
|
||||
// FIXME: We should revisit and consider removing this after
|
||||
// *assumptions on binders* is available, like once we had done in the
|
||||
// stabilization of `-Znext-solver=coherence`(#121848).
|
||||
// We ignore constraints from the nested goals in leak check. This is to match
|
||||
// with the old solver's behavior, which has separated evaluation and fulfillment,
|
||||
// and the former doesn't consider outlives obligations from the later.
|
||||
let vis = match goal.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(_)
|
||||
| ty::PredicateKind::DynCompatible(_)
|
||||
| ty::PredicateKind::Subtype(_)
|
||||
| ty::PredicateKind::Coerce(_)
|
||||
| ty::PredicateKind::ConstEquate(_, _)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::NormalizesTo(_) => VisibleForLeakCheck::No,
|
||||
ty::PredicateKind::AliasRelate(_, _, _) => VisibleForLeakCheck::Yes,
|
||||
};
|
||||
|
||||
let (normalization_nested_goals, certainty) = instantiate_and_apply_query_response(
|
||||
self.delegate,
|
||||
goal.param_env,
|
||||
&orig_values,
|
||||
response,
|
||||
vis,
|
||||
self.origin_span,
|
||||
);
|
||||
|
||||
@@ -1100,9 +1119,14 @@ where
|
||||
self.delegate.register_ty_outlives(ty, lt, self.origin_span);
|
||||
}
|
||||
|
||||
pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) {
|
||||
pub(super) fn register_region_outlives(
|
||||
&self,
|
||||
a: I::Region,
|
||||
b: I::Region,
|
||||
vis: VisibleForLeakCheck,
|
||||
) {
|
||||
// `'a: 'b` ==> `'b <= 'a`
|
||||
self.delegate.sub_regions(b, a, self.origin_span);
|
||||
self.delegate.sub_regions(b, a, vis, self.origin_span);
|
||||
}
|
||||
|
||||
/// Computes the list of goals required for `arg` to be well-formed
|
||||
@@ -1303,7 +1327,7 @@ where
|
||||
let mut unique = HashSet::default();
|
||||
external_constraints
|
||||
.region_constraints
|
||||
.retain(|outlives| !outlives.is_trivial() && unique.insert(*outlives));
|
||||
.retain(|(outlives, _)| !outlives.is_trivial() && unique.insert(*outlives));
|
||||
|
||||
let canonical = canonicalize_response(
|
||||
self.delegate,
|
||||
@@ -1533,6 +1557,7 @@ pub(super) fn evaluate_root_goal_for_proof_tree<D: SolverDelegate<Interner = I>,
|
||||
goal.param_env,
|
||||
&proof_tree.orig_values,
|
||||
response,
|
||||
VisibleForLeakCheck::Yes,
|
||||
origin_span,
|
||||
);
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ where
|
||||
goal: Goal<I, ty::OutlivesPredicate<I, I::Region>>,
|
||||
) -> QueryResult<I> {
|
||||
let ty::OutlivesPredicate(a, b) = goal.predicate;
|
||||
self.register_region_outlives(a, b);
|
||||
self.register_region_outlives(a, b, VisibleForLeakCheck::Yes);
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
|
||||
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
||||
@@ -112,6 +113,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
SubregionOrigin::RelateRegionParamBound(span, None),
|
||||
outlives.1,
|
||||
outlives.0,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
);
|
||||
Some(Certainty::Yes)
|
||||
}
|
||||
@@ -204,7 +206,9 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
.map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect())
|
||||
}
|
||||
|
||||
fn make_deduplicated_region_constraints(&self) -> Vec<ty::RegionConstraint<'tcx>> {
|
||||
fn make_deduplicated_region_constraints(
|
||||
&self,
|
||||
) -> Vec<(ty::RegionConstraint<'tcx>, ty::VisibleForLeakCheck)> {
|
||||
// Cannot use `take_registered_region_obligations` as we may compute the response
|
||||
// inside of a `probe` whenever we have multiple choices inside of the solver.
|
||||
let region_obligations = self.0.inner.borrow().region_obligations().to_owned();
|
||||
@@ -217,13 +221,23 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
||||
)
|
||||
});
|
||||
|
||||
let mut seen = FxHashSet::default();
|
||||
region_constraints
|
||||
.constraints
|
||||
.into_iter()
|
||||
.filter(|&(outlives, _)| seen.insert(outlives))
|
||||
.map(|(outlives, _)| outlives)
|
||||
.collect()
|
||||
let mut seen = FxHashMap::default();
|
||||
let mut constraints = vec![];
|
||||
for (outlives, _, vis) in region_constraints.constraints {
|
||||
match seen.entry(outlives) {
|
||||
Entry::Occupied(occupied) => {
|
||||
let idx = occupied.get();
|
||||
let (_, prev_vis): &mut (_, ty::VisibleForLeakCheck) =
|
||||
constraints.get_mut(*idx).unwrap();
|
||||
*prev_vis = (*prev_vis).or(vis);
|
||||
}
|
||||
Entry::Vacant(vacant) => {
|
||||
vacant.insert(constraints.len());
|
||||
constraints.push((outlives, vis));
|
||||
}
|
||||
}
|
||||
}
|
||||
constraints
|
||||
}
|
||||
|
||||
fn instantiate_canonical<V>(
|
||||
|
||||
@@ -738,7 +738,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => {
|
||||
let binder = bound_predicate.rebind(binder);
|
||||
selcx.infcx.enter_forall(binder, |pred| {
|
||||
selcx.infcx.register_region_outlives_constraint(pred, &dummy_cause);
|
||||
selcx.infcx.register_region_outlives_constraint(pred, ty::VisibleForLeakCheck::Yes,&dummy_cause);
|
||||
});
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(binder)) => {
|
||||
|
||||
@@ -484,7 +484,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => {
|
||||
if infcx.considering_regions {
|
||||
infcx.register_region_outlives_constraint(data, &obligation.cause);
|
||||
infcx.register_region_outlives_constraint(
|
||||
data,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
&obligation.cause,
|
||||
);
|
||||
}
|
||||
|
||||
ProcessResult::Changed(Default::default())
|
||||
|
||||
@@ -83,13 +83,13 @@ fn implied_outlives_bounds<'a, 'tcx>(
|
||||
// outlives bound required proving some higher-ranked coroutine obl.
|
||||
let QueryRegionConstraints { constraints, assumptions: _ } = constraints;
|
||||
let cause = ObligationCause::misc(span, body_id);
|
||||
for &(constraint, _) in &constraints {
|
||||
for &(constraint, _, vis) in &constraints {
|
||||
match constraint {
|
||||
ty::RegionConstraint::Outlives(predicate) => {
|
||||
infcx.register_outlives_constraint(predicate, &cause)
|
||||
infcx.register_outlives_constraint(predicate, vis, &cause)
|
||||
}
|
||||
ty::RegionConstraint::Eq(predicate) => {
|
||||
infcx.register_region_eq_constraint(predicate, &cause)
|
||||
infcx.register_region_eq_constraint(predicate, vis, &cause)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ fn compute_assumptions<'tcx>(
|
||||
tcx.mk_outlives_from_iter(
|
||||
constraints
|
||||
.into_iter()
|
||||
.flat_map(|(constraint, _)| constraint.iter_outlives())
|
||||
.flat_map(|(constraint, _, _)| constraint.iter_outlives())
|
||||
// FIXME(higher_ranked_auto): We probably should deeply resolve these before
|
||||
// filtering out infers which only correspond to unconstrained infer regions
|
||||
// which we can sometimes get.
|
||||
|
||||
@@ -8,6 +8,7 @@ use crate::fold::TypeFoldable;
|
||||
use crate::inherent::*;
|
||||
use crate::relate::RelateResult;
|
||||
use crate::relate::combine::PredicateEmittingRelation;
|
||||
use crate::solve::VisibleForLeakCheck;
|
||||
use crate::{self as ty, Interner, TyVid};
|
||||
|
||||
/// The current typing mode of an inference context. We unfortunately have some
|
||||
@@ -323,6 +324,7 @@ pub trait InferCtxtLike: Sized {
|
||||
&self,
|
||||
sub: <Self::Interner as Interner>::Region,
|
||||
sup: <Self::Interner as Interner>::Region,
|
||||
vis: VisibleForLeakCheck,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
);
|
||||
|
||||
@@ -330,6 +332,7 @@ pub trait InferCtxtLike: Sized {
|
||||
&self,
|
||||
a: <Self::Interner as Interner>::Region,
|
||||
b: <Self::Interner as Interner>::Region,
|
||||
vis: VisibleForLeakCheck,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ TrivialTypeTraversalImpls! {
|
||||
crate::solve::BuiltinImplSource,
|
||||
crate::solve::Certainty,
|
||||
crate::solve::GoalSource,
|
||||
crate::solve::VisibleForLeakCheck,
|
||||
rustc_ast_ir::Mutability,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combi
|
||||
use crate::data_structures::DelayedSet;
|
||||
use crate::relate::combine::combine_ty_args;
|
||||
pub use crate::relate::*;
|
||||
use crate::solve::Goal;
|
||||
use crate::solve::{Goal, VisibleForLeakCheck};
|
||||
use crate::{self as ty, InferCtxtLike, Interner};
|
||||
|
||||
pub trait RelateExt: InferCtxtLike {
|
||||
@@ -256,10 +256,10 @@ where
|
||||
fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult<I, I::Region> {
|
||||
match self.ambient_variance {
|
||||
// Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
|
||||
ty::Covariant => self.infcx.sub_regions(b, a, self.span),
|
||||
ty::Covariant => self.infcx.sub_regions(b, a, VisibleForLeakCheck::Yes, self.span),
|
||||
// Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
|
||||
ty::Contravariant => self.infcx.sub_regions(a, b, self.span),
|
||||
ty::Invariant => self.infcx.equate_regions(a, b, self.span),
|
||||
ty::Contravariant => self.infcx.sub_regions(a, b, VisibleForLeakCheck::Yes, self.span),
|
||||
ty::Invariant => self.infcx.equate_regions(a, b, VisibleForLeakCheck::Yes, self.span),
|
||||
ty::Bivariant => {
|
||||
unreachable!("Expected bivariance to be handled in relate_with_variance")
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ impl<I: Interner> Eq for Response<I> {}
|
||||
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub struct ExternalConstraintsData<I: Interner> {
|
||||
pub region_constraints: Vec<ty::RegionConstraint<I>>,
|
||||
pub region_constraints: Vec<(ty::RegionConstraint<I>, VisibleForLeakCheck)>,
|
||||
pub opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
|
||||
pub normalization_nested_goals: NestedNormalizationGoals<I>,
|
||||
}
|
||||
@@ -265,6 +265,47 @@ impl<I: Interner> ExternalConstraintsData<I> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the given region constraint should be considered/ignored for
|
||||
/// leak check. In most part of the compiler, this should be `Yes`, except
|
||||
/// for applying constraints from the nested goals in next-solver.
|
||||
/// `Unreachable` is used in places in which leak check isn't done, e.g.
|
||||
/// borrowck.
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub enum VisibleForLeakCheck {
|
||||
Yes,
|
||||
No,
|
||||
Unreachable,
|
||||
}
|
||||
|
||||
impl VisibleForLeakCheck {
|
||||
pub fn and(self, other: VisibleForLeakCheck) -> VisibleForLeakCheck {
|
||||
match (self, other) {
|
||||
// Make sure that we never overwrite that constraints shouldn't
|
||||
// be encountered by the leak checked
|
||||
(VisibleForLeakCheck::Unreachable, _) | (_, VisibleForLeakCheck::Unreachable) => {
|
||||
VisibleForLeakCheck::Unreachable
|
||||
}
|
||||
(VisibleForLeakCheck::No, _) | (_, VisibleForLeakCheck::No) => VisibleForLeakCheck::No,
|
||||
(VisibleForLeakCheck::Yes, VisibleForLeakCheck::Yes) => VisibleForLeakCheck::Yes,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn or(self, other: VisibleForLeakCheck) -> VisibleForLeakCheck {
|
||||
match (self, other) {
|
||||
// Make sure that we never overwrite that constraints shouldn't
|
||||
// be encountered by the leak checked
|
||||
(VisibleForLeakCheck::Unreachable, _) | (_, VisibleForLeakCheck::Unreachable) => {
|
||||
VisibleForLeakCheck::Unreachable
|
||||
}
|
||||
(VisibleForLeakCheck::Yes, _) | (_, VisibleForLeakCheck::Yes) => {
|
||||
VisibleForLeakCheck::Yes
|
||||
}
|
||||
(VisibleForLeakCheck::No, VisibleForLeakCheck::No) => VisibleForLeakCheck::No,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive_where(Clone, Hash, PartialEq, Debug, Default; I: Interner)]
|
||||
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
//@ known-bug: #140577
|
||||
//@ compile-flags: -Znext-solver=globally
|
||||
//@ edition:2021
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
trait Acquire {
|
||||
type Connection;
|
||||
}
|
||||
impl Acquire for &'static () {
|
||||
type Connection = ();
|
||||
}
|
||||
fn b<T: Acquire>() -> impl Future + Send {
|
||||
let x: Pin<Box<dyn Future<Output = T::Connection> + Send>> = todo!();
|
||||
x
|
||||
}
|
||||
fn main() {
|
||||
async {
|
||||
b::<&()>().await;
|
||||
}
|
||||
.aa();
|
||||
}
|
||||
|
||||
impl<F> Filter for F where F: Send {}
|
||||
|
||||
trait Filter {
|
||||
fn aa(self)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,10 @@ error[E0308]: mismatched types
|
||||
--> $DIR/must-prove-where-clauses-on-norm.rs:23:61
|
||||
|
|
||||
LL | let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>;
|
||||
| ------------------------------------------- ^^^^^^^^^ one type is more general than the other
|
||||
| |
|
||||
| expected due to this
|
||||
| ^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected fn pointer `for<'b> fn((), &'b _) -> &'static _`
|
||||
found fn item `for<'b> fn(<() as Trait>::Assoc<'_, 'b>, &'b _) -> &_ {foo::<'_, ()>}`
|
||||
= note: expected fn pointer `for<'b> fn((), &'b _) -> &_`
|
||||
found fn pointer `for<'b> fn((), &'b _) -> &_`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
+3
-10
@@ -1,14 +1,8 @@
|
||||
error[E0271]: type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
|
||||
--> $DIR/candidate-from-env-universe-err-project.rs:38:24
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/candidate-from-env-universe-err-project.rs:38:5
|
||||
|
|
||||
LL | projection_bound::<T>();
|
||||
| ^ types differ
|
||||
|
|
||||
note: required by a bound in `projection_bound`
|
||||
--> $DIR/candidate-from-env-universe-err-project.rs:19:42
|
||||
|
|
||||
LL | fn projection_bound<T: for<'a> Trait<'a, Assoc = usize>>() {}
|
||||
| ^^^^^^^^^^^^^ required by this bound in `projection_bound`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/candidate-from-env-universe-err-project.rs:52:30
|
||||
@@ -26,4 +20,3 @@ LL | let _higher_ranked_norm: for<'a> fn(<T as Trait<'a>>::Assoc) = |_| ();
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
||||
|
||||
@@ -36,7 +36,7 @@ fn function2<T: Trait<'static, Assoc = usize>>() {
|
||||
// does not use the leak check when trying the where-bound, causing us
|
||||
// to prefer it over the impl, resulting in a placeholder error.
|
||||
projection_bound::<T>();
|
||||
//[next]~^ ERROR type mismatch resolving `<T as Trait<'a>>::Assoc == usize`
|
||||
//[next]~^ ERROR higher-ranked subtype error
|
||||
//[current]~^^ ERROR mismatched types
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ edition:2021
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/140577>.
|
||||
//
|
||||
// This previously caused an ICE due to a non–well-formed opaque type
|
||||
// in a coroutine witness failing the leak check in the next-solver.
|
||||
//
|
||||
// In `TypingMode::Analysis`, the problematic type is hidden behind a
|
||||
// stalled coroutine candidate. However, in later passes (e.g. MIR
|
||||
// validation), we eagerly normalize it. The candidate that was
|
||||
// previously accepted as a solution then fails the leak check, resulting
|
||||
// in broken MIR and ultimately an ICE.
|
||||
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
trait Acquire {
|
||||
type Connection;
|
||||
}
|
||||
impl Acquire for &'static () {
|
||||
type Connection = ();
|
||||
}
|
||||
fn b<T: Acquire>() -> impl Future + Send {
|
||||
let x: Pin<Box<dyn Future<Output = T::Connection> + Send>> = todo!();
|
||||
x
|
||||
}
|
||||
fn main() {
|
||||
async {
|
||||
b::<&()>().await;
|
||||
}
|
||||
.aa();
|
||||
}
|
||||
|
||||
impl<F> Filter for F where F: Send {}
|
||||
|
||||
trait Filter {
|
||||
fn aa(self)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ edition: 2021
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/251>.
|
||||
//
|
||||
// This previously caused an ICE due to a non–well-formed opaque type
|
||||
// in a coroutine witness failing the leak check in the next-solver.
|
||||
//
|
||||
// In `TypingMode::Analysis`, the problematic type is hidden behind a
|
||||
// stalled coroutine candidate. However, in later passes (e.g. MIR
|
||||
// validation), we eagerly normalize it. The candidate that was
|
||||
// previously accepted as a solution then fails the leak check, resulting
|
||||
// in broken MIR and ultimately an ICE.
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
trait Access {
|
||||
// has to have an associated type, but can be anything
|
||||
type Reader;
|
||||
|
||||
fn read(&self) -> impl Future<Output = Self::Reader> + Send {
|
||||
async { loop {} }
|
||||
}
|
||||
}
|
||||
|
||||
trait AccessDyn: Sync {}
|
||||
impl Access for dyn AccessDyn {
|
||||
type Reader = ();
|
||||
}
|
||||
|
||||
trait Stream {
|
||||
fn poll_next(s: &'static dyn AccessDyn);
|
||||
}
|
||||
|
||||
// has to be a function in a trait impl, can't be a normal impl block or standalone fn
|
||||
impl Stream for () {
|
||||
fn poll_next(s: &'static dyn AccessDyn) {
|
||||
// new async block is important
|
||||
is_dyn_send(&async {
|
||||
s.read().await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn is_dyn_send(_: &dyn Send) {}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,36 @@
|
||||
//@ check-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ edition:2021
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/251>.
|
||||
//
|
||||
// This previously caused an ICE due to a non–well-formed opaque type
|
||||
// in a coroutine witness failing the leak check in the next-solver.
|
||||
//
|
||||
// In `TypingMode::Analysis`, the problematic type is hidden behind a
|
||||
// stalled coroutine candidate. However, in later passes (e.g. MIR
|
||||
// validation), we eagerly normalize it. The candidate that was
|
||||
// previously accepted as a solution then fails the leak check, resulting
|
||||
// in broken MIR and ultimately an ICE.
|
||||
|
||||
trait Trait {
|
||||
type Assoc;
|
||||
}
|
||||
impl Trait for &'static u32 {
|
||||
type Assoc = ();
|
||||
}
|
||||
struct W<T: Trait>(T::Assoc);
|
||||
|
||||
fn prove_send_and_hide<T: Send>(x: T) -> impl Send { x }
|
||||
fn as_dyn_send(_: &dyn Send) {}
|
||||
pub fn main() {
|
||||
// Checking whether the cast to the trait object is correct
|
||||
// during MIR validation uses `TypingMode::PostAnalysis` and
|
||||
// therefore looks into the opaque.
|
||||
as_dyn_send(&async move {
|
||||
let opaque_ty = prove_send_and_hide(W::<&'static u32>(()));
|
||||
std::future::ready(opaque_ty).await;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//@ run-pass
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
// Regression test for <https://github.com/rust-lang/rust/issues/153596>.
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
trait Trait {
|
||||
type Assoc;
|
||||
}
|
||||
impl<'a, 'b: 'a> Trait for Inv<'a, 'b> {
|
||||
type Assoc = ();
|
||||
}
|
||||
|
||||
trait ReqWf {}
|
||||
impl<T: Trait> ReqWf for T where T::Assoc: Sized {}
|
||||
struct Inv<'a, 'b: 'a>(Option<*mut &'a &'b ()>);
|
||||
fn mk_opaque<'a, 'b>(x: &'a &'b u32) -> impl ReqWf + use<'a, 'b> {
|
||||
Inv::<'a, 'b>(None)
|
||||
}
|
||||
|
||||
trait Bound<T> {}
|
||||
impl<T, F, R: ReqWf> Bound<T> for F where F: FnOnce(T) -> R {}
|
||||
trait ImpossiblePredicates<F> {
|
||||
fn call_me(&self)
|
||||
where
|
||||
F: for<'a, 'b> Bound<&'a &'b u32>,
|
||||
{
|
||||
println!("method body");
|
||||
}
|
||||
}
|
||||
impl<F> ImpossiblePredicates<F> for () {}
|
||||
fn mk_trait_object<F>(_: F) -> Box<dyn ImpossiblePredicates<F>> {
|
||||
Box::new(())
|
||||
}
|
||||
pub fn main() {
|
||||
let obj = mk_trait_object(mk_opaque);
|
||||
// This previously caused a segfault: the where-bounds of
|
||||
// `ImpossiblePredicate::call_me` did not hold due to missing implied bounds
|
||||
// for the fully normalized opaque type of `obj` in `fn impossible_predicates`.
|
||||
// As a result, the method's vtable ended up empty.
|
||||
//
|
||||
// However, earlier compilation passes did not report an error because the
|
||||
// opaque type had not yet been fully normalized.
|
||||
obj.call_me();
|
||||
}
|
||||
Reference in New Issue
Block a user