Skip to content

Commit cd803d0

Browse files
authored
Unrolled build for rust-lang#135007
Rollup merge of rust-lang#135007 - compiler-errors:outlives-tweaks, r=oli-obk Some type-outlives computation tweaks Some tweaks that I wrote when investigating rust-lang#135006. The only commit that's probably interesting here is f364674 (the first commit). For some reason it was concerned with filtering out param-env outlives clauses when they matched item-bound outlives clauses. However, if you look at the rest of the control flow for that function, not filtering out those bounds doesn't actually affect the behavior materially.
2 parents 3f43b1a + dd210ec commit cd803d0

File tree

2 files changed

+32
-51
lines changed

2 files changed

+32
-51
lines changed

Diff for: compiler/rustc_infer/src/infer/outlives/obligations.rs

+9-19
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,13 @@ where
363363
return;
364364
}
365365

366+
if alias_ty.has_non_region_infer() {
367+
self.tcx
368+
.dcx()
369+
.span_delayed_bug(origin.span(), "an alias has infers during region solving");
370+
return;
371+
}
372+
366373
// This case is thorny for inference. The fundamental problem is
367374
// that there are many cases where we have choice, and inference
368375
// doesn't like choice (the current region inference in
@@ -388,26 +395,9 @@ where
388395
// Compute the bounds we can derive from the environment. This
389396
// is an "approximate" match -- in some cases, these bounds
390397
// may not apply.
391-
let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty);
398+
let approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(alias_ty);
392399
debug!(?approx_env_bounds);
393400

394-
// Remove outlives bounds that we get from the environment but
395-
// which are also deducible from the trait. This arises (cc
396-
// #55756) in cases where you have e.g., `<T as Foo<'a>>::Item:
397-
// 'a` in the environment but `trait Foo<'b> { type Item: 'b
398-
// }` in the trait definition.
399-
approx_env_bounds.retain(|bound_outlives| {
400-
// OK to skip binder because we only manipulate and compare against other values from
401-
// the same binder. e.g. if we have (e.g.) `for<'a> <T as Trait<'a>>::Item: 'a` in
402-
// `bound`, the `'a` will be a `^1` (bound, debruijn index == innermost) region. If the
403-
// declaration is `trait Trait<'b> { type Item: 'b; }`, then
404-
// `projection_declared_bounds_from_trait` will be invoked with `['b => ^1]` and so we
405-
// will get `^1` returned.
406-
let bound = bound_outlives.skip_binder();
407-
let ty::Alias(_, alias_ty) = bound.0.kind() else { bug!("expected AliasTy") };
408-
self.verify_bound.declared_bounds_from_definition(*alias_ty).all(|r| r != bound.1)
409-
});
410-
411401
// If declared bounds list is empty, the only applicable rule is
412402
// OutlivesProjectionComponent. If there are inference variables,
413403
// then, we can break down the outlives into more primitive
@@ -425,7 +415,7 @@ where
425415
let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
426416
if approx_env_bounds.is_empty()
427417
&& trait_bounds.is_empty()
428-
&& (alias_ty.has_infer() || is_opaque)
418+
&& (alias_ty.has_infer_regions() || is_opaque)
429419
{
430420
debug!("no declared bounds");
431421
let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));

Diff for: compiler/rustc_infer/src/infer/outlives/verify.rs

+23-32
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
192192
/// Obviously these must be approximate -- they are in fact both *over* and
193193
/// and *under* approximated:
194194
///
195-
/// * Over-approximated because we erase regions, so
195+
/// * Over-approximated because we don't consider equality of regions.
196196
/// * Under-approximated because we look for syntactic equality and so for complex types
197197
/// like `<T as Foo<fn(&u32, &u32)>>::Item` or whatever we may fail to figure out
198198
/// all the subtleties.
@@ -205,13 +205,14 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
205205
erased_ty: Ty<'tcx>,
206206
) -> Vec<ty::PolyTypeOutlivesPredicate<'tcx>> {
207207
let tcx = self.tcx;
208+
let mut bounds = vec![];
208209

209210
// To start, collect bounds from user environment. Note that
210211
// parameter environments are already elaborated, so we don't
211212
// have to worry about that.
212-
let param_bounds = self.caller_bounds.iter().copied().filter(move |outlives_predicate| {
213+
bounds.extend(self.caller_bounds.iter().copied().filter(move |outlives_predicate| {
213214
super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty)
214-
});
215+
}));
215216

216217
// Next, collect regions we scraped from the well-formedness
217218
// constraints in the fn signature. To do that, we walk the list
@@ -224,37 +225,27 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
224225
// The problem is that the type of `x` is `&'a A`. To be
225226
// well-formed, then, A must outlive `'a`, but we don't know that
226227
// this holds from first principles.
227-
let from_region_bound_pairs =
228-
self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| {
229-
debug!(
230-
"declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
231-
(r, p)
232-
);
233-
// Fast path for the common case.
234-
match (&p, erased_ty.kind()) {
235-
// In outlive routines, all types are expected to be fully normalized.
236-
// And therefore we can safely use structural equality for alias types.
237-
(GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {}
238-
(GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {}
239-
(GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {}
240-
_ => return None,
241-
}
228+
bounds.extend(self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| {
229+
debug!(
230+
"declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
231+
(r, p)
232+
);
233+
// Fast path for the common case.
234+
match (&p, erased_ty.kind()) {
235+
// In outlive routines, all types are expected to be fully normalized.
236+
// And therefore we can safely use structural equality for alias types.
237+
(GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {}
238+
(GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {}
239+
(GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {}
240+
_ => return None,
241+
}
242242

243-
let p_ty = p.to_ty(tcx);
244-
let erased_p_ty = self.tcx.erase_regions(p_ty);
245-
(erased_p_ty == erased_ty)
246-
.then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r)))
247-
});
243+
let p_ty = p.to_ty(tcx);
244+
let erased_p_ty = self.tcx.erase_regions(p_ty);
245+
(erased_p_ty == erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r)))
246+
}));
248247

249-
param_bounds
250-
.chain(from_region_bound_pairs)
251-
.inspect(|bound| {
252-
debug!(
253-
"declared_generic_bounds_from_env_for_erased_ty: result predicate = {:?}",
254-
bound
255-
)
256-
})
257-
.collect()
248+
bounds
258249
}
259250

260251
/// Given a projection like `<T as Foo<'x>>::Bar`, returns any bounds

0 commit comments

Comments
 (0)