mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-07 17:18:32 +03:00
Auto merge of #156072 - GuillaumeGomez:rollup-9U8oPPe, r=GuillaumeGomez
Rollup of 4 pull requests Successful merges: - rust-lang/rust#154571 (Fix alias path for rustdoc) - rust-lang/rust#155749 (`-Znext-solver` Ignore region constraints from the nested goals in leakcheck) - rust-lang/rust#156026 (`bufreader::Buffer`: Remove leftover note about `initialized` field) - rust-lang/rust#156063 (Map `WSAESHUTDOWN` to `io::ErrorKind::BrokenPipe`)
This commit is contained in:
@@ -74,7 +74,7 @@ pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<
|
||||
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 @@ fn normalize_and_add_type_outlives_constraints(
|
||||
// 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 @@ pub fn instantiate_query_response_and_region_obligations<R>(
|
||||
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 @@ pub fn instantiate_nll_query_response_and_region_obligations<R>(
|
||||
output_query_region_constraints.constraints.push((
|
||||
ty::RegionEqPredicate(v_o.into(), v_r).into(),
|
||||
constraint_category,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -586,6 +587,7 @@ fn unify_canonical_vars(
|
||||
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 @@ fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
|
||||
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 @@ fn infer_variable_values(
|
||||
|
||||
// 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 @@ pub fn sub_regions(
|
||||
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 @@ pub fn equate_regions(
|
||||
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 @@ pub fn register_outlives_constraint(
|
||||
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 @@ fn push_sub_region_constraint(
|
||||
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 @@ fn iterate_region_constraints(
|
||||
{
|
||||
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 @@ fn iterate_region_constraints(
|
||||
.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 @@ pub fn involves_placeholders(&self) -> bool {
|
||||
}
|
||||
|
||||
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 @@ pub fn iter_outlives(self) -> impl Iterator<Item = Self> {
|
||||
| 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 @@ pub(super) fn make_eqregion(
|
||||
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 @@ pub(super) fn make_eqregion(
|
||||
}
|
||||
(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 @@ pub(super) fn make_eqregion(
|
||||
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 @@ pub(super) fn make_eqregion(
|
||||
(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 @@ pub(super) fn make_subregion(
|
||||
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 @@ pub(super) fn make_subregion(
|
||||
(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 @@ fn combine_vars(
|
||||
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 @@ fn regions(
|
||||
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 @@ pub fn is_proven(&self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@
|
||||
)]
|
||||
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::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 @@ pub(super) fn instantiate_and_apply_query_response<D, I>(
|
||||
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 @@ fn well_formed_goals(
|
||||
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::{
|
||||
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 @@ pub(super) fn evaluate_goal_raw(
|
||||
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 @@ pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) {
|
||||
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 @@ pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
|
||||
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 @@ fn compute_region_outlives_goal(
|
||||
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 @@ fn compute_goal_fast_path(
|
||||
SubregionOrigin::RelateRegionParamBound(span, None),
|
||||
outlives.1,
|
||||
outlives.0,
|
||||
ty::VisibleForLeakCheck::Yes,
|
||||
);
|
||||
Some(Certainty::Yes)
|
||||
}
|
||||
@@ -204,7 +206,9 @@ fn well_formed_goals(
|
||||
.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 @@ fn make_deduplicated_region_constraints(&self) -> Vec<ty::RegionConstraint<'tcx>
|
||||
)
|
||||
});
|
||||
|
||||
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 @@ fn evaluate_nested_obligations(
|
||||
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 @@ fn process_obligation(
|
||||
|
||||
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::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 @@ fn sub_regions(
|
||||
&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 @@ fn equate_regions(
|
||||
&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 @@ fn visit_with<F: $crate::TypeVisitor<I>>(
|
||||
crate::solve::BuiltinImplSource,
|
||||
crate::solve::Certainty,
|
||||
crate::solve::GoalSource,
|
||||
crate::solve::VisibleForLeakCheck,
|
||||
rustc_ast_ir::Mutability,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
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 @@ fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult<I, I::Ty> {
|
||||
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 @@ pub fn is_empty(&self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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))]
|
||||
|
||||
@@ -23,9 +23,8 @@ pub struct Buffer {
|
||||
filled: usize,
|
||||
// Whether `buf` has been fully initialized. We track this so that we can accurately tell
|
||||
// `read_buf` how many bytes of buf are initialized, to bypass as much of its defensive
|
||||
// initialization as possible. Note that while this often the same as `filled`, it doesn't need
|
||||
// to be. Calls to `fill_buf` are not required to actually fill the buffer, and omitting this
|
||||
// is a huge perf regression for `Read` impls that do not.
|
||||
// initialization as possible. Calls to `fill_buf` are not required to actually fill the buffer,
|
||||
// and omitting this is a huge perf regression for `Read` impls that do not.
|
||||
initialized: bool,
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,10 @@ pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
|
||||
c::WSAENETDOWN => NetworkDown,
|
||||
c::WSAENETUNREACH => NetworkUnreachable,
|
||||
c::WSAEDQUOT => QuotaExceeded,
|
||||
// Not a perfect mapping but this error is only returned when writing to
|
||||
// a socket after shutting down the write-end. On Unix targets, EPIPE is
|
||||
// returned in those cases.
|
||||
c::WSAESHUTDOWN => BrokenPipe,
|
||||
|
||||
_ => Uncategorized,
|
||||
}
|
||||
|
||||
@@ -706,7 +706,7 @@ impl Step for $name {
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path($path) $( .path( $alt_path ) )*
|
||||
run.selectors(&[$path $(, $alt_path )*])
|
||||
}
|
||||
|
||||
fn is_default_step(_builder: &Builder<'_>) -> bool {
|
||||
|
||||
@@ -3235,7 +3235,7 @@ impl Step for CrateRustdoc {
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/librustdoc").path("src/tools/rustdoc")
|
||||
run.selectors(&["src/librustdoc", "src/tools/rustdoc"])
|
||||
}
|
||||
|
||||
fn is_default_step(_builder: &Builder<'_>) -> bool {
|
||||
|
||||
@@ -689,7 +689,7 @@ impl Step for Rustdoc {
|
||||
const IS_HOST: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/rustdoc").path("src/librustdoc")
|
||||
run.selectors(&["src/tools/rustdoc", "src/librustdoc"])
|
||||
}
|
||||
|
||||
fn is_default_step(_builder: &Builder<'_>) -> bool {
|
||||
|
||||
@@ -96,5 +96,4 @@ expression: bench
|
||||
- Set({bench::compiler/rustc_windows_rc})
|
||||
[Bench] test::CrateRustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({bench::src/librustdoc})
|
||||
- Set({bench::src/tools/rustdoc})
|
||||
- Set({bench::src/librustdoc, bench::src/tools/rustdoc})
|
||||
|
||||
@@ -19,5 +19,4 @@ expression: build
|
||||
- Set({build::library/unwind})
|
||||
[Build] tool::Rustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({build::src/librustdoc})
|
||||
- Set({build::src/tools/rustdoc})
|
||||
- Set({build::src/librustdoc, build::src/tools/rustdoc})
|
||||
|
||||
@@ -80,8 +80,7 @@ expression: check
|
||||
- Set({check::compiler/rustc_windows_rc})
|
||||
[Check] check::Rustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({check::src/librustdoc})
|
||||
- Set({check::src/tools/rustdoc})
|
||||
- Set({check::src/librustdoc, check::src/tools/rustdoc})
|
||||
[Check] check::CraneliftCodegenBackend
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({check::cg_clif})
|
||||
|
||||
+1
-2
@@ -80,8 +80,7 @@ expression: check compiletest --include-default-paths
|
||||
- Set({check::compiler/rustc_windows_rc})
|
||||
[Check] check::Rustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({check::src/librustdoc})
|
||||
- Set({check::src/tools/rustdoc})
|
||||
- Set({check::src/librustdoc, check::src/tools/rustdoc})
|
||||
[Check] check::CraneliftCodegenBackend
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({check::cg_clif})
|
||||
|
||||
@@ -80,8 +80,7 @@ expression: fix
|
||||
- Set({fix::compiler/rustc_windows_rc})
|
||||
[Fix] check::Rustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({fix::src/librustdoc})
|
||||
- Set({fix::src/tools/rustdoc})
|
||||
- Set({fix::src/librustdoc, fix::src/tools/rustdoc})
|
||||
[Fix] check::CraneliftCodegenBackend
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({fix::cg_clif})
|
||||
|
||||
@@ -146,8 +146,7 @@ expression: test
|
||||
- Set({test::compiler/rustc_windows_rc})
|
||||
[Test] test::CrateRustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/librustdoc})
|
||||
- Set({test::src/tools/rustdoc})
|
||||
- Set({test::src/librustdoc, test::src/tools/rustdoc})
|
||||
[Test] test::CrateRustdocJsonTypes
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/rustdoc-json-types})
|
||||
|
||||
@@ -4,8 +4,7 @@ expression: test librustdoc rustdoc
|
||||
---
|
||||
[Test] test::CrateRustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/librustdoc})
|
||||
- Set({test::src/tools/rustdoc})
|
||||
- Set({test::src/librustdoc, test::src/tools/rustdoc})
|
||||
[Test] test::RustdocBook
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/doc/rustdoc})
|
||||
|
||||
@@ -145,8 +145,7 @@ expression: test --skip=coverage
|
||||
- Set({test::compiler/rustc_windows_rc})
|
||||
[Test] test::CrateRustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/librustdoc})
|
||||
- Set({test::src/tools/rustdoc})
|
||||
- Set({test::src/librustdoc, test::src/tools/rustdoc})
|
||||
[Test] test::CrateRustdocJsonTypes
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/rustdoc-json-types})
|
||||
|
||||
@@ -109,8 +109,7 @@ expression: test --skip=tests
|
||||
- Set({test::compiler/rustc_windows_rc})
|
||||
[Test] test::CrateRustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/librustdoc})
|
||||
- Set({test::src/tools/rustdoc})
|
||||
- Set({test::src/librustdoc, test::src/tools/rustdoc})
|
||||
[Test] test::CrateRustdocJsonTypes
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/rustdoc-json-types})
|
||||
|
||||
@@ -89,8 +89,7 @@ expression: test --skip=tests --skip=coverage-map --skip=coverage-run --skip=lib
|
||||
- Set({test::compiler/rustc_windows_rc})
|
||||
[Test] test::CrateRustdoc
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/librustdoc})
|
||||
- Set({test::src/tools/rustdoc})
|
||||
- Set({test::src/librustdoc, test::src/tools/rustdoc})
|
||||
[Test] test::CrateRustdocJsonTypes
|
||||
targets: [x86_64-unknown-linux-gnu]
|
||||
- Set({test::src/rustdoc-json-types})
|
||||
|
||||
@@ -356,7 +356,7 @@ pub enum PathSet {
|
||||
/// command-line value of `std` will match if `library/std` is in the
|
||||
/// set.
|
||||
///
|
||||
/// NOTE: the paths within a set should always be aliases of one another.
|
||||
/// NOTE: the paths within a set should all select the same unit of work.
|
||||
/// For example, `src/librustdoc` and `src/tools/rustdoc` should be in the same set,
|
||||
/// but `library/core` and `library/std` generally should not, unless there's no way (for that Step)
|
||||
/// to build them separately.
|
||||
@@ -555,10 +555,7 @@ pub fn alias(mut self, alias: &str) -> Self {
|
||||
self
|
||||
}
|
||||
|
||||
/// single, non-aliased path
|
||||
///
|
||||
/// Must be an on-disk path; use `alias` for names that do not correspond to on-disk paths.
|
||||
pub fn path(mut self, path: &str) -> Self {
|
||||
fn assert_valid_path(&self, path: &str) {
|
||||
let submodules_paths = self.builder.submodule_paths();
|
||||
|
||||
// assert only if `p` isn't submodule
|
||||
@@ -568,12 +565,31 @@ pub fn path(mut self, path: &str) -> Self {
|
||||
"`should_run.path` should correspond to a real on-disk path - use `alias` if there is no relevant path: {path}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A single path
|
||||
///
|
||||
/// Must be an on-disk path; use [`alias`][Self::alias] for names that do not
|
||||
/// correspond to on-disk paths.
|
||||
pub fn path(mut self, path: &str) -> Self {
|
||||
self.assert_valid_path(path);
|
||||
|
||||
let task = TaskPath { path: path.into(), kind: Some(self.kind) };
|
||||
self.paths.insert(PathSet::Set(BTreeSet::from_iter([task])));
|
||||
self
|
||||
}
|
||||
|
||||
/// Multiple on-disk paths that should select the same unit of work.
|
||||
pub fn selectors(mut self, paths: &[&str]) -> Self {
|
||||
let mut set = BTreeSet::new();
|
||||
for path in paths {
|
||||
self.assert_valid_path(path);
|
||||
set.insert(TaskPath { path: (*path).into(), kind: Some(self.kind) });
|
||||
}
|
||||
self.paths.insert(PathSet::Set(set));
|
||||
self
|
||||
}
|
||||
|
||||
/// Handles individual files (not directories) within a test suite.
|
||||
fn is_suite_path(&self, requested_path: &Path) -> Option<&PathSet> {
|
||||
self.paths.iter().find(|pathset| match pathset {
|
||||
|
||||
@@ -2400,6 +2400,29 @@ fn test_exclude_kind() {
|
||||
steps.assert_contains_fuzzy(StepMetadata::build("rustc", host));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exclude_rustdoc_aliases() {
|
||||
let ctx = TestCtx::new();
|
||||
let host = TargetSelection::from_user(&host_target());
|
||||
|
||||
let get_steps = |args: &[&str]| ctx.config("build").args(args).get_steps();
|
||||
|
||||
for args in [
|
||||
["--skip", "rustdoc"].as_slice(),
|
||||
["--skip", "src/tools/rustdoc"].as_slice(),
|
||||
["--skip", "src/librustdoc"].as_slice(),
|
||||
] {
|
||||
let steps = get_steps(args);
|
||||
|
||||
steps.assert_contains_fuzzy(StepMetadata::build("rustc", host));
|
||||
steps.assert_no_match(|metadata| {
|
||||
metadata.name == "rustdoc"
|
||||
&& metadata.kind == Kind::Build
|
||||
&& metadata.target == host
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cargo_stage_1() {
|
||||
let ctx = TestCtx::new();
|
||||
|
||||
@@ -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