1
Fork 0

Rollup merge of #131652 - compiler-errors:modifiers, r=Nadrieril,jieyouxu

Move polarity into `PolyTraitRef` rather than storing it on the side

Arguably we could move these modifiers into `TraitRef` instead of `PolyTraitRef`, but I see `TraitRef` as simply the *path* part of the trait ref. It doesn't really matter -- refactoring this further is much easier now.
This commit is contained in:
Matthias Krüger 2024-10-15 05:11:37 +02:00 committed by GitHub
commit 4d53a28cac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 216 additions and 199 deletions

View file

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

View file

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

View file

@ -1219,13 +1219,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let bound = this.lower_poly_trait_ref(
&PolyTraitRef {
bound_generic_params: ThinVec::new(),
modifiers: TraitBoundModifiers::NONE,
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
span: t.span,
},
itctx,
TraitBoundModifiers::NONE,
);
let bound = (bound, hir::TraitBoundModifier::None);
let bounds = this.arena.alloc_from_iter([bound]);
let lifetime_bound = this.elided_dyn_bound(t.span);
(bounds, lifetime_bound)
@ -1326,10 +1325,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// We can safely ignore constness here since AST validation
// takes care of rejecting invalid modifier combinations and
// const trait bounds in trait object types.
GenericBound::Trait(ty, modifiers) => {
let trait_ref = this.lower_poly_trait_ref(ty, itctx, *modifiers);
let polarity = this.lower_trait_bound_modifiers(*modifiers);
Some((trait_ref, polarity))
GenericBound::Trait(ty) => {
let trait_ref = this.lower_poly_trait_ref(ty, itctx);
Some(trait_ref)
}
GenericBound::Outlives(lifetime) => {
if lifetime_bound.is_none() {
@ -1958,21 +1956,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span_ext: DUMMY_SP,
});
hir::GenericBound::Trait(
hir::PolyTraitRef {
bound_generic_params: &[],
trait_ref: hir::TraitRef {
path: self.make_lang_item_path(
trait_lang_item,
opaque_ty_span,
Some(bound_args),
),
hir_ref_id: self.next_id(),
},
span: opaque_ty_span,
hir::GenericBound::Trait(hir::PolyTraitRef {
bound_generic_params: &[],
modifiers: hir::TraitBoundModifier::None,
trait_ref: hir::TraitRef {
path: self.make_lang_item_path(trait_lang_item, opaque_ty_span, Some(bound_args)),
hir_ref_id: self.next_id(),
},
hir::TraitBoundModifier::None,
)
span: opaque_ty_span,
})
}
#[instrument(level = "trace", skip(self))]
@ -1982,10 +1974,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
itctx: ImplTraitContext,
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait(
self.lower_poly_trait_ref(p, itctx, *modifiers),
self.lower_trait_bound_modifiers(*modifiers),
),
GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)),
GenericBound::Outlives(lifetime) => {
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
}
@ -2189,12 +2178,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
p: &PolyTraitRef,
itctx: ImplTraitContext,
modifiers: ast::TraitBoundModifiers,
) -> hir::PolyTraitRef<'hir> {
let 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);
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
hir::PolyTraitRef {
bound_generic_params,
modifiers,
trait_ref,
span: self.lower_span(p.span),
}
}
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
@ -2634,10 +2628,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => {
let principal = hir::PolyTraitRef {
bound_generic_params: &[],
modifiers: hir::TraitBoundModifier::None,
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
span: self.lower_span(span),
};
let principal = (principal, hir::TraitBoundModifier::None);
// The original ID is taken by the `PolyTraitRef`,
// so the `Ty` itself needs a different one.

View file

@ -1263,7 +1263,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
if !bound_pred.bound_generic_params.is_empty() {
for bound in &bound_pred.bounds {
match bound {
GenericBound::Trait(t, _) => {
GenericBound::Trait(t) => {
if !t.bound_generic_params.is_empty() {
self.dcx()
.emit_err(errors::NestedLifetimes { span: t.span });
@ -1283,8 +1283,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
match bound {
GenericBound::Trait(trait_ref, modifiers) => {
match (ctxt, modifiers.constness, modifiers.polarity) {
GenericBound::Trait(trait_ref) => {
match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
if !self.features.more_maybe_bounds =>
{
@ -1324,7 +1324,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
// 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()
{
match segment.args.as_deref() {
@ -1672,7 +1672,9 @@ fn deny_equality_constraints(
}),
) {
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]
.iter()
.map(|segment| segment.ident.name)
@ -1700,7 +1702,9 @@ fn deny_equality_constraints(
) {
if ident == potential_param.ident {
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);
}
}

View file

@ -8,7 +8,6 @@ mod item;
use std::borrow::Cow;
use ast::TraitBoundModifiers;
use rustc_ast::attr::AttrIdGenerator;
use rustc_ast::ptr::P;
use rustc_ast::token::{
@ -1253,6 +1252,27 @@ impl<'a> State<'a> {
fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
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)
}
@ -1740,31 +1760,7 @@ impl<'a> State<'a> {
}
match bound {
GenericBound::Trait(
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());
}
}
GenericBound::Trait(tref) => {
self.print_poly_trait_ref(tref);
}
GenericBound::Outlives(lt) => self.print_lifetime(*lt),

View file

@ -254,7 +254,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
debug!(?hrtb_bounds);
hrtb_bounds.iter().for_each(|bound| {
let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }, _) = bound else {
let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }) = bound else {
return;
};
diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static);
@ -277,7 +277,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
return;
};
bounds.iter().for_each(|bd| {
if let Trait(PolyTraitRef { trait_ref: tr_ref, .. }, _) = bd
if let Trait(PolyTraitRef { trait_ref: tr_ref, .. }) = bd
&& let Def(_, res_defid) = tr_ref.path.res
&& res_defid == trait_res_defid // trait id matches
&& let TyKind::Path(Resolved(_, path)) = bounded_ty.kind

View file

@ -837,7 +837,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
hir_ty
);
};
if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref, _)], .. } = opaque_ty
if let hir::OpaqueTy { bounds: [hir::GenericBound::Trait(trait_ref)], .. } = opaque_ty
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
&& let Some(args) = segment.args
&& let [constraint] = args.constraints

View file

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

View file

@ -143,24 +143,25 @@ impl<'a> ExtCtxt<'a> {
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 {
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),
span,
}
}
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 {
polarity: ast::BoundPolarity::Positive,
constness: if is_const {
ast::BoundConstness::Maybe(DUMMY_SP)
} else {
ast::BoundConstness::Never
},
asyncness: ast::BoundAsyncness::Normal,
})
ast::GenericBound::Trait(self.poly_trait_ref(path.span, path, is_const))
}
pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime {

View file

@ -520,7 +520,7 @@ pub enum TraitBoundModifier {
#[derive(Clone, Copy, Debug, HashStable_Generic)]
pub enum GenericBound<'hir> {
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
Trait(PolyTraitRef<'hir>),
Outlives(&'hir Lifetime),
Use(&'hir [PreciseCapturingArg<'hir>], Span),
}
@ -528,7 +528,7 @@ pub enum GenericBound<'hir> {
impl GenericBound<'_> {
pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
match self {
GenericBound::Trait(data, _) => Some(&data.trait_ref),
GenericBound::Trait(data) => Some(&data.trait_ref),
_ => None,
}
}
@ -2874,11 +2874,7 @@ pub enum TyKind<'hir> {
OpaqueDef(&'hir OpaqueTy<'hir>, &'hir [GenericArg<'hir>]),
/// A trait object type `Bound1 + Bound2 + Bound3`
/// where `Bound` is a trait or a lifetime.
TraitObject(
&'hir [(PolyTraitRef<'hir>, TraitBoundModifier)],
&'hir Lifetime,
TraitObjectSyntax,
),
TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax),
/// Unused for now.
Typeof(&'hir AnonConst),
/// `TyKind::Infer` means the type should be inferred instead of it having been
@ -3182,6 +3178,11 @@ pub struct PolyTraitRef<'hir> {
/// The `'a` in `for<'a> Foo<&'a T>`.
pub bound_generic_params: &'hir [GenericParam<'hir>],
/// The constness and polarity of the trait ref.
///
/// The `async` modifier is lowered directly into a different trait for now.
pub modifiers: TraitBoundModifier,
/// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`.
pub trait_ref: TraitRef<'hir>,

View file

@ -905,7 +905,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
try_visit!(visitor.visit_array_length(length));
}
TyKind::TraitObject(bounds, ref lifetime, _syntax) => {
for (bound, _modifier) in bounds {
for bound in bounds {
try_visit!(visitor.visit_poly_trait_ref(bound));
}
try_visit!(visitor.visit_lifetime(lifetime));
@ -1160,7 +1160,7 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>(
bound: &'v GenericBound<'v>,
) -> V::Result {
match *bound {
GenericBound::Trait(ref typ, _modifier) => visitor.visit_poly_trait_ref(typ),
GenericBound::Trait(ref typ) => visitor.visit_poly_trait_ref(typ),
GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
GenericBound::Use(args, _) => {
walk_list!(visitor, visit_precise_capturing_arg, args);

View file

@ -832,7 +832,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> {
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
match ty.kind {
hir::TyKind::TraitObject([(trait_ref, _)], ..) => match trait_ref.trait_ref.path.segments {
hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments {
[s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()),
_ => false,
},

View file

@ -866,7 +866,7 @@ impl<'tcx> ItemCtxt<'tcx> {
#[instrument(level = "trace", skip(self))]
fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
match b {
hir::GenericBound::Trait(poly_trait_ref, _) => {
hir::GenericBound::Trait(poly_trait_ref) => {
let trait_ref = &poly_trait_ref.trait_ref;
if let Some(trait_did) = trait_ref.trait_def_id() {
self.tcx.trait_may_define_assoc_item(trait_did, assoc_name)

View file

@ -644,7 +644,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
debug!(?bounds, ?lifetime, "TraitObject");
let scope = Scope::TraitRefBoundary { s: self.scope };
self.with(scope, |this| {
for (bound, _) in bounds {
for bound in bounds {
this.visit_poly_trait_ref_inner(
bound,
NonLifetimeBinderAllowed::Deny("trait object types"),
@ -1918,7 +1918,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
return None;
}
predicate.bounds.iter().find_map(|bound| {
let hir::GenericBound::Trait(trait_, _) = bound else {
let hir::GenericBound::Trait(trait_) = bound else {
return None;
};
BoundVarContext::supertrait_hrtb_vars(

View file

@ -44,10 +44,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
for hir_bound in hir_bounds {
let hir::GenericBound::Trait(ptr, modifier) = hir_bound else {
let hir::GenericBound::Trait(ptr) = hir_bound else {
continue;
};
match modifier {
match ptr.modifiers {
hir::TraitBoundModifier::Maybe => unbounds.push(ptr),
hir::TraitBoundModifier::Negative => {
if let Some(sized_def_id) = sized_def_id
@ -156,8 +156,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
{
for hir_bound in hir_bounds {
match hir_bound {
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
let (constness, polarity) = match modifier {
hir::GenericBound::Trait(poly_trait_ref) => {
let (constness, polarity) = match poly_trait_ref.modifiers {
hir::TraitBoundModifier::Const => {
(ty::BoundConstness::Const, ty::PredicatePolarity::Positive)
}

View file

@ -30,7 +30,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&self,
span: Span,
hir_id: hir::HirId,
hir_trait_bounds: &[(hir::PolyTraitRef<'tcx>, hir::TraitBoundModifier)],
hir_trait_bounds: &[hir::PolyTraitRef<'tcx>],
lifetime: &hir::Lifetime,
representation: DynKind,
) -> Ty<'tcx> {
@ -39,8 +39,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let mut bounds = Bounds::default();
let mut potential_assoc_types = Vec::new();
let dummy_self = self.tcx().types.trait_object_dummy_self;
for (trait_bound, modifier) in hir_trait_bounds.iter().rev() {
if *modifier == hir::TraitBoundModifier::Maybe {
for trait_bound in hir_trait_bounds.iter().rev() {
// FIXME: This doesn't handle `? const`.
if trait_bound.modifiers == hir::TraitBoundModifier::Maybe {
continue;
}
if let GenericArgCountResult {
@ -263,7 +264,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let args = tcx.mk_args(&args);
let span = i.bottom().1;
let empty_generic_args = hir_trait_bounds.iter().any(|(hir_bound, _)| {
let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| {
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
&& hir_bound.span.contains(span)
});

View file

@ -718,7 +718,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&self,
associated_types: FxIndexMap<Span, FxIndexSet<DefId>>,
potential_assoc_types: Vec<usize>,
trait_bounds: &[(hir::PolyTraitRef<'_>, hir::TraitBoundModifier)],
trait_bounds: &[hir::PolyTraitRef<'_>],
) {
if associated_types.values().all(|v| v.is_empty()) {
return;
@ -764,12 +764,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// related to issue #91997, turbofishes added only when in an expr or pat
let mut in_expr_or_pat = false;
if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.0.trait_ref.hir_ref_id));
let grandparent = tcx.parent_hir_node(tcx.parent_hir_id(bound.trait_ref.hir_ref_id));
in_expr_or_pat = match grandparent {
hir::Node::Expr(_) | hir::Node::Pat(_) => true,
_ => false,
};
match bound.0.trait_ref.path.segments {
match bound.trait_ref.path.segments {
// FIXME: `trait_ref.path.span` can point to a full path with multiple
// segments, even though `trait_ref.path.segments` is of length `1`. Work
// around that bug here, even though it should be fixed elsewhere.
@ -810,7 +810,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// and we can then use their span to indicate this to the user.
let bound_names = trait_bounds
.iter()
.filter_map(|(poly_trait_ref, _)| {
.filter_map(|poly_trait_ref| {
let path = poly_trait_ref.trait_ref.path.segments.last()?;
let args = path.args?;

View file

@ -50,7 +50,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.ok()
.is_some_and(|s| s.trim_end().ends_with('<'));
let is_global = poly_trait_ref.0.trait_ref.path.is_global();
let is_global = poly_trait_ref.trait_ref.path.is_global();
let mut sugg = vec![(
self_ty.span.shrink_to_lo(),
@ -211,7 +211,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Check if trait object is safe for suggesting dynamic dispatch.
let is_dyn_compatible = match self_ty.kind {
hir::TyKind::TraitObject(objects, ..) => {
objects.iter().all(|(o, _)| match o.trait_ref.path.res {
objects.iter().all(|o| match o.trait_ref.path.res {
Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id),
_ => false,
})

View file

@ -301,16 +301,13 @@ impl<'a> State<'a> {
self.word_space("dyn");
}
let mut first = true;
for (bound, modifier) in bounds {
for bound in bounds {
if first {
first = false;
} else {
self.nbsp();
self.word_space("+");
}
if *modifier == TraitBoundModifier::Maybe {
self.word("?");
}
self.print_poly_trait_ref(bound);
}
if !lifetime.is_elided() {
@ -679,6 +676,10 @@ impl<'a> State<'a> {
}
fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) {
// FIXME: This isn't correct!
if t.modifiers == TraitBoundModifier::Maybe {
self.word("?");
}
self.print_formal_generic_params(t.bound_generic_params);
self.print_trait_ref(&t.trait_ref);
}
@ -2077,10 +2078,7 @@ impl<'a> State<'a> {
}
match bound {
GenericBound::Trait(tref, modifier) => {
if modifier == &TraitBoundModifier::Maybe {
self.word("?");
}
GenericBound::Trait(tref) => {
self.print_poly_trait_ref(tref);
}
GenericBound::Outlives(lt) => {

View file

@ -849,7 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::FnRetTy::Return(hir_ty) => {
if let hir::TyKind::OpaqueDef(op_ty, ..) = hir_ty.kind
// FIXME: account for RPITIT.
&& let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds
&& let [hir::GenericBound::Trait(trait_ref)] = op_ty.bounds
&& let Some(hir::PathSegment { args: Some(generic_args), .. }) =
trait_ref.trait_ref.path.segments.last()
&& let [constraint] = generic_args.constraints
@ -1035,7 +1035,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// extract all bounds from the source code using their spans
let all_matching_bounds_strs = predicates_from_where
.filter_map(|bound| match bound {
GenericBound::Trait(_, _) => {
GenericBound::Trait(_) => {
self.tcx.sess.source_map().span_to_snippet(bound.span()).ok()
}
_ => None,

View file

@ -112,10 +112,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) {
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
for (bound, modifier) in &bounds[..] {
for bound in &bounds[..] {
let def_id = bound.trait_ref.trait_def_id();
if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop))
&& *modifier != hir::TraitBoundModifier::Maybe
// FIXME: ?Drop is not a thing.
&& bound.modifiers != hir::TraitBoundModifier::Maybe
{
let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });

View file

@ -192,7 +192,8 @@ fn suggest_changing_unsized_bound(
.iter()
.enumerate()
.filter(|(_, bound)| {
if let hir::GenericBound::Trait(poly, hir::TraitBoundModifier::Maybe) = bound
if let hir::GenericBound::Trait(poly) = bound
&& poly.modifiers == hir::TraitBoundModifier::Maybe
&& poly.trait_ref.trait_def_id() == def_id
{
true

View file

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

View file

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

View file

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

View file

@ -519,11 +519,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
continue;
};
for bound in bounds {
let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE) = bound
else {
let ast::GenericBound::Trait(trait_ref) = bound else {
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(
constraint.ident.span.between(trait_ref.span),
"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 {
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![];
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| {
// Only consider type params with exactly one trait bound.
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
&& param.ident.span.eq_ctxt(span)
{
@ -1333,8 +1335,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
}
if let (
[ast::PathSegment { args: None, .. }],
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifiers::NONE)],
[ast::GenericBound::Trait(poly_trait_ref)],
) = (&type_param_path.segments[..], &bounds[..])
&& poly_trait_ref.modifiers == ast::TraitBoundModifiers::NONE
{
if let [ast::PathSegment { ident, args: None, .. }] =
&poly_trait_ref.trait_ref.path.segments[..]
@ -2814,7 +2817,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
&& bounded_ty.id == binder
{
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
.span
.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 =
LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] };
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);
}
}
@ -3444,17 +3447,15 @@ fn mk_where_bound_predicate(
span: DUMMY_SP,
bound_generic_params: ThinVec::new(),
bounded_ty: ast::ptr::P(ty.clone()),
bounds: vec![ast::GenericBound::Trait(
ast::PolyTraitRef {
bound_generic_params: ThinVec::new(),
trait_ref: ast::TraitRef {
path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
ref_id: DUMMY_NODE_ID,
},
span: DUMMY_SP,
bounds: vec![ast::GenericBound::Trait(ast::PolyTraitRef {
bound_generic_params: ThinVec::new(),
modifiers: ast::TraitBoundModifiers::NONE,
trait_ref: ast::TraitRef {
path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
ref_id: DUMMY_NODE_ID,
},
ast::TraitBoundModifiers::NONE,
)],
span: DUMMY_SP,
})],
};
Some(new_where_bound_predicate)

View file

@ -86,7 +86,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
}
hir::TyKind::TraitObject(bounds, ..) => {
for (bound, _) in bounds {
for bound in bounds {
self.current_index.shift_in(1);
self.visit_poly_trait_ref(bound);
self.current_index.shift_out(1);

View file

@ -599,7 +599,7 @@ impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
_,
) = t.kind
{
for (ptr, _) in poly_trait_refs {
for ptr in poly_trait_refs {
if Some(self.1) == ptr.trait_ref.trait_def_id() {
self.0.push(ptr.span);
}

View file

@ -894,7 +894,9 @@ fn foo(&self) -> Self::T { String::new() }
// FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
let trait_bounds = bounds.iter().filter_map(|bound| match bound {
hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => Some(ptr),
hir::GenericBound::Trait(ptr) if ptr.modifiers == hir::TraitBoundModifier::None => {
Some(ptr)
}
_ => None,
});

View file

@ -740,9 +740,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| match (
left, right,
) {
(hir::GenericBound::Trait(tl, ml), hir::GenericBound::Trait(tr, mr))
// FIXME: Suspicious
(hir::GenericBound::Trait(tl), hir::GenericBound::Trait(tr))
if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
&& ml == mr =>
&& tl.modifiers == tr.modifiers =>
{
true
}

View file

@ -439,7 +439,7 @@ pub fn report_dyn_incompatibility<'tcx>(
if tcx.parent_hir_node(hir_id).fn_sig().is_some() {
// Do not suggest `impl Trait` when dealing with things like super-traits.
err.span_suggestion_verbose(
ty.span.until(trait_ref.0.span),
ty.span.until(trait_ref.span),
"consider using an opaque type instead",
"impl ",
Applicability::MaybeIncorrect,

View file

@ -3074,11 +3074,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
match ty.kind {
hir::TyKind::TraitObject(traits, _, _) => {
let (span, kw) = match traits {
[(first, _), ..] if first.span.lo() == ty.span.lo() => {
[first, ..] if first.span.lo() == ty.span.lo() => {
// Missing `dyn` in front of trait object.
(ty.span.shrink_to_lo(), "dyn ")
}
[(first, _), ..] => (ty.span.until(first.span), ""),
[first, ..] => (ty.span.until(first.span), ""),
[] => span_bug!(ty.span, "trait object with no traits: {ty:?}"),
};
let needs_parens = traits.len() != 1;
@ -5162,7 +5162,7 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>(
let async_span = tcx.sess.source_map().span_extend_while_whitespace(async_span);
let future = tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
let [hir::GenericBound::Trait(trait_ref, _)] = future.bounds else {
let [hir::GenericBound::Trait(trait_ref)] = future.bounds else {
// `async fn` should always lower to a single bound... but don't ICE.
return None;
};

View file

@ -125,7 +125,7 @@ fn sized_trait_bound_spans<'tcx>(
bounds: hir::GenericBounds<'tcx>,
) -> impl 'tcx + Iterator<Item = Span> {
bounds.iter().filter_map(move |b| match b {
hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
hir::GenericBound::Trait(trait_ref)
if trait_has_sized_self(
tcx,
trait_ref.trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),