Use dedicated PreciseCapturingArg for representing what goes in use<>

This commit is contained in:
Michael Goulet 2024-04-03 21:47:02 -04:00
parent 647b672f16
commit fc9e344874
6 changed files with 146 additions and 56 deletions

View File

@ -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)`.

View File

@ -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,

View File

@ -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,

View File

@ -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,18 +1534,15 @@ 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 // We'll actually validate these later on; all we need is the list of
// lifetimes to duplicate during this portion of lowering. // lifetimes to duplicate during this portion of lowering.
precise_capturing precise_capturing
.args
.iter() .iter()
.filter_map(|arg| match arg { .filter_map(|arg| match arg {
ast::AngleBracketedArg::Arg(ast::GenericArg::Lifetime(lt)) => Some(*lt), ast::PreciseCapturingArg::Lifetime(lt) => Some(*lt),
_ => None, ast::PreciseCapturingArg::Arg(..) => None,
}) })
.collect() .collect()
} else { } else {

View File

@ -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)

View File

@ -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 {