1
Fork 0

Extract AssocItem handling.

This commit is contained in:
Camille GILLOT 2022-04-01 16:05:42 +02:00
parent cdcc53b7dc
commit 228def7e20

View file

@ -1732,72 +1732,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|this| { |this| {
this.visit_generics(generics); this.visit_generics(generics);
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
this.resolve_trait_items(items);
let walk_assoc_item =
|this: &mut Self,
generics: &Generics,
kind,
item: &'ast AssocItem| {
this.with_generic_param_rib(
&generics.params,
AssocItemRibKind,
LifetimeRibKind::Generics {
binder: item.id,
span: generics.span,
kind,
},
|this| {
visit::walk_assoc_item(this, item, AssocCtxt::Trait)
},
);
};
this.with_trait_items(items, |this| {
for item in items {
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
this.visit_ty(ty);
// Only impose the restrictions of `ConstRibKind` for an
// actual constant expression in a provided default.
if let Some(expr) = default {
// We allow arbitrary const expressions inside of associated consts,
// even if they are potentially not const evaluatable.
//
// Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising.
this.with_constant_rib(
IsRepeatExpr::No,
HasGenericParams::Yes,
None,
|this| this.visit_expr(expr),
);
}
}
AssocItemKind::Fn(box Fn { generics, .. }) => {
walk_assoc_item(
this,
generics,
LifetimeBinderKind::Function,
item,
);
}
AssocItemKind::TyAlias(box TyAlias {
generics,
..
}) => {
walk_assoc_item(
this,
generics,
LifetimeBinderKind::Item,
item,
);
}
AssocItemKind::MacCall(_) => {
panic!("unexpanded macro in resolve!")
}
};
}
});
}, },
); );
}, },
@ -2073,16 +2008,53 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
} }
/// When evaluating a `trait` use its associated types' idents for suggestions in E0412. /// When evaluating a `trait` use its associated types' idents for suggestions in E0412.
fn with_trait_items<T>( fn resolve_trait_items(&mut self, trait_items: &'ast [P<AssocItem>]) {
&mut self,
trait_items: &'ast [P<AssocItem>],
f: impl FnOnce(&mut Self) -> T,
) -> T {
let trait_assoc_items = let trait_assoc_items =
replace(&mut self.diagnostic_metadata.current_trait_assoc_items, Some(&trait_items)); replace(&mut self.diagnostic_metadata.current_trait_assoc_items, Some(&trait_items));
let result = f(self);
let walk_assoc_item =
|this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| {
this.with_generic_param_rib(
&generics.params,
AssocItemRibKind,
LifetimeRibKind::Generics { binder: item.id, span: generics.span, kind },
|this| visit::walk_assoc_item(this, item, AssocCtxt::Trait),
);
};
for item in trait_items {
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
self.visit_ty(ty);
// Only impose the restrictions of `ConstRibKind` for an
// actual constant expression in a provided default.
if let Some(expr) = default {
// We allow arbitrary const expressions inside of associated consts,
// even if they are potentially not const evaluatable.
//
// Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising.
self.with_constant_rib(
IsRepeatExpr::No,
HasGenericParams::Yes,
None,
|this| this.visit_expr(expr),
);
}
}
AssocItemKind::Fn(box Fn { generics, .. }) => {
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
}
AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
walk_assoc_item(self, generics, LifetimeBinderKind::Item, item);
}
AssocItemKind::MacCall(_) => {
panic!("unexpanded macro in resolve!")
}
};
}
self.diagnostic_metadata.current_trait_assoc_items = trait_assoc_items; self.diagnostic_metadata.current_trait_assoc_items = trait_assoc_items;
result
} }
/// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`).
@ -2173,13 +2145,27 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
for item in impl_items { for item in impl_items {
this.resolve_impl_item(&**item);
}
});
});
},
);
});
});
});
});
});
}
fn resolve_impl_item(&mut self, item: &'ast AssocItem) {
use crate::ResolutionError::*; use crate::ResolutionError::*;
match &item.kind { match &item.kind {
AssocItemKind::Const(_default, _ty, _expr) => { AssocItemKind::Const(_default, _ty, _expr) => {
debug!("resolve_implementation AssocItemKind::Const"); debug!("resolve_implementation AssocItemKind::Const");
// If this is a trait impl, ensure the const // If this is a trait impl, ensure the const
// exists in trait // exists in trait
this.check_trait_item( self.check_trait_item(
item.id, item.id,
item.ident, item.ident,
&item.kind, &item.kind,
@ -2193,26 +2179,21 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
// //
// Type parameters can already be used and as associated consts are // Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising. // not used as part of the type system, this is far less surprising.
this.with_constant_rib( self.with_constant_rib(IsRepeatExpr::No, HasGenericParams::Yes, None, |this| {
IsRepeatExpr::No, visit::walk_assoc_item(this, item, AssocCtxt::Impl)
HasGenericParams::Yes, });
None,
|this| {
visit::walk_assoc_item(
this,
item,
AssocCtxt::Impl,
)
},
);
} }
AssocItemKind::Fn(box Fn { generics, .. }) => { AssocItemKind::Fn(box Fn { generics, .. }) => {
debug!("resolve_implementation AssocItemKind::Fn"); debug!("resolve_implementation AssocItemKind::Fn");
// We also need a new scope for the impl item type parameters. // We also need a new scope for the impl item type parameters.
this.with_generic_param_rib( self.with_generic_param_rib(
&generics.params, &generics.params,
AssocItemRibKind, AssocItemRibKind,
LifetimeRibKind::Generics { binder: item.id, span: generics.span, kind: LifetimeBinderKind::Function }, LifetimeRibKind::Generics {
binder: item.id,
span: generics.span,
kind: LifetimeBinderKind::Function,
},
|this| { |this| {
// If this is a trait impl, ensure the method // If this is a trait impl, ensure the method
// exists in trait // exists in trait
@ -2225,23 +2206,21 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|i, s, c| MethodNotMemberOfTrait(i, s, c), |i, s, c| MethodNotMemberOfTrait(i, s, c),
); );
visit::walk_assoc_item( visit::walk_assoc_item(this, item, AssocCtxt::Impl)
this,
item,
AssocCtxt::Impl,
)
}, },
); );
} }
AssocItemKind::TyAlias(box TyAlias { AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
generics, ..
}) => {
debug!("resolve_implementation AssocItemKind::TyAlias"); debug!("resolve_implementation AssocItemKind::TyAlias");
// We also need a new scope for the impl item type parameters. // We also need a new scope for the impl item type parameters.
this.with_generic_param_rib( self.with_generic_param_rib(
&generics.params, &generics.params,
AssocItemRibKind, AssocItemRibKind,
LifetimeRibKind::Generics { binder: item.id, span: generics.span, kind: LifetimeBinderKind::Item }, LifetimeRibKind::Generics {
binder: item.id,
span: generics.span,
kind: LifetimeBinderKind::Item,
},
|this| { |this| {
// If this is a trait impl, ensure the type // If this is a trait impl, ensure the type
// exists in trait // exists in trait
@ -2254,11 +2233,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|i, s, c| TypeNotMemberOfTrait(i, s, c), |i, s, c| TypeNotMemberOfTrait(i, s, c),
); );
visit::walk_assoc_item( visit::walk_assoc_item(this, item, AssocCtxt::Impl)
this,
item,
AssocCtxt::Impl,
)
}, },
); );
} }
@ -2267,16 +2242,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
} }
} }
} }
});
});
},
);
});
});
});
});
});
}
fn check_trait_item<F>( fn check_trait_item<F>(
&mut self, &mut self,