Move trait bound modifiers into ast::PolyTraitRef

This commit is contained in:
Michael Goulet 2024-10-13 09:31:22 -04:00
parent 7500e09b8b
commit 95dba280b9
17 changed files with 118 additions and 103 deletions

View file

@ -308,7 +308,7 @@ impl TraitBoundModifiers {
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericBound { pub enum GenericBound {
Trait(PolyTraitRef, TraitBoundModifiers), Trait(PolyTraitRef),
Outlives(Lifetime), Outlives(Lifetime),
/// Precise capturing syntax: `impl Sized + use<'a>` /// Precise capturing syntax: `impl Sized + use<'a>`
Use(ThinVec<PreciseCapturingArg>, Span), Use(ThinVec<PreciseCapturingArg>, Span),
@ -1213,10 +1213,12 @@ impl Expr {
pub fn to_bound(&self) -> Option<GenericBound> { pub fn to_bound(&self) -> Option<GenericBound> {
match &self.kind { match &self.kind {
ExprKind::Path(None, path) => Some(GenericBound::Trait( ExprKind::Path(None, path) => Some(GenericBound::Trait(PolyTraitRef::new(
PolyTraitRef::new(ThinVec::new(), path.clone(), self.span), ThinVec::new(),
path.clone(),
TraitBoundModifiers::NONE, TraitBoundModifiers::NONE,
)), self.span,
))),
_ => None, _ => None,
} }
} }
@ -2965,6 +2967,9 @@ pub struct PolyTraitRef {
/// The `'a` in `for<'a> Foo<&'a T>`. /// The `'a` in `for<'a> Foo<&'a T>`.
pub bound_generic_params: ThinVec<GenericParam>, pub bound_generic_params: ThinVec<GenericParam>,
// Optional constness, asyncness, or polarity.
pub modifiers: TraitBoundModifiers,
/// The `Foo<&'a T>` in `<'a> Foo<&'a T>`. /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`.
pub trait_ref: TraitRef, pub trait_ref: TraitRef,
@ -2972,9 +2977,15 @@ pub struct PolyTraitRef {
} }
impl PolyTraitRef { impl PolyTraitRef {
pub fn new(generic_params: ThinVec<GenericParam>, path: Path, span: Span) -> Self { pub fn new(
generic_params: ThinVec<GenericParam>,
path: Path,
modifiers: TraitBoundModifiers,
span: Span,
) -> Self {
PolyTraitRef { PolyTraitRef {
bound_generic_params: generic_params, bound_generic_params: generic_params,
modifiers,
trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID }, trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID },
span, span,
} }

View file

@ -913,7 +913,7 @@ fn walk_fn_ret_ty<T: MutVisitor>(vis: &mut T, fn_ret_ty: &mut FnRetTy) {
fn walk_param_bound<T: MutVisitor>(vis: &mut T, pb: &mut GenericBound) { fn walk_param_bound<T: MutVisitor>(vis: &mut T, pb: &mut GenericBound) {
match pb { match pb {
GenericBound::Trait(ty, _modifier) => vis.visit_poly_trait_ref(ty), GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref),
GenericBound::Outlives(lifetime) => walk_lifetime(vis, lifetime), GenericBound::Outlives(lifetime) => walk_lifetime(vis, lifetime),
GenericBound::Use(args, span) => { GenericBound::Use(args, span) => {
for arg in args { for arg in args {
@ -1034,7 +1034,7 @@ fn walk_trait_ref<T: MutVisitor>(vis: &mut T, TraitRef { path, ref_id }: &mut Tr
} }
fn walk_poly_trait_ref<T: MutVisitor>(vis: &mut T, p: &mut PolyTraitRef) { fn walk_poly_trait_ref<T: MutVisitor>(vis: &mut T, p: &mut PolyTraitRef) {
let PolyTraitRef { bound_generic_params, trait_ref, span } = p; let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span } = p;
bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
vis.visit_trait_ref(trait_ref); vis.visit_trait_ref(trait_ref);
vis.visit_span(span); vis.visit_span(span);

View file

@ -263,7 +263,7 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> {
ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => { ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => {
match bounds.last() { match bounds.last() {
Some(ast::GenericBound::Trait(bound, _)) => { Some(ast::GenericBound::Trait(bound)) => {
match path_return_type(&bound.trait_ref.path) { match path_return_type(&bound.trait_ref.path) {
Some(trailing_ty) => ty = trailing_ty, Some(trailing_ty) => ty = trailing_ty,
None => break None, None => break None,

View file

@ -329,7 +329,7 @@ pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef)
where where
V: Visitor<'a>, V: Visitor<'a>,
{ {
let PolyTraitRef { bound_generic_params, trait_ref, span: _ } = trait_ref; let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span: _ } = trait_ref;
walk_list!(visitor, visit_generic_param, bound_generic_params); walk_list!(visitor, visit_generic_param, bound_generic_params);
visitor.visit_trait_ref(trait_ref) visitor.visit_trait_ref(trait_ref)
} }
@ -720,7 +720,7 @@ impl WalkItemKind for ForeignItemKind {
pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result { pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result {
match bound { match bound {
GenericBound::Trait(typ, _modifier) => visitor.visit_poly_trait_ref(typ), GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref),
GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound), GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound),
GenericBound::Use(args, _span) => { GenericBound::Use(args, _span) => {
walk_list!(visitor, visit_precise_capturing_arg, args); walk_list!(visitor, visit_precise_capturing_arg, args);

View file

@ -1504,8 +1504,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
for bound in &bound_pred.bounds { for bound in &bound_pred.bounds {
if !matches!( if !matches!(
*bound, *bound,
GenericBound::Trait(_, TraitBoundModifiers { GenericBound::Trait(PolyTraitRef {
polarity: BoundPolarity::Maybe(_), modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
.. ..
}) })
) { ) {

View file

@ -1219,11 +1219,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let bound = this.lower_poly_trait_ref( let bound = this.lower_poly_trait_ref(
&PolyTraitRef { &PolyTraitRef {
bound_generic_params: ThinVec::new(), bound_generic_params: ThinVec::new(),
modifiers: TraitBoundModifiers::NONE,
trait_ref: TraitRef { path: path.clone(), ref_id: t.id }, trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
span: t.span, span: t.span,
}, },
itctx, itctx,
TraitBoundModifiers::NONE,
); );
let bounds = this.arena.alloc_from_iter([bound]); let bounds = this.arena.alloc_from_iter([bound]);
let lifetime_bound = this.elided_dyn_bound(t.span); let lifetime_bound = this.elided_dyn_bound(t.span);
@ -1325,8 +1325,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// We can safely ignore constness here since AST validation // We can safely ignore constness here since AST validation
// takes care of rejecting invalid modifier combinations and // takes care of rejecting invalid modifier combinations and
// const trait bounds in trait object types. // const trait bounds in trait object types.
GenericBound::Trait(ty, modifiers) => { GenericBound::Trait(ty) => {
let trait_ref = this.lower_poly_trait_ref(ty, itctx, *modifiers); let trait_ref = this.lower_poly_trait_ref(ty, itctx);
Some(trait_ref) Some(trait_ref)
} }
GenericBound::Outlives(lifetime) => { GenericBound::Outlives(lifetime) => {
@ -1974,9 +1974,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
itctx: ImplTraitContext, itctx: ImplTraitContext,
) -> hir::GenericBound<'hir> { ) -> hir::GenericBound<'hir> {
match tpb { match tpb {
GenericBound::Trait(p, modifiers) => { GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx, *modifiers))
}
GenericBound::Outlives(lifetime) => { GenericBound::Outlives(lifetime) => {
hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
} }
@ -2180,12 +2178,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self, &mut self,
p: &PolyTraitRef, p: &PolyTraitRef,
itctx: ImplTraitContext, itctx: ImplTraitContext,
modifiers: ast::TraitBoundModifiers,
) -> hir::PolyTraitRef<'hir> { ) -> hir::PolyTraitRef<'hir> {
let bound_generic_params = let bound_generic_params =
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
let trait_ref = self.lower_trait_ref(modifiers, &p.trait_ref, itctx); let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
let modifiers = self.lower_trait_bound_modifiers(modifiers); let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
hir::PolyTraitRef { hir::PolyTraitRef {
bound_generic_params, bound_generic_params,
modifiers, modifiers,

View file

@ -1260,7 +1260,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
if !bound_pred.bound_generic_params.is_empty() { if !bound_pred.bound_generic_params.is_empty() {
for bound in &bound_pred.bounds { for bound in &bound_pred.bounds {
match bound { match bound {
GenericBound::Trait(t, _) => { GenericBound::Trait(t) => {
if !t.bound_generic_params.is_empty() { if !t.bound_generic_params.is_empty() {
self.dcx() self.dcx()
.emit_err(errors::NestedLifetimes { span: t.span }); .emit_err(errors::NestedLifetimes { span: t.span });
@ -1280,8 +1280,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) { fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
match bound { match bound {
GenericBound::Trait(trait_ref, modifiers) => { GenericBound::Trait(trait_ref) => {
match (ctxt, modifiers.constness, modifiers.polarity) { match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
if !self.features.more_maybe_bounds => if !self.features.more_maybe_bounds =>
{ {
@ -1321,7 +1321,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
// Negative trait bounds are not allowed to have associated constraints // Negative trait bounds are not allowed to have associated constraints
if let BoundPolarity::Negative(_) = modifiers.polarity if let BoundPolarity::Negative(_) = trait_ref.modifiers.polarity
&& let Some(segment) = trait_ref.trait_ref.path.segments.last() && let Some(segment) = trait_ref.trait_ref.path.segments.last()
{ {
match segment.args.as_deref() { match segment.args.as_deref() {
@ -1669,7 +1669,9 @@ fn deny_equality_constraints(
}), }),
) { ) {
for bound in bounds { for bound in bounds {
if let GenericBound::Trait(poly, TraitBoundModifiers::NONE) = bound { if let GenericBound::Trait(poly) = bound
&& poly.modifiers == TraitBoundModifiers::NONE
{
if full_path.segments[..full_path.segments.len() - 1] if full_path.segments[..full_path.segments.len() - 1]
.iter() .iter()
.map(|segment| segment.ident.name) .map(|segment| segment.ident.name)
@ -1697,7 +1699,9 @@ fn deny_equality_constraints(
) { ) {
if ident == potential_param.ident { if ident == potential_param.ident {
for bound in bounds { for bound in bounds {
if let ast::GenericBound::Trait(poly, TraitBoundModifiers::NONE) = bound { if let ast::GenericBound::Trait(poly) = bound
&& poly.modifiers == TraitBoundModifiers::NONE
{
suggest(poly, potential_assoc, predicate); suggest(poly, potential_assoc, predicate);
} }
} }

View file

@ -8,7 +8,6 @@ mod item;
use std::borrow::Cow; use std::borrow::Cow;
use ast::TraitBoundModifiers;
use rustc_ast::attr::AttrIdGenerator; use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::token::{ use rustc_ast::token::{
@ -1253,6 +1252,27 @@ impl<'a> State<'a> {
fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) { fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
self.print_formal_generic_params(&t.bound_generic_params); self.print_formal_generic_params(&t.bound_generic_params);
let ast::TraitBoundModifiers { constness, asyncness, polarity } = t.modifiers;
match constness {
ast::BoundConstness::Never => {}
ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => {
self.word_space(constness.as_str());
}
}
match asyncness {
ast::BoundAsyncness::Normal => {}
ast::BoundAsyncness::Async(_) => {
self.word_space(asyncness.as_str());
}
}
match polarity {
ast::BoundPolarity::Positive => {}
ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => {
self.word(polarity.as_str());
}
}
self.print_trait_ref(&t.trait_ref) self.print_trait_ref(&t.trait_ref)
} }
@ -1740,31 +1760,7 @@ impl<'a> State<'a> {
} }
match bound { match bound {
GenericBound::Trait( GenericBound::Trait(tref) => {
tref,
TraitBoundModifiers { constness, asyncness, polarity },
) => {
match constness {
ast::BoundConstness::Never => {}
ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => {
self.word_space(constness.as_str());
}
}
match asyncness {
ast::BoundAsyncness::Normal => {}
ast::BoundAsyncness::Async(_) => {
self.word_space(asyncness.as_str());
}
}
match polarity {
ast::BoundPolarity::Positive => {}
ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => {
self.word(polarity.as_str());
}
}
self.print_poly_trait_ref(tref); self.print_poly_trait_ref(tref);
} }
GenericBound::Outlives(lt) => self.print_lifetime(*lt), GenericBound::Outlives(lt) => self.print_lifetime(*lt),

View file

@ -333,12 +333,12 @@ fn contains_maybe_sized_bound_on_pointee(predicates: &[WherePredicate], pointee:
} }
fn is_maybe_sized_bound(bound: &GenericBound) -> bool { fn is_maybe_sized_bound(bound: &GenericBound) -> bool {
if let GenericBound::Trait( if let GenericBound::Trait(trait_ref) = bound
trait_ref, && let TraitBoundModifiers { polarity: ast::BoundPolarity::Maybe(_), .. } =
TraitBoundModifiers { polarity: ast::BoundPolarity::Maybe(_), .. }, trait_ref.modifiers
) = bound && is_sized_marker(&trait_ref.trait_ref.path)
{ {
is_sized_marker(&trait_ref.trait_ref.path) true
} else { } else {
false false
} }

View file

@ -143,24 +143,25 @@ impl<'a> ExtCtxt<'a> {
ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID } ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID }
} }
pub fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef { pub fn poly_trait_ref(&self, span: Span, path: ast::Path, is_const: bool) -> ast::PolyTraitRef {
ast::PolyTraitRef { ast::PolyTraitRef {
bound_generic_params: ThinVec::new(), bound_generic_params: ThinVec::new(),
modifiers: ast::TraitBoundModifiers {
polarity: ast::BoundPolarity::Positive,
constness: if is_const {
ast::BoundConstness::Maybe(DUMMY_SP)
} else {
ast::BoundConstness::Never
},
asyncness: ast::BoundAsyncness::Normal,
},
trait_ref: self.trait_ref(path), trait_ref: self.trait_ref(path),
span, span,
} }
} }
pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound { pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
ast::GenericBound::Trait(self.poly_trait_ref(path.span, path), ast::TraitBoundModifiers { ast::GenericBound::Trait(self.poly_trait_ref(path.span, path, is_const))
polarity: ast::BoundPolarity::Positive,
constness: if is_const {
ast::BoundConstness::Maybe(DUMMY_SP)
} else {
ast::BoundConstness::Never
},
asyncness: ast::BoundAsyncness::Normal,
})
} }
pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime { pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime {

View file

@ -2113,7 +2113,7 @@ impl<'a> Parser<'a> {
&& let Some(poly) = bounds && let Some(poly) = bounds
.iter() .iter()
.filter_map(|bound| match bound { .filter_map(|bound| match bound {
ast::GenericBound::Trait(poly, _) => Some(poly), ast::GenericBound::Trait(poly) => Some(poly),
_ => None, _ => None,
}) })
.last() .last()

View file

@ -948,8 +948,8 @@ impl<'a> Parser<'a> {
{ {
return Ok((false, seg.ident, seg.args.as_deref().cloned())); return Ok((false, seg.ident, seg.args.as_deref().cloned()));
} else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind } else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind
&& let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE)] = && let [ast::GenericBound::Trait(trait_ref)] = bounds.as_slice()
bounds.as_slice() && trait_ref.modifiers == ast::TraitBoundModifiers::NONE
&& let [seg] = trait_ref.trait_ref.path.segments.as_slice() && let [seg] = trait_ref.trait_ref.path.segments.as_slice()
{ {
return Ok((true, seg.ident, seg.args.as_deref().cloned())); return Ok((true, seg.ident, seg.args.as_deref().cloned()));

View file

@ -419,8 +419,13 @@ impl<'a> Parser<'a> {
lo: Span, lo: Span,
parse_plus: bool, parse_plus: bool,
) -> PResult<'a, TyKind> { ) -> PResult<'a, TyKind> {
let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span)); let poly_trait_ref = PolyTraitRef::new(
let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifiers::NONE)]; generic_params,
path,
TraitBoundModifiers::NONE,
lo.to(self.prev_token.span),
);
let bounds = vec![GenericBound::Trait(poly_trait_ref)];
self.parse_remaining_bounds(bounds, parse_plus) self.parse_remaining_bounds(bounds, parse_plus)
} }
@ -1085,8 +1090,9 @@ impl<'a> Parser<'a> {
} }
} }
let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_token.span)); let poly_trait =
Ok(GenericBound::Trait(poly_trait, modifiers)) PolyTraitRef::new(lifetime_defs, path, modifiers, lo.to(self.prev_token.span));
Ok(GenericBound::Trait(poly_trait))
} }
// recovers a `Fn(..)` parenthesized-style path from `fn(..)` // recovers a `Fn(..)` parenthesized-style path from `fn(..)`

View file

@ -519,11 +519,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
continue; continue;
}; };
for bound in bounds { for bound in bounds {
let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE) = bound let ast::GenericBound::Trait(trait_ref) = bound else {
else {
continue; continue;
}; };
if base_error.span == trait_ref.span { if trait_ref.modifiers == ast::TraitBoundModifiers::NONE
&& base_error.span == trait_ref.span
{
err.span_suggestion_verbose( err.span_suggestion_verbose(
constraint.ident.span.between(trait_ref.span), constraint.ident.span.between(trait_ref.span),
"you might have meant to write a path instead of an associated type bound", "you might have meant to write a path instead of an associated type bound",
@ -837,7 +838,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
); );
if bounds.iter().all(|bound| match bound { if bounds.iter().all(|bound| match bound {
ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..) => true, ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..) => true,
ast::GenericBound::Trait(tr, _) => tr.span == base_error.span, ast::GenericBound::Trait(tr) => tr.span == base_error.span,
}) { }) {
let mut sugg = vec![]; let mut sugg = vec![];
if base_error.span != start_span { if base_error.span != start_span {
@ -1210,7 +1211,8 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let param = generics.params.iter().find_map(|param| { let param = generics.params.iter().find_map(|param| {
// Only consider type params with exactly one trait bound. // Only consider type params with exactly one trait bound.
if let [bound] = &*param.bounds if let [bound] = &*param.bounds
&& let ast::GenericBound::Trait(tref, ast::TraitBoundModifiers::NONE) = bound && let ast::GenericBound::Trait(tref) = bound
&& tref.modifiers == ast::TraitBoundModifiers::NONE
&& tref.span == span && tref.span == span
&& param.ident.span.eq_ctxt(span) && param.ident.span.eq_ctxt(span)
{ {
@ -1333,8 +1335,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
} }
if let ( if let (
[ast::PathSegment { args: None, .. }], [ast::PathSegment { args: None, .. }],
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifiers::NONE)], [ast::GenericBound::Trait(poly_trait_ref)],
) = (&type_param_path.segments[..], &bounds[..]) ) = (&type_param_path.segments[..], &bounds[..])
&& poly_trait_ref.modifiers == ast::TraitBoundModifiers::NONE
{ {
if let [ast::PathSegment { ident, args: None, .. }] = if let [ast::PathSegment { ident, args: None, .. }] =
&poly_trait_ref.trait_ref.path.segments[..] &poly_trait_ref.trait_ref.path.segments[..]
@ -2814,7 +2817,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
&& bounded_ty.id == binder && bounded_ty.id == binder
{ {
for bound in bounds { for bound in bounds {
if let ast::GenericBound::Trait(poly_trait_ref, _) = bound if let ast::GenericBound::Trait(poly_trait_ref) = bound
&& let span = poly_trait_ref && let span = poly_trait_ref
.span .span
.with_hi(poly_trait_ref.trait_ref.path.span.lo()) .with_hi(poly_trait_ref.trait_ref.path.span.lo())
@ -3233,7 +3236,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
let mut lt_finder = let mut lt_finder =
LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] }; LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] };
for bound in arg_refs { for bound in arg_refs {
if let ast::GenericBound::Trait(trait_ref, _) = bound { if let ast::GenericBound::Trait(trait_ref) = bound {
lt_finder.visit_trait_ref(&trait_ref.trait_ref); lt_finder.visit_trait_ref(&trait_ref.trait_ref);
} }
} }
@ -3444,17 +3447,15 @@ fn mk_where_bound_predicate(
span: DUMMY_SP, span: DUMMY_SP,
bound_generic_params: ThinVec::new(), bound_generic_params: ThinVec::new(),
bounded_ty: ast::ptr::P(ty.clone()), bounded_ty: ast::ptr::P(ty.clone()),
bounds: vec![ast::GenericBound::Trait( bounds: vec![ast::GenericBound::Trait(ast::PolyTraitRef {
ast::PolyTraitRef { bound_generic_params: ThinVec::new(),
bound_generic_params: ThinVec::new(), modifiers: ast::TraitBoundModifiers::NONE,
trait_ref: ast::TraitRef { trait_ref: ast::TraitRef {
path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None }, path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
ref_id: DUMMY_NODE_ID, ref_id: DUMMY_NODE_ID,
},
span: DUMMY_SP,
}, },
ast::TraitBoundModifiers::NONE, span: DUMMY_SP,
)], })],
}; };
Some(new_where_bound_predicate) Some(new_where_bound_predicate)

View file

@ -783,7 +783,8 @@ pub fn eq_str_lit(l: &StrLit, r: &StrLit) -> bool {
} }
pub fn eq_poly_ref_trait(l: &PolyTraitRef, r: &PolyTraitRef) -> bool { pub fn eq_poly_ref_trait(l: &PolyTraitRef, r: &PolyTraitRef) -> bool {
eq_path(&l.trait_ref.path, &r.trait_ref.path) l.modifiers == r.modifiers
&& eq_path(&l.trait_ref.path, &r.trait_ref.path)
&& over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { && over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
eq_generic_param(l, r) eq_generic_param(l, r)
}) })
@ -817,7 +818,7 @@ pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool {
pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool { pub fn eq_generic_bound(l: &GenericBound, r: &GenericBound) -> bool {
use GenericBound::*; use GenericBound::*;
match (l, r) { match (l, r) {
(Trait(ptr1, tbm1), Trait(ptr2, tbm2)) => tbm1 == tbm2 && eq_poly_ref_trait(ptr1, ptr2), (Trait(ptr1), Trait(ptr2)) => eq_poly_ref_trait(ptr1, ptr2),
(Outlives(l), Outlives(r)) => eq_id(l.ident, r.ident), (Outlives(l), Outlives(r)) => eq_id(l.ident, r.ident),
_ => false, _ => false,
} }

View file

@ -180,7 +180,7 @@ impl Spanned for ast::GenericArg {
impl Spanned for ast::GenericBound { impl Spanned for ast::GenericBound {
fn span(&self) -> Span { fn span(&self) -> Span {
match *self { match *self {
ast::GenericBound::Trait(ref ptr, _) => ptr.span, ast::GenericBound::Trait(ref ptr) => ptr.span,
ast::GenericBound::Outlives(ref l) => l.ident.span, ast::GenericBound::Outlives(ref l) => l.ident.span,
ast::GenericBound::Use(_, span) => span, ast::GenericBound::Use(_, span) => span,
} }

View file

@ -610,16 +610,14 @@ impl Rewrite for ast::GenericBound {
fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
match *self { match *self {
ast::GenericBound::Trait( ast::GenericBound::Trait(ref poly_trait_ref) => {
ref poly_trait_ref, let snippet = context.snippet(self.span());
ast::TraitBoundModifiers { let has_paren = snippet.starts_with('(') && snippet.ends_with(')');
let ast::TraitBoundModifiers {
constness, constness,
asyncness, asyncness,
polarity, polarity,
}, } = poly_trait_ref.modifiers;
) => {
let snippet = context.snippet(self.span());
let has_paren = snippet.starts_with('(') && snippet.ends_with(')');
let mut constness = constness.as_str().to_string(); let mut constness = constness.as_str().to_string();
if !constness.is_empty() { if !constness.is_empty() {
constness.push(' '); constness.push(' ');