+ if self.has_where_clause {
+ self.predicates
+ .iter()
+ .filter(|p| p.in_where_clause())
+ .last()
+ .map_or(end, |p| p.span())
+ .shrink_to_hi()
+ .to(end)
+ } else {
+ end
+ }
+ }
+
+ pub fn bounds_for_param(
+ &self,
+ param_def_id: LocalDefId,
+ ) -> impl Iterator<Item = &WhereBoundPredicate<'_>> {
+ self.predicates.iter().filter_map(move |pred| match pred {
+ WherePredicate::BoundPredicate(bp) if bp.is_param_bound(param_def_id.to_def_id()) => {
+ Some(bp)
+ }
+ _ => None,
+ })
+ }
+
+ pub fn bounds_span_for_suggestions(&self, param_def_id: LocalDefId) -> Option<Span> {
+ self.bounds_for_param(param_def_id).flat_map(|bp| bp.bounds.iter().rev()).find_map(
+ |bound| {
+ // We include bounds that come from a `#[derive(_)]` but point at the user's code,
+ // as we use this method to get a span appropriate for suggestions.
+ let bs = bound.span();
+ if bs.can_be_used_for_suggestions() { Some(bs.shrink_to_hi()) } else { None }
+ },
+ )
+ }
+
+ pub fn span_for_predicate_removal(&self, pos: usize) -> Span {
+ let predicate = &self.predicates[pos];
+ let span = predicate.span();
+
+ if !predicate.in_where_clause() {
+ // <T: ?Sized, U>
+ // ^^^^^^^^
+ return span;
+ }
+
+ // We need to find out which comma to remove.
+ if pos < self.predicates.len() - 1 {
+ let next_pred = &self.predicates[pos + 1];
+ if next_pred.in_where_clause() {
+ // where T: ?Sized, Foo: Bar,
+ // ^^^^^^^^^^^
+ return span.until(next_pred.span());
+ }
+ }
+
+ if pos > 0 {
+ let prev_pred = &self.predicates[pos - 1];
+ if prev_pred.in_where_clause() {
+ // where Foo: Bar, T: ?Sized,
+ // ^^^^^^^^^^^
+ return prev_pred.span().shrink_to_hi().to(span);
+ }
+ }
+
+ // This is the only predicate in the where clause.
+ // where T: ?Sized
+ // ^^^^^^^^^^^^^^^
+ self.where_clause_span
+ }
+
+ pub fn span_for_bound_removal(&self, predicate_pos: usize, bound_pos: usize) -> Span {
+ let predicate = &self.predicates[predicate_pos];
+ let bounds = predicate.bounds();
+
+ if bounds.len() == 1 {
+ return self.span_for_predicate_removal(predicate_pos);
+ }
+
+ let span = bounds[bound_pos].span();
+ if bound_pos == 0 {
+ // where T: ?Sized + Bar, Foo: Bar,
+ // ^^^^^^^^^
+ span.to(bounds[1].span().shrink_to_lo())
+ } else {
+ // where T: Bar + ?Sized, Foo: Bar,
+ // ^^^^^^^^^
+ bounds[bound_pos - 1].span().shrink_to_hi().to(span)
+ }