mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Use dedicated PreciseCapturingArg for representing what goes in use<>
This commit is contained in:
parent
647b672f16
commit
fc9e344874
@ -2132,7 +2132,7 @@ pub enum TyKind {
|
|||||||
/// The `NodeId` exists to prevent lowering from having to
|
/// The `NodeId` exists to prevent lowering from having to
|
||||||
/// generate `NodeId`s on the fly, which would complicate
|
/// generate `NodeId`s on the fly, which would complicate
|
||||||
/// the generation of opaque `type Foo = impl Trait` items significantly.
|
/// the generation of opaque `type Foo = impl Trait` items significantly.
|
||||||
ImplTrait(NodeId, GenericBounds, Option<P<GenericArgs>>),
|
ImplTrait(NodeId, GenericBounds, Option<ThinVec<PreciseCapturingArg>>),
|
||||||
/// No-op; kept solely so that we can pretty-print faithfully.
|
/// No-op; kept solely so that we can pretty-print faithfully.
|
||||||
Paren(P<Ty>),
|
Paren(P<Ty>),
|
||||||
/// Unused for now.
|
/// Unused for now.
|
||||||
@ -2188,6 +2188,14 @@ pub enum TraitObjectSyntax {
|
|||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
|
||||||
|
pub enum PreciseCapturingArg {
|
||||||
|
/// Lifetime parameter
|
||||||
|
Lifetime(Lifetime),
|
||||||
|
/// Type or const parameter
|
||||||
|
Arg(Ident, NodeId),
|
||||||
|
}
|
||||||
|
|
||||||
/// Inline assembly operand explicit register or register class.
|
/// Inline assembly operand explicit register or register class.
|
||||||
///
|
///
|
||||||
/// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.
|
/// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.
|
||||||
|
@ -259,6 +259,14 @@ pub trait MutVisitor: Sized {
|
|||||||
noop_visit_param_bound(tpb, self);
|
noop_visit_param_bound(tpb, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_precise_capturing_args(&mut self, args: &mut ThinVec<PreciseCapturingArg>) {
|
||||||
|
noop_visit_precise_capturing_args(args, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_precise_capturing_arg(&mut self, arg: &mut PreciseCapturingArg) {
|
||||||
|
noop_visit_precise_capturing_arg(arg, self);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_mt(&mut self, mt: &mut MutTy) {
|
fn visit_mt(&mut self, mt: &mut MutTy) {
|
||||||
noop_visit_mt(mt, self);
|
noop_visit_mt(mt, self);
|
||||||
}
|
}
|
||||||
@ -522,7 +530,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
|||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
|
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
|
||||||
visit_opt(precise_capturing, |precise_capturing| {
|
visit_opt(precise_capturing, |precise_capturing| {
|
||||||
vis.visit_generic_args(precise_capturing);
|
vis.visit_precise_capturing_args(precise_capturing);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
|
TyKind::MacCall(mac) => vis.visit_mac_call(mac),
|
||||||
@ -917,6 +925,27 @@ pub fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn noop_visit_precise_capturing_args<T: MutVisitor>(
|
||||||
|
args: &mut ThinVec<PreciseCapturingArg>,
|
||||||
|
vis: &mut T,
|
||||||
|
) {
|
||||||
|
for arg in args {
|
||||||
|
vis.visit_precise_capturing_arg(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn noop_visit_precise_capturing_arg<T: MutVisitor>(arg: &mut PreciseCapturingArg, vis: &mut T) {
|
||||||
|
match arg {
|
||||||
|
PreciseCapturingArg::Lifetime(lt) => {
|
||||||
|
vis.visit_lifetime(lt);
|
||||||
|
}
|
||||||
|
PreciseCapturingArg::Arg(ident, id) => {
|
||||||
|
vis.visit_ident(ident);
|
||||||
|
vis.visit_id(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn noop_flat_map_generic_param<T: MutVisitor>(
|
pub fn noop_flat_map_generic_param<T: MutVisitor>(
|
||||||
mut param: GenericParam,
|
mut param: GenericParam,
|
||||||
vis: &mut T,
|
vis: &mut T,
|
||||||
|
@ -20,6 +20,7 @@ use rustc_span::Span;
|
|||||||
|
|
||||||
pub use rustc_ast_ir::visit::VisitorResult;
|
pub use rustc_ast_ir::visit::VisitorResult;
|
||||||
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
|
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
|
||||||
|
use thin_vec::ThinVec;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum AssocCtxt {
|
pub enum AssocCtxt {
|
||||||
@ -184,6 +185,12 @@ pub trait Visitor<'ast>: Sized {
|
|||||||
fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
|
fn visit_param_bound(&mut self, bounds: &'ast GenericBound, _ctxt: BoundKind) -> Self::Result {
|
||||||
walk_param_bound(self, bounds)
|
walk_param_bound(self, bounds)
|
||||||
}
|
}
|
||||||
|
fn visit_precise_capturing_args(&mut self, args: &'ast ThinVec<PreciseCapturingArg>) {
|
||||||
|
walk_precise_capturing_args(self, args);
|
||||||
|
}
|
||||||
|
fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
|
||||||
|
walk_precise_capturing_arg(self, arg);
|
||||||
|
}
|
||||||
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
|
fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef) -> Self::Result {
|
||||||
walk_poly_trait_ref(self, t)
|
walk_poly_trait_ref(self, t)
|
||||||
}
|
}
|
||||||
@ -459,7 +466,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
|
|||||||
}
|
}
|
||||||
TyKind::ImplTrait(_, bounds, precise_capturing) => {
|
TyKind::ImplTrait(_, bounds, precise_capturing) => {
|
||||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
|
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Impl);
|
||||||
visit_opt!(visitor, visit_generic_args, precise_capturing);
|
visit_opt!(visitor, visit_precise_capturing_args, precise_capturing);
|
||||||
}
|
}
|
||||||
TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
|
TyKind::Typeof(expression) => try_visit!(visitor.visit_anon_const(expression)),
|
||||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
|
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Dummy | TyKind::Err(_) => {}
|
||||||
@ -638,6 +645,29 @@ pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_precise_capturing_args<'a, V: Visitor<'a>>(
|
||||||
|
visitor: &mut V,
|
||||||
|
args: &'a ThinVec<PreciseCapturingArg>,
|
||||||
|
) {
|
||||||
|
for arg in args {
|
||||||
|
visitor.visit_precise_capturing_arg(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>(
|
||||||
|
visitor: &mut V,
|
||||||
|
arg: &'a PreciseCapturingArg,
|
||||||
|
) {
|
||||||
|
match arg {
|
||||||
|
PreciseCapturingArg::Lifetime(lt) => {
|
||||||
|
visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg);
|
||||||
|
}
|
||||||
|
PreciseCapturingArg::Arg(ident, _) => {
|
||||||
|
visitor.visit_ident(*ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk_generic_param<'a, V: Visitor<'a>>(
|
pub fn walk_generic_param<'a, V: Visitor<'a>>(
|
||||||
visitor: &mut V,
|
visitor: &mut V,
|
||||||
param: &'a GenericParam,
|
param: &'a GenericParam,
|
||||||
|
@ -1525,7 +1525,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
bounds: &GenericBounds,
|
bounds: &GenericBounds,
|
||||||
fn_kind: Option<FnDeclKind>,
|
fn_kind: Option<FnDeclKind>,
|
||||||
itctx: ImplTraitContext,
|
itctx: ImplTraitContext,
|
||||||
precise_capturing: Option<&ast::GenericArgs>,
|
precise_capturing: Option<&[ast::PreciseCapturingArg]>,
|
||||||
) -> hir::TyKind<'hir> {
|
) -> hir::TyKind<'hir> {
|
||||||
// Make sure we know that some funky desugaring has been going on here.
|
// Make sure we know that some funky desugaring has been going on here.
|
||||||
// This is a first: there is code in other places like for loop
|
// This is a first: there is code in other places like for loop
|
||||||
@ -1534,58 +1534,55 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// frequently opened issues show.
|
// frequently opened issues show.
|
||||||
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
|
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
|
||||||
|
|
||||||
let captured_lifetimes_to_duplicate = if let Some(precise_capturing) = precise_capturing {
|
let captured_lifetimes_to_duplicate =
|
||||||
let ast::GenericArgs::AngleBracketed(precise_capturing) = precise_capturing else {
|
if let Some(precise_capturing) = precise_capturing_args {
|
||||||
panic!("we only parse angle-bracketed args")
|
// We'll actually validate these later on; all we need is the list of
|
||||||
};
|
// lifetimes to duplicate during this portion of lowering.
|
||||||
// We'll actually validate these later on; all we need is the list of
|
precise_capturing
|
||||||
// lifetimes to duplicate during this portion of lowering.
|
.iter()
|
||||||
precise_capturing
|
.filter_map(|arg| match arg {
|
||||||
.args
|
ast::PreciseCapturingArg::Lifetime(lt) => Some(*lt),
|
||||||
.iter()
|
ast::PreciseCapturingArg::Arg(..) => None,
|
||||||
.filter_map(|arg| match arg {
|
})
|
||||||
ast::AngleBracketedArg::Arg(ast::GenericArg::Lifetime(lt)) => Some(*lt),
|
.collect()
|
||||||
_ => None,
|
} else {
|
||||||
})
|
match origin {
|
||||||
.collect()
|
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
||||||
} else {
|
// type alias impl trait and associated type position impl trait were
|
||||||
match origin {
|
// decided to capture all in-scope lifetimes, which we collect for
|
||||||
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
// all opaques during resolution.
|
||||||
// type alias impl trait and associated type position impl trait were
|
|
||||||
// decided to capture all in-scope lifetimes, which we collect for
|
|
||||||
// all opaques during resolution.
|
|
||||||
self.resolver
|
|
||||||
.take_extra_lifetime_params(opaque_ty_node_id)
|
|
||||||
.into_iter()
|
|
||||||
.map(|(ident, id, _)| Lifetime { id, ident })
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
hir::OpaqueTyOrigin::FnReturn(..) => {
|
|
||||||
if matches!(
|
|
||||||
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
|
|
||||||
FnDeclKind::Impl | FnDeclKind::Trait
|
|
||||||
) || self.tcx.features().lifetime_capture_rules_2024
|
|
||||||
|| span.at_least_rust_2024()
|
|
||||||
{
|
|
||||||
// return-position impl trait in trait was decided to capture all
|
|
||||||
// in-scope lifetimes, which we collect for all opaques during resolution.
|
|
||||||
self.resolver
|
self.resolver
|
||||||
.take_extra_lifetime_params(opaque_ty_node_id)
|
.take_extra_lifetime_params(opaque_ty_node_id)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(ident, id, _)| Lifetime { id, ident })
|
.map(|(ident, id, _)| Lifetime { id, ident })
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
}
|
||||||
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
|
hir::OpaqueTyOrigin::FnReturn(..) => {
|
||||||
// example, we only need to duplicate lifetimes that appear in the
|
if matches!(
|
||||||
// bounds, since those are the only ones that are captured by the opaque.
|
fn_kind.expect("expected RPITs to be lowered with a FnKind"),
|
||||||
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
|
FnDeclKind::Impl | FnDeclKind::Trait
|
||||||
|
) || self.tcx.features().lifetime_capture_rules_2024
|
||||||
|
|| span.at_least_rust_2024()
|
||||||
|
{
|
||||||
|
// return-position impl trait in trait was decided to capture all
|
||||||
|
// in-scope lifetimes, which we collect for all opaques during resolution.
|
||||||
|
self.resolver
|
||||||
|
.take_extra_lifetime_params(opaque_ty_node_id)
|
||||||
|
.into_iter()
|
||||||
|
.map(|(ident, id, _)| Lifetime { id, ident })
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
// in fn return position, like the `fn test<'a>() -> impl Debug + 'a`
|
||||||
|
// example, we only need to duplicate lifetimes that appear in the
|
||||||
|
// bounds, since those are the only ones that are captured by the opaque.
|
||||||
|
lifetime_collector::lifetimes_in_bounds(self.resolver, bounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hir::OpaqueTyOrigin::AsyncFn(..) => {
|
||||||
|
unreachable!("should be using `lower_async_fn_ret_ty`")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::OpaqueTyOrigin::AsyncFn(..) => {
|
};
|
||||||
unreachable!("should be using `lower_async_fn_ret_ty`")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
debug!(?captured_lifetimes_to_duplicate);
|
debug!(?captured_lifetimes_to_duplicate);
|
||||||
|
|
||||||
self.lower_opaque_inner(
|
self.lower_opaque_inner(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use super::{Parser, PathStyle, TokenType, Trailing};
|
use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
|
||||||
|
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
|
self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
|
||||||
@ -14,7 +14,7 @@ use rustc_ast::util::case::Case;
|
|||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
|
self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound,
|
||||||
GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef,
|
GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef,
|
||||||
TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID,
|
PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID,
|
||||||
};
|
};
|
||||||
use rustc_errors::{Applicability, PResult};
|
use rustc_errors::{Applicability, PResult};
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
@ -671,13 +671,10 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// parse precise captures, if any.
|
// parse precise captures, if any.
|
||||||
let precise_capturing = if self.eat_keyword(kw::Use) {
|
let precise_capturing = if self.eat_keyword(kw::Use) {
|
||||||
self.expect_lt()?;
|
|
||||||
let use_span = self.prev_token.span;
|
let use_span = self.prev_token.span;
|
||||||
self.psess.gated_spans.gate(sym::precise_capturing, use_span);
|
self.psess.gated_spans.gate(sym::precise_capturing, use_span);
|
||||||
let lo = self.token.span;
|
let args = self.parse_precise_capturing_args()?;
|
||||||
let args = self.parse_angle_args(None)?;
|
Some(args)
|
||||||
self.expect_gt()?;
|
|
||||||
Some(ast::AngleBracketedArgs { args, span: lo.to(self.prev_token.span) }.into())
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -690,6 +687,25 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, precise_capturing))
|
Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, precise_capturing))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_precise_capturing_args(&mut self) -> PResult<'a, ThinVec<PreciseCapturingArg>> {
|
||||||
|
Ok(self
|
||||||
|
.parse_unspanned_seq(
|
||||||
|
&TokenKind::Lt,
|
||||||
|
&TokenKind::Gt,
|
||||||
|
SeqSep::trailing_allowed(token::Comma),
|
||||||
|
|self_| {
|
||||||
|
if self_.check_ident() {
|
||||||
|
Ok(PreciseCapturingArg::Arg(self_.parse_ident().unwrap(), DUMMY_NODE_ID))
|
||||||
|
} else if self_.check_lifetime() {
|
||||||
|
Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime()))
|
||||||
|
} else {
|
||||||
|
self_.unexpected_any()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)?
|
||||||
|
.0)
|
||||||
|
}
|
||||||
|
|
||||||
/// Is a `dyn B0 + ... + Bn` type allowed here?
|
/// Is a `dyn B0 + ... + Bn` type allowed here?
|
||||||
fn is_explicit_dyn_type(&mut self) -> bool {
|
fn is_explicit_dyn_type(&mut self) -> bool {
|
||||||
self.check_keyword(kw::Dyn)
|
self.check_keyword(kw::Dyn)
|
||||||
|
@ -1047,10 +1047,20 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
|||||||
});
|
});
|
||||||
self.diag_metadata.current_function = previous_value;
|
self.diag_metadata.current_function = previous_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
|
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
|
||||||
self.resolve_lifetime(lifetime, use_ctxt)
|
self.resolve_lifetime(lifetime, use_ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
|
||||||
|
match arg {
|
||||||
|
PreciseCapturingArg::Lifetime(_) => visit::walk_precise_capturing_arg(self, arg),
|
||||||
|
PreciseCapturingArg::Arg(ident, _) => {
|
||||||
|
todo!("cannot resolve args yet: {ident}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_generics(&mut self, generics: &'ast Generics) {
|
fn visit_generics(&mut self, generics: &'ast Generics) {
|
||||||
self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some());
|
self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some());
|
||||||
for p in &generics.where_clause.predicates {
|
for p in &generics.where_clause.predicates {
|
||||||
|
Loading…
Reference in New Issue
Block a user