diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index d310f72f7a3f8..139f62e5ef992 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,6 +1,7 @@ use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext}; use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; use rustc_hir as hir; +use rustc_data_structures::thin_slice::ThinSlice; use smallvec::SmallVec; @@ -27,7 +28,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_stmts( &mut self, mut ast_stmts: &[Stmt], - ) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>) { + ) -> (&'hir ThinSlice>, Option<&'hir hir::Expr<'hir>>) { let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new(); let mut expr = None; while let [s, tail @ ..] = ast_stmts { @@ -78,7 +79,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ast_stmts = &ast_stmts[1..]; } - (self.arena.alloc_from_iter(stmts), expr) + (self.arena.allocate_thin_from_iter(stmts), expr) } fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 181f94ab74f93..d745613f446cc 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -11,6 +11,7 @@ use rustc_ast::attr; use rustc_ast::ptr::P as AstP; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; @@ -25,6 +26,10 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x))) } + fn lower_exprs_thin(&mut self, exprs: &[AstP]) -> &'hir ThinSlice> { + self.arena.allocate_thin_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x))) + } + pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> { self.arena.alloc(self.lower_expr_mut(e)) } @@ -100,7 +105,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args) } else { let f = self.lower_expr(f); - hir::ExprKind::Call(f, self.lower_exprs(args)) + hir::ExprKind::Call(f, self.lower_exprs_thin(args)) } } ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => { @@ -112,8 +117,9 @@ impl<'hir> LoweringContext<'_, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Path), )); let receiver = self.lower_expr(receiver); - let args = - self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x))); + let args = self + .arena + .allocate_thin_from_iter(args.iter().map(|x| self.lower_expr_mut(x))); hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(*span)) } ExprKind::Binary(binop, lhs, rhs) => { @@ -135,12 +141,16 @@ impl<'hir> LoweringContext<'_, 'hir> { LitKind::Err } }; - hir::ExprKind::Lit(respan(self.lower_span(e.span), lit_kind)) + let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind)); + hir::ExprKind::Lit(lit) + } + ExprKind::IncludedBytes(bytes) => { + let lit = self.arena.alloc(respan( + self.lower_span(e.span), + LitKind::ByteStr(bytes.clone(), StrStyle::Cooked), + )); + hir::ExprKind::Lit(lit) } - ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan( - self.lower_span(e.span), - LitKind::ByteStr(bytes.clone(), StrStyle::Cooked), - )), ExprKind::Cast(expr, ty) => { let expr = self.lower_expr(expr); let ty = @@ -403,7 +413,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Now lower everything as normal. let f = self.lower_expr(&f); - hir::ExprKind::Call(f, self.lower_exprs(&real_args)) + hir::ExprKind::Call(f, self.lower_exprs_thin(&real_args)) } fn lower_expr_if( @@ -490,7 +500,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let then = self.lower_block_expr(body); let expr_break = self.expr_break(span); let stmt_break = self.stmt_expr(span, expr_break); - let else_blk = self.block_all(span, arena_vec![self; stmt_break], None); + let else_blk = self.block_all(span, arena_thin_vec![self; stmt_break], None); let else_expr = self.arena.alloc(self.expr_block(else_blk)); let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr)); let if_expr = self.expr(span, if_kind); @@ -550,7 +560,7 @@ impl<'hir> LoweringContext<'_, 'hir> { overall_span: Span, ) -> &'hir hir::Expr<'hir> { let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None)); - self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) + self.expr_call(overall_span, constructor, arena_thin_vec![self; *expr]) } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> { @@ -649,7 +659,7 @@ impl<'hir> LoweringContext<'_, 'hir> { def_id: self.local_def_id(closure_node_id), binder: hir::ClosureBinder::Default, capture_clause, - bound_generic_params: &[], + bound_generic_params: ThinSlice::empty(), fn_decl, body, fn_decl_span: self.lower_span(span), @@ -751,19 +761,19 @@ impl<'hir> LoweringContext<'_, 'hir> { let new_unchecked = self.expr_call_lang_item_fn_mut( span, hir::LangItem::PinNewUnchecked, - arena_vec![self; ref_mut_awaitee], + arena_thin_vec![self; ref_mut_awaitee], Some(expr_hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( gen_future_span, hir::LangItem::GetContext, - arena_vec![self; task_context], + arena_thin_vec![self; task_context], Some(expr_hir_id), ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, - arena_vec![self; new_unchecked, get_context], + arena_thin_vec![self; new_unchecked, get_context], Some(expr_hir_id), ); self.arena.alloc(self.expr_unsafe(call)) @@ -796,7 +806,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let pending_pat = self.pat_lang_item_variant( span, hir::LangItem::PollPending, - &[], + ThinSlice::empty(), Some(expr_hir_id), ); let empty_block = self.expr_block_empty(span); @@ -834,7 +844,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } }; - let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None); + let loop_block = + self.block_all(span, arena_thin_vec![self; inner_match_stmt, yield_stmt], None); // loop { .. } let loop_expr = self.arena.alloc(hir::Expr { @@ -860,7 +871,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let into_future_expr = self.expr_call_lang_item_fn( into_future_span, hir::LangItem::IntoFutureIntoFuture, - arena_vec![self; expr], + arena_thin_vec![self; expr], Some(expr_hir_id), ); @@ -1088,9 +1099,9 @@ impl<'hir> LoweringContext<'_, 'hir> { ); // `a = lhs1; b = lhs2;`. - let stmts = self - .arena - .alloc_from_iter(std::iter::once(destructure_let).chain(assignments.into_iter())); + let stmts = self.arena.allocate_thin_from_iter( + std::iter::once(destructure_let).chain(assignments.into_iter()), + ); // Wrap everything in a block. hir::ExprKind::Block(&self.block_all(whole_span, stmts, None), None) @@ -1163,7 +1174,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (pats, rest) = self.destructure_sequence(elements, "slice", eq_sign_span, assignments); let slice_pat = if let Some((i, span)) = rest { - let (before, after) = pats.split_at(i); + let (before, after): (&[hir::Pat<'_>], &[hir::Pat<'_>]) = pats.split_at(i); hir::PatKind::Slice( before, Some(self.arena.alloc(self.pat_without_dbm(span, hir::PatKind::Wild))), @@ -1216,7 +1227,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } // Structs. ExprKind::Struct(se) => { - let field_pats = self.arena.alloc_from_iter(se.fields.iter().map(|f| { + let field_pats = self.arena.allocate_thin_from_iter(se.fields.iter().map(|f| { let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments); hir::PatField { hir_id: self.next_id(), @@ -1256,7 +1267,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Paren(e) => { // We special-case `(..)` for consistency with patterns. if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { - let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0))); + let tuple_pat = + hir::PatKind::Tuple(ThinSlice::empty(), hir::DotDotPos::new(Some(0))); return self.pat_without_dbm(lhs.span, tuple_pat); } else { return self.destructure_assign_mut(e, eq_sign_span, assignments); @@ -1286,10 +1298,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ctx: &str, eq_sign_span: Span, assignments: &mut Vec>, - ) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>) { + ) -> (&'hir ThinSlice>, Option<(usize, Span)>) { let mut rest = None; let elements = - self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| { + self.arena.allocate_thin_from_iter(elements.iter().enumerate().filter_map(|(i, e)| { // Check for `..` pattern. if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { if let Some((_, prev_span)) = rest { @@ -1312,7 +1324,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path))); - hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) + hir::ExprKind::Call(fn_expr, arena_thin_vec![self; e1, e2]) } fn lower_expr_range( @@ -1508,7 +1520,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let next_expr = self.expr_call_lang_item_fn( head_span, hir::LangItem::IteratorNext, - arena_vec![self; ref_mut_iter], + arena_thin_vec![self; ref_mut_iter], None, ); let arms = arena_vec![self; none_arm, some_arm]; @@ -1517,7 +1529,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let match_stmt = self.stmt_expr(for_span, match_expr); - let loop_block = self.block_all(for_span, arena_vec![self; match_stmt], None); + let loop_block = self.block_all(for_span, arena_thin_vec![self; match_stmt], None); // `[opt_ident]: loop { ... }` let kind = hir::ExprKind::Loop( @@ -1537,7 +1549,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr_call_lang_item_fn( head_span, hir::LangItem::IntoIterIntoIter, - arena_vec![self; head], + arena_thin_vec![self; head], None, ) }; @@ -1593,7 +1605,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr_call_lang_item_fn( unstable_span, hir::LangItem::TryTraitBranch, - arena_vec![self; sub_expr], + arena_thin_vec![self; sub_expr], None, ) }; @@ -1749,47 +1761,38 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> { - self.expr( - sp, - hir::ExprKind::Lit(hir::Lit { - span: sp, - node: ast::LitKind::Int( - value as u128, - ast::LitIntType::Unsigned(ast::UintTy::Usize), - ), - }), - ) + let lit = self.arena.alloc(hir::Lit { + span: sp, + node: ast::LitKind::Int(value as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)), + }); + self.expr(sp, hir::ExprKind::Lit(lit)) } pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> { - self.expr( - sp, - hir::ExprKind::Lit(hir::Lit { - span: sp, - node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)), - }), - ) + let lit = self.arena.alloc(hir::Lit { + span: sp, + node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)), + }); + self.expr(sp, hir::ExprKind::Lit(lit)) } pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> { - self.expr(sp, hir::ExprKind::Lit(hir::Lit { span: sp, node: ast::LitKind::Char(value) })) + let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) }); + self.expr(sp, hir::ExprKind::Lit(lit)) } pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> { - self.expr( - sp, - hir::ExprKind::Lit(hir::Lit { - span: sp, - node: ast::LitKind::Str(value, ast::StrStyle::Cooked), - }), - ) + let lit = self + .arena + .alloc(hir::Lit { span: sp, node: ast::LitKind::Str(value, ast::StrStyle::Cooked) }); + self.expr(sp, hir::ExprKind::Lit(lit)) } pub(super) fn expr_call_mut( &mut self, span: Span, e: &'hir hir::Expr<'hir>, - args: &'hir [hir::Expr<'hir>], + args: &'hir ThinSlice>, ) -> hir::Expr<'hir> { self.expr(span, hir::ExprKind::Call(e, args)) } @@ -1798,7 +1801,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, span: Span, e: &'hir hir::Expr<'hir>, - args: &'hir [hir::Expr<'hir>], + args: &'hir ThinSlice>, ) -> &'hir hir::Expr<'hir> { self.arena.alloc(self.expr_call_mut(span, e, args)) } @@ -1807,7 +1810,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, span: Span, lang_item: hir::LangItem, - args: &'hir [hir::Expr<'hir>], + args: &'hir ThinSlice>, hir_id: Option, ) -> hir::Expr<'hir> { let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id)); @@ -1818,7 +1821,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, span: Span, lang_item: hir::LangItem, - args: &'hir [hir::Expr<'hir>], + args: &'hir ThinSlice>, hir_id: Option, ) -> &'hir hir::Expr<'hir> { self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id)) @@ -1879,7 +1882,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.arena.alloc(hir::Path { span: self.lower_span(span), res, - segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)], + segments: arena_thin_vec![self; hir::PathSegment::new(ident, hir_id, res)], }), )); @@ -1893,7 +1896,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span, hir::ExprKind::Block( self.arena.alloc(hir::Block { - stmts: &[], + stmts: ThinSlice::empty(), expr: Some(expr), hir_id, rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated), @@ -1906,7 +1909,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> { - let blk = self.block_all(span, &[], None); + let blk = self.block_all(span, ThinSlice::empty(), None); let expr = self.expr_block(blk); self.arena.alloc(expr) } diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 72352b138cbf4..71cba04fe6802 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -3,6 +3,7 @@ use rustc_ast as ast; use rustc_ast::visit::{self, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_hir as hir; use rustc_span::{ sym, @@ -212,7 +213,7 @@ fn make_argument<'hir>( Usize => sym::from_usize, }, )); - ctx.expr_call_mut(sp, new_fn, std::slice::from_ref(arg)) + ctx.expr_call_mut(sp, new_fn, arena_thin_vec![ctx; *arg]) } /// Generate a hir expression for a format_args Count. @@ -247,7 +248,7 @@ fn make_count<'hir>( hir::LangItem::FormatCount, sym::Is, )); - let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, *n)]); + let value = ctx.arena.allocate_thin_from_iter([ctx.expr_usize(sp, *n)]); ctx.expr_call_mut(sp, count_is, value) } Some(FormatCount::Argument(arg)) => { @@ -258,7 +259,7 @@ fn make_count<'hir>( hir::LangItem::FormatCount, sym::Param, )); - let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, i)]); + let value = ctx.arena.allocate_thin_from_iter([ctx.expr_usize(sp, i)]); ctx.expr_call_mut(sp, count_param, value) } else { ctx.expr( @@ -340,7 +341,7 @@ fn make_format_spec<'hir>( hir::LangItem::FormatPlaceholder, sym::new, )); - let args = ctx.arena.alloc_from_iter([position, fill, align, flags, precision, width]); + let args = ctx.arena.allocate_thin_from_iter([position, fill, align, flags, precision, width]); ctx.expr_call_mut(sp, format_placeholder_new, args) } @@ -426,7 +427,7 @@ fn expand_format_args<'hir>( hir::LangItem::FormatArguments, sym::new_const, )); - let new_args = ctx.arena.alloc_from_iter([lit_pieces]); + let new_args = ctx.arena.allocate_thin_from_iter([lit_pieces]); return hir::ExprKind::Call(new, new_args); } @@ -530,17 +531,17 @@ fn expand_format_args<'hir>( hir::LangItem::FormatUnsafeArg, sym::new, )); - let unsafe_arg_new_call = ctx.expr_call(macsp, unsafe_arg_new, &[]); + let unsafe_arg_new_call = ctx.expr_call(macsp, unsafe_arg_new, ThinSlice::empty()); let hir_id = ctx.next_id(); let unsafe_arg = ctx.expr_block(ctx.arena.alloc(hir::Block { - stmts: &[], + stmts: ThinSlice::empty(), expr: Some(unsafe_arg_new_call), hir_id, rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated), span: macsp, targeted_by_break: false, })); - let args = ctx.arena.alloc_from_iter([lit_pieces, args, format_options, unsafe_arg]); + let args = ctx.arena.allocate_thin_from_iter([lit_pieces, args, format_options, unsafe_arg]); hir::ExprKind::Call(new_v1_formatted, args) } else { // Generate: @@ -553,7 +554,7 @@ fn expand_format_args<'hir>( hir::LangItem::FormatArguments, sym::new_v1, )); - let new_args = ctx.arena.alloc_from_iter([lit_pieces, args]); + let new_args = ctx.arena.allocate_thin_from_iter([lit_pieces, args]); hir::ExprKind::Call(new_v1, new_args) } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9a117ac9a3cf7..dbe3fdc20dd12 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -7,6 +7,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; use rustc_data_structures::sorted_map::SortedMap; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -1172,7 +1173,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // ``` let body = this.block_all( desugared_span, - this.arena.alloc_from_iter(statements), + this.arena.allocate_thin_from_iter(statements), Some(user_body), ); @@ -1366,8 +1367,8 @@ impl<'hir> LoweringContext<'_, 'hir> { predicates.extend(impl_trait_bounds.into_iter()); let lowered_generics = self.arena.alloc(hir::Generics { - params: self.arena.alloc_from_iter(params), - predicates: self.arena.alloc_from_iter(predicates), + params: self.arena.allocate_thin_from_iter(params), + predicates: self.arena.allocate_thin_from_iter(predicates), has_where_clause_predicates, where_clause_span, span, @@ -1418,7 +1419,7 @@ impl<'hir> LoweringContext<'_, 'hir> { res, segments: self .arena - .alloc_from_iter([hir::PathSegment::new(ident, hir_id, res)]), + .allocate_thin_from_iter([hir::PathSegment::new(ident, hir_id, res)]), }); let ty_id = self.next_id(); let bounded_ty = @@ -1428,7 +1429,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounded_ty: self.arena.alloc(bounded_ty), bounds, span, - bound_generic_params: &[], + bound_generic_params: ThinSlice::empty(), origin, })) } @@ -1459,7 +1460,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), bounded_ty: self .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), - bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { + bounds: self.arena.allocate_thin_from_iter(bounds.iter().map(|bound| { self.lower_param_bound( bound, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0b6b02ba00fb5..b6a1668cf7c69 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -74,6 +74,7 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::SmallVec; use std::collections::hash_map::Entry; use thin_vec::ThinVec; +use rustc_data_structures::thin_slice::ThinSlice; macro_rules! arena_vec { ($this:expr; $($x:expr),*) => ( @@ -81,6 +82,12 @@ macro_rules! arena_vec { ); } +macro_rules! arena_thin_vec { + ($this:expr; $($x:expr),*) => ( + $this.arena.allocate_thin_from_iter([$($x),*]) + ); +} + mod asm; mod block; mod errors; @@ -848,7 +855,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, binder: NodeId, generic_params: &[GenericParam], - ) -> &'hir [hir::GenericParam<'hir>] { + ) -> &'hir ThinSlice> { let mut generic_params: Vec<_> = self .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder) .collect(); @@ -857,7 +864,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| { self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder) })); - let generic_params = self.arena.alloc_from_iter(generic_params); + let generic_params = self.arena.allocate_thin_from_iter(generic_params); debug!(?generic_params); generic_params @@ -1304,7 +1311,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None, self.arena.alloc(hir::Path { res, - segments: arena_vec![self; hir::PathSegment::new( + segments: arena_thin_vec![self; hir::PathSegment::new( Ident::with_dummy_span(kw::SelfUpper), hir_id, res @@ -1511,7 +1518,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // This creates HIR lifetime definitions as `hir::GenericParam`, in the given // example `type TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection // containing `&['x]`. - let lifetime_defs = lctx.arena.alloc_from_iter(collected_lifetimes.iter().map( + let lifetime_defs = lctx.arena.allocate_thin_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime)| { let hir_id = lctx.lower_node_id(new_node_id); debug_assert_ne!(lctx.opt_local_def_id(new_node_id), None); @@ -1547,7 +1554,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_item = hir::OpaqueTy { generics: self.arena.alloc(hir::Generics { params: lifetime_defs, - predicates: &[], + predicates: ThinSlice::empty(), has_where_clause_predicates: false, where_clause_span: lctx.lower_span(span), span: lctx.lower_span(span), @@ -1969,7 +1976,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }, ); - let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map( + let generic_params = this.arena.allocate_thin_from_iter(collected_lifetimes.iter().map( |&(new_node_id, lifetime, _)| { let hir_id = this.lower_node_id(new_node_id); debug_assert_ne!(this.opt_local_def_id(new_node_id), None); @@ -2000,12 +2007,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_item = hir::OpaqueTy { generics: this.arena.alloc(hir::Generics { params: generic_params, - predicates: &[], + predicates: ThinSlice::empty(), has_where_clause_predicates: false, where_clause_span: this.lower_span(span), span: this.lower_span(span), }), - bounds: arena_vec![this; future_bound], + bounds: arena_thin_vec![this; future_bound], origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), in_trait, }; @@ -2073,8 +2080,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // "" let future_args = self.arena.alloc(hir::GenericArgs { - args: &[], - bindings: arena_vec![self; self.output_ty_binding(span, output_ty)], + args: ThinSlice::empty(), + bindings: arena_thin_vec![self; self.output_ty_binding(span, output_ty)], parenthesized: false, span_ext: DUMMY_SP, }); @@ -2166,8 +2173,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, params: &[GenericParam], source: hir::GenericParamSource, - ) -> &'hir [hir::GenericParam<'hir>] { - self.arena.alloc_from_iter(self.lower_generic_params_mut(params, source)) + ) -> &'hir ThinSlice> { + self.arena.allocate_thin_from_iter(self.lower_generic_params_mut(params, source)) } #[instrument(level = "trace", skip(self))] @@ -2269,7 +2276,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds: &[GenericBound], itctx: &ImplTraitContext, ) -> hir::GenericBounds<'hir> { - self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) + self.arena.allocate_thin_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } fn lower_param_bounds_mut<'s>( @@ -2323,7 +2330,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span, res, segments: - arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], + arena_thin_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], }), )); @@ -2421,13 +2428,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> &'hir hir::Block<'hir> { - self.block_all(expr.span, &[], Some(expr)) + self.block_all(expr.span, ThinSlice::empty(), Some(expr)) } fn block_all( &mut self, span: Span, - stmts: &'hir [hir::Stmt<'hir>], + stmts: &'hir ThinSlice>, expr: Option<&'hir hir::Expr<'hir>>, ) -> &'hir hir::Block<'hir> { let blk = hir::Block { @@ -2457,14 +2464,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> { - self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None) + self.pat_lang_item_variant(span, hir::LangItem::OptionNone, ThinSlice::empty(), None) } fn single_pat_field( &mut self, span: Span, pat: &'hir hir::Pat<'hir>, - ) -> &'hir [hir::PatField<'hir>] { + ) -> &'hir ThinSlice> { let field = hir::PatField { hir_id: self.next_id(), ident: Ident::new(sym::integer(0), self.lower_span(span)), @@ -2472,14 +2479,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { pat, span: self.lower_span(span), }; - arena_vec![self; field] + arena_thin_vec![self; field] } fn pat_lang_item_variant( &mut self, span: Span, lang_item: hir::LangItem, - fields: &'hir [hir::PatField<'hir>], + fields: &'hir ThinSlice>, hir_id: Option, ) -> &'hir hir::Pat<'hir> { let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id); @@ -2594,7 +2601,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// Helper struct for delayed construction of GenericArgs. struct GenericArgsCtor<'hir> { args: SmallVec<[hir::GenericArg<'hir>; 4]>, - bindings: &'hir [hir::TypeBinding<'hir>], + bindings: &'hir ThinSlice>, parenthesized: bool, span: Span, } @@ -2606,7 +2613,7 @@ impl<'hir> GenericArgsCtor<'hir> { fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> { let ga = hir::GenericArgs { - args: this.arena.alloc_from_iter(self.args), + args: this.arena.allocate_thin_from_iter(self.args), bindings: self.bindings, parenthesized: self.parenthesized, span_ext: this.lower_span(self.span), diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 2509b70563956..960f2b58fcfe3 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -12,6 +12,7 @@ use rustc_hir as hir; use rustc_hir::def::Res; use rustc_span::symbol::Ident; use rustc_span::{source_map::Spanned, Span}; +use rustc_data_structures::thin_slice::ThinSlice; impl<'a, 'hir> LoweringContext<'a, 'hir> { pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> { @@ -44,7 +45,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } PatKind::Or(pats) => { break hir::PatKind::Or( - self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat_mut(x))), + self.arena.allocate_thin_from_iter(pats.iter().map(|x| self.lower_pat_mut(x))), ); } PatKind::Path(qself, path) => { @@ -66,7 +67,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Path), ); - let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { + let fs = self.arena.allocate_thin_from_iter(fields.iter().map(|f| { let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -116,7 +117,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, pats: &[P], ctx: &str, - ) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) { + ) -> (&'hir ThinSlice>, hir::DotDotPos) { let mut elems = Vec::with_capacity(pats.len()); let mut rest = None; @@ -160,7 +161,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - (self.arena.alloc_from_iter(elems), hir::DotDotPos::new(rest.map(|(ddpos, _)| ddpos))) + (self.arena.allocate_thin_from_iter(elems), hir::DotDotPos::new(rest.map(|(ddpos, _)| ddpos))) } /// Lower a slice pattern of form `[pat_0, ..., pat_n]` into @@ -226,9 +227,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } hir::PatKind::Slice( - self.arena.alloc_from_iter(before), + self.arena.allocate_thin_from_iter(before), slice, - self.arena.alloc_from_iter(after), + self.arena.allocate_thin_from_iter(after), ) } @@ -262,7 +263,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(hir::Path { span: self.lower_span(ident.span), res, - segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], + segments: arena_thin_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], }), )) } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 592fc5aa6456f..0b192235bca0e 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -11,6 +11,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::GenericArg; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span, DUMMY_SP}; +use rustc_data_structures::thin_slice::ThinSlice; use smallvec::{smallvec, SmallVec}; @@ -36,7 +37,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let proj_start = p.segments.len() - unresolved_segments; let path = self.arena.alloc(hir::Path { res: self.lower_res(base_res), - segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map( + segments: self.arena.allocate_thin_from_iter(p.segments[..proj_start].iter().enumerate().map( |(i, segment)| { let param_mode = match (qself_position, param_mode) { (Some(j), ParamMode::Optional) if i < j => { @@ -152,7 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> &'hir hir::UsePath<'hir> { self.arena.alloc(hir::UsePath { res, - segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { + segments: self.arena.allocate_thin_from_iter(p.segments.iter().map(|segment| { self.lower_path_segment( p.span, segment, @@ -223,7 +224,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ( GenericArgsCtor { args: Default::default(), - bindings: &[], + bindings: ThinSlice::empty(), parenthesized: false, span: path_span.shrink_to_hi(), }, @@ -324,7 +325,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { AngleBracketedArg::Constraint(_) => None, }) .collect(); - let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg { + let bindings = self.arena.allocate_thin_from_iter(data.args.iter().filter_map(|arg| match arg { AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)), AngleBracketedArg::Arg(_) => None, })); @@ -375,7 +376,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ( GenericArgsCtor { args, - bindings: arena_vec![self; binding], + bindings: arena_thin_vec![self; binding], parenthesized: true, span: data.inputs_span, }, @@ -391,8 +392,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::TypeBinding<'hir> { let ident = Ident::with_dummy_span(hir::FN_OUTPUT_NAME); let kind = hir::TypeBindingKind::Equality { term: ty.into() }; - let args = arena_vec![self;]; - let bindings = arena_vec![self;]; + let args = arena_thin_vec![self;]; + let bindings = arena_thin_vec![self;]; let gen_args = self.arena.alloc(hir::GenericArgs { args, bindings, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 75a3dd0c0f3d6..a17064244f328 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2,6 +2,7 @@ use either::Either; use rustc_const_eval::util::CallKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, }; @@ -405,7 +406,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { (def_id.as_local(), args, 0) } else { - (None, &[][..], 0) + (None, ThinSlice::empty(), 0) }; if let Some(def_id) = def_id && let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id)) @@ -1278,8 +1279,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } if let hir::Expr { kind: hir::ExprKind::Path(path), .. } = e { - if let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path && - seg.ident.name == kw::SelfLower && self.in_closure { + if let hir::QPath::Resolved(_, hir::Path { segments, ..}) = path + && let [seg] = segments.as_slice() + && seg.ident.name == kw::SelfLower && self.in_closure + { self.closure_change_spans.push(e.span); } } @@ -1304,7 +1307,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn visit_stmt(&mut self, s: &'hir hir::Stmt<'hir>) { if let hir::StmtKind::Semi(e) = s.kind && let hir::ExprKind::Call(hir::Expr { kind: hir::ExprKind::Path(path), ..}, args) = e.kind && - let hir::QPath::Resolved(_, hir::Path { segments: [seg], ..}) = path && + let hir::QPath::Resolved(_, hir::Path { segments, ..}) = path && + let [seg] = segments.as_slice() && let Res::Local(hir_id) = seg.res && Some(hir_id) == self.closure_local_id { let (span, arg_str) = if args.len() > 0 { diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 62b3f3ecfc32f..c319a654addc2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -84,7 +84,7 @@ impl<'tcx> BorrowExplanation<'tcx> { expr = inner; } if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind - && let [hir::PathSegment { ident, args: None, .. }] = p.segments + && let [hir::PathSegment { ident, args: None, .. }] = p.segments.as_slice() && let hir::def::Res::Local(hir_id) = p.res && let Some(hir::Node::Pat(pat)) = tcx.hir().find(hir_id) { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index a8c216407f931..5970df3e3960d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -977,15 +977,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { kind: Call( _, - [ - Expr { - kind: - MethodCall(path_segment, _, _, span), - hir_id, - .. - }, - .., - ], + args, ), .. }, @@ -999,6 +991,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }, _, ) = hir_map.body(fn_body_id).value.kind + && let [ + Expr { + kind: + MethodCall(path_segment, _, _, span), + hir_id, + .. + }, + .., + ] = args.as_slice() { let opt_suggestions = self .infcx diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index cc5a1f5ab122d..7d72a23f3ee78 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -758,29 +758,26 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ); }; let opaque_ty = hir.item(id); - if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { - bounds: - [ - hir::GenericBound::LangItemTrait( - hir::LangItem::Future, - _, - _, - hir::GenericArgs { - bindings: - [ - hir::TypeBinding { - ident: Ident { name: sym::Output, .. }, - kind: - hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) }, - .. - }, - ], - .. - }, - ), - ], - .. - }) = opaque_ty.kind + if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) = opaque_ty.kind + && let [ + hir::GenericBound::LangItemTrait( + hir::LangItem::Future, + _, + _, + hir::GenericArgs { + bindings, + .. + }, + ), + ] = bounds.as_slice() + && let [ + hir::TypeBinding { + ident: Ident { name: sym::Output, .. }, + kind: + hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) }, + .. + }, + ] = bindings.as_slice() { ty } else { diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 0339fb925d458..865bc340b6d2c 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -22,6 +22,7 @@ #![feature(new_uninit)] #![feature(once_cell)] #![feature(rustc_attrs)] +#![feature(extern_types)] #![feature(negative_impls)] #![feature(test)] #![feature(thread_id_value)] @@ -65,6 +66,7 @@ pub mod small_c_str; pub mod small_str; pub mod snapshot_map; pub mod svh; +pub mod thin_slice; pub use ena::snapshot_vec; pub mod memmap; pub mod sorted_map; diff --git a/compiler/rustc_data_structures/src/thin_slice.rs b/compiler/rustc_data_structures/src/thin_slice.rs new file mode 100644 index 0000000000000..c092eb9380e05 --- /dev/null +++ b/compiler/rustc_data_structures/src/thin_slice.rs @@ -0,0 +1,178 @@ +use rustc_serialize::{Encodable, Encoder}; +use std::cmp::Ordering; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::mem; +use std::ops::Deref; +use std::ptr; +use std::slice; + +/// A thin length-prefixed slice. Pointers to this slice are just +/// one ptr-size wide. +#[repr(C)] +pub struct ThinSlice { + len: usize, + + /// Although this claims to be a zero-length array, in practice `len` + /// elements are actually present. + data: [T; 0], + + opaque: OpaqueSliceContents, +} + +extern "C" { + /// A dummy type used to force `List` to be unsized while not requiring + /// references to it be wide pointers. + type OpaqueSliceContents; +} + +impl ThinSlice { + /// Returns a reference to the (unique, static) empty list. + #[inline(always)] + pub fn empty<'a>() -> &'a Self { + #[repr(align(64))] + struct MaxAlign; + + assert!(mem::align_of::() <= mem::align_of::()); + + #[repr(C)] + struct InOrder(T, U); + + // The empty slice is static and contains a single `0` usize (for the + // length) that is 64-byte aligned, thus featuring the necessary + // trailing padding for elements with up to 64-byte alignment. + static EMPTY_SLICE: InOrder = InOrder(0, MaxAlign); + unsafe { &*(&EMPTY_SLICE as *const _ as *const Self) } + } + + /// Returns a reference an empty list. Is not guaranteed to be the same for all empty slices. + #[inline(always)] + pub const fn const_empty<'a>() -> &'a Self { + #[repr(align(64))] + struct MaxAlign; + + assert!(mem::align_of::() <= mem::align_of::()); + + #[repr(C)] + struct InOrder(T, U); + + // The empty slice is static and contains a single `0` usize (for the + // length) that is 64-byte aligned, thus featuring the necessary + // trailing padding for elements with up to 64-byte alignment. + const EMPTY_SLICE: InOrder = InOrder(0, MaxAlign); + unsafe { &*(&EMPTY_SLICE as *const _ as *const Self) } + } + + pub fn len(&self) -> usize { + self.len + } + + pub fn as_slice(&self) -> &[T] { + self + } + + /// Initializes the thin slice from the slice into the memory location specified in `mem`. + /// + /// # Safety + /// `mem` must be valid for writes of the length of a usize + padding + the slice. + /// The caller must ensure that the memory remains valid of the duration of the lifetime. + pub unsafe fn initialize<'a>(mem: *mut Self, slice: &[T]) -> &'a Self { + // Write the length + ptr::addr_of_mut!((*mem).len).write(slice.len()); + + // Write the elements + ptr::addr_of_mut!((*mem).data) + .cast::() + .copy_from_nonoverlapping(slice.as_ptr(), slice.len()); + + &*mem + } + + // If this method didn't exist, we would use `slice.iter` due to + // deref coercion. + // + // This would be weird, as `self.into_iter` iterates over `T` directly. + #[inline(always)] + pub fn iter(&self) -> <&'_ Self as IntoIterator>::IntoIter { + self.into_iter() + } +} + +impl Default for &ThinSlice { + fn default() -> Self { + ThinSlice::empty() + } +} + +impl> Encodable for ThinSlice { + #[inline] + fn encode(&self, s: &mut S) { + (**self).encode(s); + } +} + +impl PartialEq for ThinSlice { + #[inline] + fn eq(&self, other: &ThinSlice) -> bool { + &*self == &*other + } +} + +impl Eq for ThinSlice {} + +impl Ord for ThinSlice +where + T: Ord, +{ + fn cmp(&self, other: &ThinSlice) -> Ordering { + self.as_slice().cmp(other.as_slice()) + } +} + +impl PartialOrd for ThinSlice +where + T: PartialOrd, +{ + fn partial_cmp(&self, other: &ThinSlice) -> Option { + self.as_slice().partial_cmp(other.as_slice()) + } +} + +impl Hash for ThinSlice { + #[inline] + fn hash(&self, s: &mut H) { + self.as_slice().hash(s) + } +} + +impl Deref for ThinSlice { + type Target = [T]; + #[inline(always)] + fn deref(&self) -> &[T] { + self.as_ref() + } +} + +impl AsRef<[T]> for ThinSlice { + #[inline(always)] + fn as_ref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } + } +} + +impl<'a, T> IntoIterator for &'a ThinSlice { + type Item = &'a T; + type IntoIter = <&'a [T] as IntoIterator>::IntoIter; + #[inline(always)] + fn into_iter(self) -> Self::IntoIter { + self[..].iter() + } +} + +unsafe impl Sync for ThinSlice {} + +impl fmt::Debug for ThinSlice { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index c89e7eb75f8f0..c35bb3ee1ea30 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -1,56 +1,17 @@ /// This higher-order macro declares a list of types which can be allocated by `Arena`. -/// -/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]`, -/// where `T` is the type listed. These impls will appear in the implement_ty_decoder! macro. +/// Note that all `Copy` types can be allocated by default and need not be specified here. #[macro_export] macro_rules! arena_types { ($macro:path) => ( $macro!([ // HIR types [] hir_krate: rustc_hir::Crate<'tcx>, - [] arm: rustc_hir::Arm<'tcx>, - [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, rustc_span::Span), [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, - [] closure: rustc_hir::Closure<'tcx>, - [] block: rustc_hir::Block<'tcx>, - [] bare_fn_ty: rustc_hir::BareFnTy<'tcx>, - [] body: rustc_hir::Body<'tcx>, - [] generics: rustc_hir::Generics<'tcx>, - [] generic_arg: rustc_hir::GenericArg<'tcx>, - [] generic_args: rustc_hir::GenericArgs<'tcx>, - [] generic_bound: rustc_hir::GenericBound<'tcx>, - [] generic_param: rustc_hir::GenericParam<'tcx>, - [] expr: rustc_hir::Expr<'tcx>, - [] impl_: rustc_hir::Impl<'tcx>, - [] let_expr: rustc_hir::Let<'tcx>, - [] expr_field: rustc_hir::ExprField<'tcx>, - [] pat_field: rustc_hir::PatField<'tcx>, - [] fn_decl: rustc_hir::FnDecl<'tcx>, - [] foreign_item: rustc_hir::ForeignItem<'tcx>, - [] foreign_item_ref: rustc_hir::ForeignItemRef, - [] impl_item: rustc_hir::ImplItem<'tcx>, - [] impl_item_ref: rustc_hir::ImplItemRef, [] item: rustc_hir::Item<'tcx>, - [] inline_asm: rustc_hir::InlineAsm<'tcx>, - [] local: rustc_hir::Local<'tcx>, - [] mod_: rustc_hir::Mod<'tcx>, [] owner_info: rustc_hir::OwnerInfo<'tcx>, - [] param: rustc_hir::Param<'tcx>, - [] pat: rustc_hir::Pat<'tcx>, - [] path: rustc_hir::Path<'tcx>, [] use_path: rustc_hir::UsePath<'tcx>, - [] path_segment: rustc_hir::PathSegment<'tcx>, - [] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>, - [] qpath: rustc_hir::QPath<'tcx>, - [] stmt: rustc_hir::Stmt<'tcx>, - [] field_def: rustc_hir::FieldDef<'tcx>, - [] trait_item: rustc_hir::TraitItem<'tcx>, - [] trait_item_ref: rustc_hir::TraitItemRef, - [] ty: rustc_hir::Ty<'tcx>, - [] type_binding: rustc_hir::TypeBinding<'tcx>, - [] variant: rustc_hir::Variant<'tcx>, - [] where_predicate: rustc_hir::WherePredicate<'tcx>, + [] lint: rustc_hir::Lit, ]); ) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f4b46b9a131fb..1acf26d046929 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -13,6 +13,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_error_messages::MultiSpan; use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; @@ -182,13 +183,13 @@ impl Lifetime { /// A `Path` is essentially Rust's notion of a name; for instance, /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Path<'hir, R = Res> { pub span: Span, /// The resolution for the path. pub res: R, /// The segments in the path: the things separated by `::`. - pub segments: &'hir [PathSegment<'hir>], + pub segments: &'hir ThinSlice>, } /// Up to three resolutions for type, value and macro namespaces. @@ -202,7 +203,7 @@ impl Path<'_> { /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct PathSegment<'hir> { /// The identifier portion of this path segment. pub ident: Ident, @@ -243,13 +244,13 @@ impl<'hir> PathSegment<'hir> { } } -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Encodable, Clone, Copy, Debug, HashStable_Generic)] pub struct ConstArg { pub value: AnonConst, pub span: Span, } -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Encodable, Clone, Copy, Debug, HashStable_Generic)] pub struct InferArg { pub hir_id: HirId, pub span: Span, @@ -261,7 +262,7 @@ impl InferArg { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), Type(&'hir Ty<'hir>), @@ -318,13 +319,13 @@ impl GenericArg<'_> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct GenericArgs<'hir> { /// The generic arguments for this path segment. - pub args: &'hir [GenericArg<'hir>], + pub args: &'hir ThinSlice>, /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo`. - pub bindings: &'hir [TypeBinding<'hir>], + pub bindings: &'hir ThinSlice>, /// Were arguments written in parenthesized form `Fn(T) -> U`? /// This is required mostly for pretty-printing and diagnostics, /// but also for changing lifetime elision rules to be "function-like". @@ -340,7 +341,7 @@ pub struct GenericArgs<'hir> { impl<'hir> GenericArgs<'hir> { pub const fn none() -> Self { - Self { args: &[], bindings: &[], parenthesized: false, span_ext: DUMMY_SP } + Self { args: ThinSlice::const_empty(), bindings: ThinSlice::const_empty(), parenthesized: false, span_ext: DUMMY_SP } } pub fn inputs(&self) -> &[Ty<'hir>] { @@ -431,7 +432,7 @@ pub enum TraitBoundModifier { /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. -#[derive(Clone, Debug, HashStable_Generic)] +#[derive(Clone, Copy, Debug, HashStable_Generic)] pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` @@ -456,7 +457,7 @@ impl GenericBound<'_> { } } -pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>]; +pub type GenericBounds<'hir> = &'hir ThinSlice>; #[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] pub enum LifetimeParamKind { @@ -472,7 +473,7 @@ pub enum LifetimeParamKind { Error, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum GenericParamKind<'hir> { /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime { @@ -489,7 +490,7 @@ pub enum GenericParamKind<'hir> { }, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct GenericParam<'hir> { pub hir_id: HirId, pub def_id: LocalDefId, @@ -541,10 +542,10 @@ pub struct GenericParamCount { /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Generics<'hir> { - pub params: &'hir [GenericParam<'hir>], - pub predicates: &'hir [WherePredicate<'hir>], + pub params: &'hir ThinSlice>, + pub predicates: &'hir ThinSlice>, pub has_where_clause_predicates: bool, pub where_clause_span: Span, pub span: Span, @@ -553,8 +554,8 @@ pub struct Generics<'hir> { impl<'hir> Generics<'hir> { pub const fn empty() -> &'hir Generics<'hir> { const NOPE: Generics<'_> = Generics { - params: &[], - predicates: &[], + params: ThinSlice::const_empty(), + predicates: ThinSlice::const_empty(), has_where_clause_predicates: false, where_clause_span: DUMMY_SP, span: DUMMY_SP, @@ -713,7 +714,7 @@ impl<'hir> Generics<'hir> { } /// A single predicate in a where-clause. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum WherePredicate<'hir> { /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate<'hir>), @@ -744,7 +745,7 @@ impl<'hir> WherePredicate<'hir> { match self { WherePredicate::BoundPredicate(p) => p.bounds, WherePredicate::RegionPredicate(p) => p.bounds, - WherePredicate::EqPredicate(_) => &[], + WherePredicate::EqPredicate(_) => ThinSlice::empty(), } } } @@ -757,14 +758,14 @@ pub enum PredicateOrigin { } /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct WhereBoundPredicate<'hir> { pub hir_id: HirId, pub span: Span, /// Origin of the predicate. pub origin: PredicateOrigin, /// Any generics from a `for` binding. - pub bound_generic_params: &'hir [GenericParam<'hir>], + pub bound_generic_params: &'hir ThinSlice>, /// The type being bounded. pub bounded_ty: &'hir Ty<'hir>, /// Trait and lifetime bounds (e.g., `Clone + Send + 'static`). @@ -779,7 +780,7 @@ impl<'hir> WhereBoundPredicate<'hir> { } /// A lifetime predicate (e.g., `'a: 'b + 'c`). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct WhereRegionPredicate<'hir> { pub span: Span, pub in_where_clause: bool, @@ -795,7 +796,7 @@ impl<'hir> WhereRegionPredicate<'hir> { } /// An equality predicate (e.g., `T = int`); currently unsupported. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct WhereEqPredicate<'hir> { pub span: Span, pub lhs_ty: &'hir Ty<'hir>, @@ -805,7 +806,7 @@ pub struct WhereEqPredicate<'hir> { /// HIR node coupled with its parent's id in the same HIR owner. /// /// The parent is trash when the node is a HIR owner. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct ParentedNode<'tcx> { pub parent: ItemLocalId, pub node: Node<'tcx>, @@ -943,13 +944,13 @@ pub struct Crate<'hir> { pub opt_hir_hash: Option, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Closure<'hir> { pub def_id: LocalDefId, pub binder: ClosureBinder, pub constness: Constness, pub capture_clause: CaptureBy, - pub bound_generic_params: &'hir [GenericParam<'hir>], + pub bound_generic_params: &'hir ThinSlice>, pub fn_decl: &'hir FnDecl<'hir>, pub body: BodyId, /// The span of the declaration block: 'move |...| -> ...' @@ -962,7 +963,7 @@ pub struct Closure<'hir> { /// A block of statements `{ .. }`, which may have a label (in this case the /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of /// the `rules` being anything but `DefaultBlock`. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Block<'hir> { /// Statements in a block. pub stmts: &'hir [Stmt<'hir>], @@ -990,7 +991,7 @@ impl<'hir> Block<'hir> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Pat<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1069,7 +1070,7 @@ impl<'hir> Pat<'hir> { /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` /// are treated the same as` x: x, y: ref y, z: ref mut z`, /// except `is_shorthand` is true. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct PatField<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1125,7 +1126,7 @@ impl fmt::Debug for DotDotPos { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum PatKind<'hir> { /// Represents a wildcard pattern (i.e., `_`). Wild, @@ -1138,16 +1139,16 @@ pub enum PatKind<'hir> { /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). /// The `bool` is `true` in the presence of a `..`. - Struct(QPath<'hir>, &'hir [PatField<'hir>], bool), + Struct(QPath<'hir>, &'hir ThinSlice>, bool), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `DotDotPos` denotes its position. /// `0 <= position <= subpats.len()` - TupleStruct(QPath<'hir>, &'hir [Pat<'hir>], DotDotPos), + TupleStruct(QPath<'hir>, &'hir ThinSlice>, DotDotPos), /// An or-pattern `A | B | C`. /// Invariant: `pats.len() >= 2`. - Or(&'hir [Pat<'hir>]), + Or(&'hir ThinSlice>), /// A path pattern for a unit struct/variant or a (maybe-associated) constant. Path(QPath<'hir>), @@ -1155,7 +1156,7 @@ pub enum PatKind<'hir> { /// A tuple pattern (e.g., `(a, b)`). /// If the `..` pattern fragment is present, then `Option` denotes its position. /// `0 <= position <= subpats.len()` - Tuple(&'hir [Pat<'hir>], DotDotPos), + Tuple(&'hir ThinSlice>, DotDotPos), /// A `box` pattern. Box(&'hir Pat<'hir>), @@ -1335,7 +1336,7 @@ impl UnOp { } /// A statement. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Stmt<'hir> { pub hir_id: HirId, pub kind: StmtKind<'hir>, @@ -1343,7 +1344,7 @@ pub struct Stmt<'hir> { } /// The contents of a statement. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum StmtKind<'hir> { /// A local (`let`) binding. Local(&'hir Local<'hir>), @@ -1359,7 +1360,7 @@ pub enum StmtKind<'hir> { } /// Represents a `let` statement (i.e., `let : = ;`). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Local<'hir> { pub pat: &'hir Pat<'hir>, /// Type annotation, if any (otherwise the type will be inferred). @@ -1377,7 +1378,7 @@ pub struct Local<'hir> { /// Represents a single arm of a `match` expression, e.g. /// ` (if ) => `. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Arm<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1395,7 +1396,7 @@ pub struct Arm<'hir> { /// /// In an if-let, imagine it as `if (let = ) { ... }`; in a let-else, it is part of the /// desugaring to if-let. Only let-else supports the type annotation at present. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Let<'hir> { pub hir_id: HirId, pub span: Span, @@ -1404,7 +1405,7 @@ pub struct Let<'hir> { pub init: &'hir Expr<'hir>, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum Guard<'hir> { If(&'hir Expr<'hir>), IfLet(&'hir Let<'hir>), @@ -1424,7 +1425,7 @@ impl<'hir> Guard<'hir> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct ExprField<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1472,7 +1473,7 @@ pub struct BodyId { /// /// All bodies have an **owner**, which can be accessed via the HIR /// map using `body_owner_def_id()`. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Body<'hir> { pub params: &'hir [Param<'hir>], pub value: &'hir Expr<'hir>, @@ -1663,7 +1664,7 @@ pub struct AnonConst { } /// An expression. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Expr<'hir> { pub hir_id: HirId, pub kind: ExprKind<'hir>, @@ -1821,8 +1822,8 @@ impl Expr<'_> { .all(|e| e.can_have_side_effects()), ExprKind::Array(args) - | ExprKind::Tup(args) - | ExprKind::Call( + | ExprKind::Tup(args) => args.iter().all(|arg| arg.can_have_side_effects()), + ExprKind::Call( Expr { kind: ExprKind::Path(QPath::Resolved( @@ -1904,7 +1905,7 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ExprKind<'hir> { /// Allow anonymous constants from an inline `const` block ConstBlock(AnonConst), @@ -1916,7 +1917,7 @@ pub enum ExprKind<'hir> { /// and the second field is the list of arguments. /// This also represents calling the constructor of /// tuple-like ADTs such as tuple structs and enum variants. - Call(&'hir Expr<'hir>, &'hir [Expr<'hir>]), + Call(&'hir Expr<'hir>, &'hir ThinSlice>), /// A method call (e.g., `x.foo::<'static, Bar, Baz>(a, b, c, d)`). /// /// The `PathSegment` represents the method name and its generic arguments @@ -1933,7 +1934,7 @@ pub enum ExprKind<'hir> { /// the `hir_id` of the `MethodCall` node itself. /// /// [`type_dependent_def_id`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.type_dependent_def_id - MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir [Expr<'hir>], Span), + MethodCall(&'hir PathSegment<'hir>, &'hir Expr<'hir>, &'hir ThinSlice>, Span), /// A tuple (e.g., `(a, b, c, d)`). Tup(&'hir [Expr<'hir>]), /// A binary operation (e.g., `a + b`, `a * b`). @@ -1941,7 +1942,7 @@ pub enum ExprKind<'hir> { /// A unary operation (e.g., `!x`, `*x`). Unary(UnOp, &'hir Expr<'hir>), /// A literal (e.g., `1`, `"foo"`). - Lit(Lit), + Lit(&'hir Lit), /// A cast (e.g., `foo as f64`). Cast(&'hir Expr<'hir>, &'hir Ty<'hir>), /// A type reference (e.g., `Foo`). @@ -2030,7 +2031,7 @@ pub enum ExprKind<'hir> { /// To resolve the path to a `DefId`, call [`qpath_res`]. /// /// [`qpath_res`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.qpath_res -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum QPath<'hir> { /// Path to a definition, optionally "fully-qualified" with a `Self` /// type, if the path points to an associated item in a trait. @@ -2222,7 +2223,7 @@ impl From for YieldSource { // N.B., if you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct MutTy<'hir> { pub ty: &'hir Ty<'hir>, pub mutbl: Mutability, @@ -2230,7 +2231,7 @@ pub struct MutTy<'hir> { /// Represents a function's signature in a trait declaration, /// trait implementation, or a free function. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct FnSig<'hir> { pub header: FnHeader, pub decl: &'hir FnDecl<'hir>, @@ -2257,7 +2258,7 @@ impl TraitItemId { /// possibly including a default implementation. A trait item is /// either required (meaning it doesn't have an implementation, just a /// signature) or provided (meaning it has a default implementation). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct TraitItem<'hir> { pub ident: Ident, pub owner_id: OwnerId, @@ -2306,7 +2307,7 @@ impl<'hir> TraitItem<'hir> { } /// Represents a trait method's body (or just argument names). -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)] pub enum TraitFn<'hir> { /// No default body in the trait, just a signature. Required(&'hir [Ident]), @@ -2316,7 +2317,7 @@ pub enum TraitFn<'hir> { } /// Represents a trait method or associated constant or type -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TraitItemKind<'hir> { /// An associated constant with an optional value (otherwise `impl`s must contain a value). Const(&'hir Ty<'hir>, Option), @@ -2344,7 +2345,7 @@ impl ImplItemId { } /// Represents anything within an `impl` block. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct ImplItem<'hir> { pub ident: Ident, pub owner_id: OwnerId, @@ -2394,7 +2395,7 @@ impl<'hir> ImplItem<'hir> { } /// Represents various kinds of content within an `impl`. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ImplItemKind<'hir> { /// An associated constant of the given type, set to the constant result /// of the expression. @@ -2423,7 +2424,7 @@ pub const FN_OUTPUT_NAME: Symbol = sym::Output; /// Binding(...), /// } /// ``` -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct TypeBinding<'hir> { pub hir_id: HirId, pub ident: Ident, @@ -2432,7 +2433,7 @@ pub struct TypeBinding<'hir> { pub span: Span, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum Term<'hir> { Ty(&'hir Ty<'hir>), Const(AnonConst), @@ -2451,7 +2452,7 @@ impl<'hir> From for Term<'hir> { } // Represents the two kinds of type bindings. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TypeBindingKind<'hir> { /// E.g., `Foo`. Constraint { bounds: &'hir [GenericBound<'hir>] }, @@ -2474,7 +2475,7 @@ impl TypeBinding<'_> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Ty<'hir> { pub hir_id: HirId, pub kind: TyKind<'hir>, @@ -2487,7 +2488,7 @@ impl<'hir> Ty<'hir> { let TyKind::Path(QPath::Resolved(None, path)) = self.kind else { return None; }; - let [segment] = &path.segments else { + let [segment] = &path.segments.as_slice() else { return None; }; match path.res { @@ -2619,7 +2620,7 @@ impl PrimTy { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct BareFnTy<'hir> { pub unsafety: Unsafety, pub abi: Abi, @@ -2628,7 +2629,7 @@ pub struct BareFnTy<'hir> { pub param_names: &'hir [Ident], } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct OpaqueTy<'hir> { pub generics: &'hir Generics<'hir>, pub bounds: GenericBounds<'hir>, @@ -2648,7 +2649,7 @@ pub enum OpaqueTyOrigin { } /// The various kinds of types recognized by the compiler. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TyKind<'hir> { /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), @@ -2688,7 +2689,7 @@ pub enum TyKind<'hir> { Err(rustc_span::ErrorGuaranteed), } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum InlineAsmOperand<'hir> { In { reg: InlineAsmRegOrRegClass, @@ -2741,7 +2742,7 @@ impl<'hir> InlineAsmOperand<'hir> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct InlineAsm<'hir> { pub template: &'hir [InlineAsmTemplatePiece], pub template_strs: &'hir [(Symbol, Option, Span)], @@ -2751,7 +2752,7 @@ pub struct InlineAsm<'hir> { } /// Represents a parameter in a function header. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Param<'hir> { pub hir_id: HirId, pub pat: &'hir Pat<'hir>, @@ -2760,7 +2761,7 @@ pub struct Param<'hir> { } /// Represents the header (not the body) of a function declaration. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct FnDecl<'hir> { /// The types of the function's parameters. /// @@ -2833,7 +2834,7 @@ impl Defaultness { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum FnRetTy<'hir> { /// Return type is not specified. /// @@ -2866,7 +2867,7 @@ pub enum ClosureBinder { For { span: Span }, } -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)] pub struct Mod<'hir> { pub spans: ModSpans, pub item_ids: &'hir [ItemId], @@ -2881,12 +2882,12 @@ pub struct ModSpans { pub inject_use_span: Span, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct EnumDef<'hir> { pub variants: &'hir [Variant<'hir>], } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Variant<'hir> { /// Name of the variant. pub ident: Ident, @@ -2923,7 +2924,7 @@ pub enum UseKind { /// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the /// trait being referred to but just a unique `HirId` that serves as a key /// within the resolution map. -#[derive(Clone, Debug, HashStable_Generic)] +#[derive(Clone, Debug, Copy, HashStable_Generic)] pub struct TraitRef<'hir> { pub path: &'hir Path<'hir>, // Don't hash the `ref_id`. It is tracked via the thing it is used to access. @@ -2942,7 +2943,7 @@ impl TraitRef<'_> { } } -#[derive(Clone, Debug, HashStable_Generic)] +#[derive(Clone, Debug, Copy, HashStable_Generic)] pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], @@ -2953,7 +2954,7 @@ pub struct PolyTraitRef<'hir> { pub span: Span, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct FieldDef<'hir> { pub span: Span, pub vis_span: Span, @@ -2972,7 +2973,7 @@ impl FieldDef<'_> { } /// Fields and constructor IDs of enum variants and structs. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum VariantData<'hir> { /// A struct variant. /// @@ -3299,7 +3300,7 @@ pub enum ItemKind<'hir> { Impl(&'hir Impl<'hir>), } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Impl<'hir> { pub unsafety: Unsafety, pub polarity: ImplPolarity, @@ -3362,7 +3363,7 @@ impl ItemKind<'_> { /// type or method, and whether it is public). This allows other /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Encodable, Debug, Clone, Copy, HashStable_Generic)] pub struct TraitItemRef { pub id: TraitItemId, pub ident: Ident, @@ -3376,7 +3377,7 @@ pub struct TraitItemRef { /// type or method, and whether it is public). This allows other /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct ImplItemRef { pub id: ImplItemId, pub ident: Ident, @@ -3415,14 +3416,14 @@ impl ForeignItemId { /// type or method, and whether it is public). This allows other /// passes to find the impl they want without loading the ID (which /// means fewer edges in the incremental compilation graph). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct ForeignItemRef { pub id: ForeignItemId, pub ident: Ident, pub span: Span, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct ForeignItem<'hir> { pub ident: Ident, pub kind: ForeignItemKind<'hir>, @@ -3444,7 +3445,7 @@ impl ForeignItem<'_> { } /// An item within an `extern` block. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ForeignItemKind<'hir> { /// A foreign function. Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>), @@ -3464,7 +3465,7 @@ pub struct Upvar { // The TraitCandidate's import_ids is empty if the trait is defined in the same module, and // has length > 0 if the trait is found through an chain of imports, starting with the // import/use statement in the scope where the trait is used. -#[derive(Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Encodable, Decodable, Debug, Clone, HashStable_Generic)] pub struct TraitCandidate { pub def_id: DefId, pub import_ids: SmallVec<[LocalDefId; 1]>, @@ -3967,14 +3968,14 @@ mod size_asserts { // tidy-alphabetical-start static_assert_size!(Block<'_>, 48); static_assert_size!(Body<'_>, 32); - static_assert_size!(Expr<'_>, 64); - static_assert_size!(ExprKind<'_>, 48); + static_assert_size!(Expr<'_>, 56); + static_assert_size!(ExprKind<'_>, 40); static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); static_assert_size!(GenericArg<'_>, 32); static_assert_size!(GenericBound<'_>, 48); - static_assert_size!(Generics<'_>, 56); + static_assert_size!(Generics<'_>, 40); static_assert_size!(Impl<'_>, 80); static_assert_size!(ImplItem<'_>, 80); static_assert_size!(ImplItemKind<'_>, 32); @@ -3983,7 +3984,7 @@ mod size_asserts { static_assert_size!(Local<'_>, 64); static_assert_size!(Param<'_>, 32); static_assert_size!(Pat<'_>, 72); - static_assert_size!(Path<'_>, 40); + static_assert_size!(Path<'_>, 32); static_assert_size!(PathSegment<'_>, 48); static_assert_size!(PatKind<'_>, 48); static_assert_size!(QPath<'_>, 24); @@ -3997,6 +3998,22 @@ mod size_asserts { // tidy-alphabetical-end } +mod dropless { + use super::*; + + macro_rules! static_assert_no_destructor { + ($ty:ty) => { + const _: () = { + if std::mem::needs_drop::<$ty>() { + panic!(concat!(stringify!($ty), " has a destructor")); + } + }; + }; + } + + static_assert_no_destructor!(Expr<'_>); +} + fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug { struct DebugFn(F); impl) -> fmt::Result> fmt::Debug for DebugFn { diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 98d967cc0b86e..cc700e5d346f2 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -31,6 +31,7 @@ pub mod def_path_hash_map; pub mod definitions; pub mod diagnostic_items; pub mod errors; +use rustc_data_structures::thin_slice::ThinSlice; pub use rustc_span::def_id; mod hir; pub mod hir_id; @@ -47,7 +48,54 @@ mod tests; pub use hir::*; pub use hir_id::*; pub use lang_items::{LangItem, LanguageItems}; +use smallvec::SmallVec; pub use stable_hash_impls::HashStableContext; pub use target::{MethodKind, Target}; arena_types!(rustc_arena::declare_arena); + +pub trait ArenaAllocatableThin<'tcx, C = rustc_arena::IsNotCopy>: Sized { + fn allocate_thin_from_iter<'a>( + arena: &'a Arena<'tcx>, + iter: impl ::std::iter::IntoIterator, + ) -> &'a ThinSlice; +} + +// Any type that impls `Copy` can be arena-allocated in the `DroplessArena`. +impl<'tcx, T: Copy> ArenaAllocatableThin<'tcx, rustc_arena::IsCopy> for T { + fn allocate_thin_from_iter<'a>( + arena: &'a Arena<'tcx>, + iter: impl ::std::iter::IntoIterator, + ) -> &'a ThinSlice { + let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect(); + + let len = vec.len(); + if len == 0 { + return ThinSlice::empty(); + } + // Move the content to the arena by copying and then forgetting it. + + let slice = vec.as_slice(); + + let (layout, _offset) = std::alloc::Layout::new::() + .extend(std::alloc::Layout::for_value::<[T]>(slice)) + .unwrap(); + let mem = arena.dropless.alloc_raw(layout) as *mut ThinSlice; + // SAFETY: We ensured that we allocated enough memory above. It includes the ptr and the slice correctly aligned. + let thin = unsafe { ThinSlice::initialize(mem, slice) }; + unsafe { + vec.set_len(0); + } + thin + } +} + +impl<'tcx> Arena<'tcx> { + #[inline] + pub fn allocate_thin_from_iter<'a, T: ArenaAllocatableThin<'tcx, C>, C>( + &'a self, + iter: impl ::std::iter::IntoIterator, + ) -> &'a ThinSlice { + T::allocate_thin_from_iter(self, iter) + } +} diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index e870aa543d0b5..a8a423a94324b 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -140,7 +140,9 @@ impl hir::Pat<'_> { /// If the pattern is `Some()` from a desugared for loop, returns the inner pattern pub fn for_loop_some(&self) -> Option<&Self> { if self.span.desugaring_kind() == Some(DesugaringKind::ForLoop) { - if let hir::PatKind::Struct(_, [pat_field], _) = self.kind { + if let hir::PatKind::Struct(_, fields, _) = self.kind + && let [pat_field] = fields.as_slice() + { return Some(pat_field.pat); } } diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 156334fe785b9..3900b626a965c 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -456,7 +456,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) { - match bound.trait_ref.path.segments { + match bound.trait_ref.path.segments.as_slice() { // 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. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6d9dfe9697c0c..251ac10502e22 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1982,7 +1982,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) = &qself.kind { // If the path segment already has type params, we want to overwrite // them. - match &path.segments { + match &path.segments.as_slice() { // `segment` is the previous to last element on the path, // which would normally be the `enum` itself, while the last // `_` `PathSegment` corresponds to the variant. @@ -2855,7 +2855,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // `Self` in trait or type alias. assert_eq!(opt_self_ty, None); self.prohibit_generics(path.segments.iter(), |err| { - if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments { + if let [hir::PathSegment { args: Some(args), ident, .. }] = &path.segments.as_slice() { err.span_suggestion_verbose( ident.span.shrink_to_hi().to(args.span_ext), "the `Self` type doesn't accept type parameters", diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index d8dda7a93be13..ffa8a843552e8 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -281,7 +281,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { match arg.kind { - hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments.as_slice() { [PathSegment { res: Res::SelfTyParam { .. }, .. }] => { let impl_ty_name = None; self.selftys.push((path.span, impl_ty_name)); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 737532b98a47a..f4bfa70f27962 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -745,10 +745,12 @@ impl<'tcx> TypeVisitor> for GATSubstCollector<'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 { - [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()), - _ => false, - }, + hir::TyKind::TraitObject([trait_ref], ..) => { + match trait_ref.trait_ref.path.segments.as_slice() { + [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()), + _ => false, + } + } _ => false, } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c41e96290df16..6a8c147dfebc2 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -438,7 +438,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { | hir::ItemKind::Struct(_, generics) | hir::ItemKind::Union(_, generics) => { let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics); - let (lt_sp, sugg) = match generics.params { + let (lt_sp, sugg) = match generics.params.as_slice() { [] => (generics.span, format!("<{}>", lt_name)), [bound, ..] => { (bound.span.shrink_to_lo(), format!("{}, ", lt_name)) diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index cae884ae8fb73..9e196dbed0918 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -803,7 +803,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { rcvr.span.find_ancestor_inside(expr.span).unwrap_or(rcvr.span) ) else { return; }; let Ok(rest) = - (match args { + (match args.as_slice() { [] => Ok(String::new()), [arg] => sm.span_to_snippet( arg.span.find_ancestor_inside(expr.span).unwrap_or(arg.span), diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 5235710a2666e..28b9dd43f38d6 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -412,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind - && let [segment] = path.segments + && let [segment] = path.segments.as_slice() && let Some(mut diag) = self .tcx .sess diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 4846579b9809b..923daf98f26a2 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let map = self.tcx.hir(); let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; }; - let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; }; + let [hir::PathSegment { ident, args: None, .. }] = p.segments.as_slice() else { return false; }; let hir::def::Res::Local(hir_id) = p.res else { return false; }; let Some(hir::Node::Pat(pat)) = map.find(hir_id) else { return false; }; let Some(hir::Node::Local(hir::Local { @@ -1130,12 +1130,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, hir::Path { res: hir::def::Res::Local(_), - segments: [hir::PathSegment { ident, .. }], + segments, .. }, )), .. - } => Some(ident), + } if let [hir::PathSegment { ident, .. }] = segments.as_slice() => Some(ident), _ => None, }?; @@ -1951,7 +1951,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Check if start has method named end. let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = method_name.kind else { return; }; - let [hir::PathSegment { ident, .. }] = p.segments else { return; }; + let [hir::PathSegment { ident, .. }] = p.segments.as_slice() else { return; }; let self_ty = self.typeck_results.borrow().expr_ty(start.expr); let Ok(_pick) = self.lookup_probe_for_diagnostic( *ident, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 3def97bca4789..df8d1acef53cf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1019,8 +1019,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match rcvr.kind { ExprKind::Path(QPath::Resolved( None, - hir::Path { segments: [segment], .. }, - )) => format!("`{}`", segment.ident), + hir::Path { segments, .. }, + )) if let [segment] = segments.as_slice() => format!("`{}`", segment.ident), _ => "its receiver".to_string(), } ), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 18a49ef2f0162..e3b7198a2d962 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -246,22 +246,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'tcx>, expected: Ty<'tcx>, ) -> bool { - if let hir::ExprKind::MethodCall(hir::PathSegment { ident: method, .. }, recv_expr, &[], _) = expr.kind && - let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) && - self.can_coerce(recv_ty, expected) { - let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) { - expr.span.with_lo(recv_span.hi()) - } else { - expr.span.with_lo(method.span.lo() - rustc_span::BytePos(1)) - }; - err.span_suggestion_verbose( - span, - "try removing the method call", - "", - Applicability::MachineApplicable, - ); - return true; - } + if let hir::ExprKind::MethodCall(hir::PathSegment { ident: method, .. }, recv_expr, args, _) = expr.kind + && args.is_empty() + && let Some(recv_ty) = self.typeck_results.borrow().expr_ty_opt(recv_expr) + && self.can_coerce(recv_ty, expected) + { + let span = if let Some(recv_span) = recv_expr.span.find_ancestor_inside(expr.span) { + expr.span.with_lo(recv_span.hi()) + } else { + expr.span.with_lo(method.span.lo() - rustc_span::BytePos(1)) + }; + err.span_suggestion_verbose( + span, + "try removing the method call", + "", + Applicability::MachineApplicable, + ); + return true; + } false } @@ -713,8 +715,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .. }) = self.tcx.hir().get(item_id.hir_id()) && let [hir::GenericBound::LangItemTrait( - hir::LangItem::Future, _, _, generic_args)] = op_ty.bounds - && let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args + hir::LangItem::Future, _, _, generic_args)] = op_ty.bounds.as_slice() + && let hir::GenericArgs { bindings, .. } = generic_args + && let [ty_binding] = bindings.as_slice() && let hir::TypeBindingKind::Equality { term: hir::Term::Ty(term) } = ty_binding.kind { // Check if async function's return type was omitted. @@ -1243,7 +1246,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { node: rustc_ast::LitKind::Int(lit, rustc_ast::LitIntType::Unsuffixed), span, }) => { - let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; }; + let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(*span) else { return false; }; if !(snippet.starts_with("0x") || snippet.starts_with("0X")) { return false; } @@ -1302,7 +1305,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We have satisfied all requirements to provide a suggestion. Emit it. err.span_suggestion( - span, + *span, format!("if you meant to create a null pointer, use `{null_path_str}()`"), null_path_str + "()", Applicability::MachineApplicable, @@ -1328,9 +1331,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (item, segment) = match expr.kind { hir::ExprKind::Path(QPath::Resolved( Some(ty), - hir::Path { segments: [segment], .. }, - )) - | hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => { + hir::Path { segments, .. }, + )) if let [segment] = segments.as_slice() => { + if let Some(self_ty) = self.typeck_results.borrow().node_type_opt(ty.hir_id) + && let Ok(pick) = self.probe_for_name( + Mode::Path, + Ident::new(capitalized_name, segment.ident.span), + Some(expected_ty), + IsSuggestion(true), + self_ty, + expr.hir_id, + ProbeScope::TraitsInScope, + ) + { + (pick.item, segment) + } else { + return false; + } + } + hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => { if let Some(self_ty) = self.typeck_results.borrow().node_type_opt(ty.hir_id) && let Ok(pick) = self.probe_for_name( Mode::Path, @@ -1349,8 +1368,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } hir::ExprKind::Path(QPath::Resolved( None, - hir::Path { segments: [.., segment], .. }, - )) => { + hir::Path { segments, .. }, + )) if let [.., segment] = segments.as_slice() => { // we resolved through some path that doesn't end in the item name, // better not do a bad suggestion by accident. if old_item_name != segment.ident.name { @@ -1410,7 +1429,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found_ty: Ty<'tcx>, expr: &hir::Expr<'_>, ) { - let hir::ExprKind::MethodCall(segment, callee_expr, &[], _) = expr.kind else { return; }; + let hir::ExprKind::MethodCall(segment, callee_expr, args, _) = expr.kind else { return; }; + if !args.is_empty() { + return; + } let Some(clone_trait_did) = self.tcx.lang_items().clone_trait() else { return; }; let ty::Ref(_, pointee_ty, _) = found_ty.kind() else { return }; let results = self.typeck_results.borrow(); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c36c75e444368..fa19b407f9c8f 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1873,7 +1873,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let len = unmentioned_fields.len(); let (prefix, postfix, sp) = match fields { [] => match &pat.kind { - PatKind::Struct(path, [], false) => { + PatKind::Struct(path, fields, false) if fields.is_empty() => { (" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi())) } _ => return err, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index fd16363a1db01..147ce242863fb 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2314,7 +2314,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit } ) }); - if named_lifetime_param_exist && let [param, ..] = ast_generics.params + if named_lifetime_param_exist && let [param, ..] = ast_generics.params.as_slice() { add_lt_suggs.push(Some(( self.tcx.def_span(param.def_id).shrink_to_lo(), diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 2875448ee157c..940fff3c3268a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -144,7 +144,7 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { hir::intravisit::walk_ty(self, mut_ty.ty); return; } - hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { + hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments.as_slice() { [segment] if matches!( segment.res, diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index bccb0a94e986d..848dd7f0bb231 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -51,7 +51,9 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { // Save the span of expressions in `for _ in expr` syntax, // so we can give a better suggestion for those later. if let hir::ExprKind::Match(arg, [_], hir::MatchSource::ForLoopDesugar) = &expr.kind { - if let hir::ExprKind::Call(path, [arg]) = &arg.kind { + if let hir::ExprKind::Call(path, args) = &arg.kind + && let [arg] = args.as_slice() + { if let hir::ExprKind::Path(hir::QPath::LangItem( hir::LangItem::IntoIterIntoIter, .., diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 7b58bf03bbea8..6972e3a555d4f 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -85,12 +85,14 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { fn extract_for_loop<'tcx>(expr: &Expr<'tcx>) -> Option<(&'tcx Pat<'tcx>, &'tcx Expr<'tcx>)> { if let hir::ExprKind::DropTemps(e) = expr.kind && let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind - && let hir::ExprKind::Call(_, [arg]) = iterexpr.kind + && let hir::ExprKind::Call(_, args) = iterexpr.kind + && let [arg] = args.as_slice() && let hir::ExprKind::Loop(block, ..) = arm.body.kind && let [stmt] = block.stmts && let hir::StmtKind::Expr(e) = stmt.kind && let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind - && let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind + && let hir::PatKind::Struct(_, fields, _) = some_arm.pat.kind + && let [field] = fields.as_slice() { Some((field.pat, arg)) } else { diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 5bb1abfd2ec97..9388483ce45dd 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -47,7 +47,9 @@ declare_lint_pass!(NonPanicFmt => [NON_FMT_PANICS]); impl<'tcx> LateLintPass<'tcx> for NonPanicFmt { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if let hir::ExprKind::Call(f, [arg]) = &expr.kind { + if let hir::ExprKind::Call(f, args) = &expr.kind + && let [arg] = args.as_slice() + { if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() { let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index faca61fc29bf9..1e20f4b08977a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1364,8 +1364,9 @@ declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]); impl<'tcx> LateLintPass<'tcx> for UnusedAllocation { fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) { match e.kind { - hir::ExprKind::Call(path_expr, [_]) - if let hir::ExprKind::Path(qpath) = &path_expr.kind + hir::ExprKind::Call(path_expr, args) + if args.len() == 1 + && let hir::ExprKind::Path(qpath) = &path_expr.kind && let Some(did) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() && cx.tcx.is_diagnostic_item(sym::box_new, did) => {} diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 79365ef281be7..40b11377a086b 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -1,4 +1,5 @@ use crate::arena::Arena; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_serialize::{Encodable, Encoder}; use std::alloc::Layout; use std::cmp::Ordering; @@ -8,7 +9,6 @@ use std::iter; use std::mem; use std::ops::Deref; use std::ptr; -use std::slice; /// `List` is a bit like `&[T]`, but with some critical differences. /// - IMPORTANT: Every `List` is *required* to have unique contents. The @@ -26,48 +26,29 @@ use std::slice; /// - `T` must be `Copy`. This lets `List` be stored in a dropless arena and /// iterators return a `T` rather than a `&T`. /// - `T` must not be zero-sized. -#[repr(C)] +#[repr(transparent)] pub struct List { - len: usize, - - /// Although this claims to be a zero-length array, in practice `len` - /// elements are actually present. - data: [T; 0], - - opaque: OpaqueListContents, -} - -extern "C" { - /// A dummy type used to force `List` to be unsized while not requiring - /// references to it be wide pointers. - type OpaqueListContents; + inner: ThinSlice, } impl List { /// Returns a reference to the (unique, static) empty list. #[inline(always)] pub fn empty<'a>() -> &'a List { - #[repr(align(64))] - struct MaxAlign; - - assert!(mem::align_of::() <= mem::align_of::()); - - #[repr(C)] - struct InOrder(T, U); - - // The empty slice is static and contains a single `0` usize (for the - // length) that is 64-byte aligned, thus featuring the necessary - // trailing padding for elements with up to 64-byte alignment. - static EMPTY_SLICE: InOrder = InOrder(0, MaxAlign); - unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } + Self::from_inner(ThinSlice::empty()) } pub fn len(&self) -> usize { - self.len + self.inner.len() } pub fn as_slice(&self) -> &[T] { - self + self.inner.as_slice() + } + + fn from_inner(inner: &ThinSlice) -> &Self { + // SAFETY: We are repr(transparent). + unsafe { &*(inner as *const ThinSlice as *const Self) } } } @@ -89,18 +70,9 @@ impl List { let (layout, _offset) = Layout::new::().extend(Layout::for_value::<[T]>(slice)).unwrap(); - let mem = arena.dropless.alloc_raw(layout) as *mut List; - unsafe { - // Write the length - ptr::addr_of_mut!((*mem).len).write(slice.len()); - - // Write the elements - ptr::addr_of_mut!((*mem).data) - .cast::() - .copy_from_nonoverlapping(slice.as_ptr(), slice.len()); - - &*mem - } + let mem = arena.dropless.alloc_raw(layout) as *mut ThinSlice; + // SAFETY: We ensured that we allocated enough memory above. It includes the ptr and the slice correctly aligned. + unsafe { Self::from_inner(ThinSlice::initialize(mem, slice)) } } // If this method didn't exist, we would use `slice.iter` due to @@ -183,7 +155,7 @@ impl Deref for List { impl AsRef<[T]> for List { #[inline(always)] fn as_ref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } + self.inner.as_ref() } } @@ -196,8 +168,6 @@ impl<'a, T: Copy> IntoIterator for &'a List { } } -unsafe impl Sync for List {} - unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List { const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 6fd9b9dbb5755..4afbcb77b08d7 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -334,7 +334,7 @@ impl<'tcx> Cx<'tcx> { && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && path.res.opt_def_id().map_or(false, |did| did == box_item) && fn_path.ident.name == sym::new - && let [value] = args + && let [value] = args.as_slice() { return Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: ExprKind::Box { value: self.mirror_expr(value) } } } else { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 2640ca56b00e9..693e64c045bf0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -394,10 +394,11 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { if let hir::PatKind::Path(hir::QPath::Resolved( None, hir::Path { - segments: &[hir::PathSegment { args: None, res, ident, .. }], + segments, .. }, )) = &pat.kind + && let &[hir::PathSegment { args: None, res, ident, .. }] = segments.as_slice() { ( None, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1b0cd5d91ab53..cc10e92c1d5b4 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -938,8 +938,8 @@ impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> { match self.break_expr_kind { ExprKind::Path(hir::QPath::Resolved( None, - hir::Path { segments: [segment], res: hir::def::Res::Err, .. }, - )) if label.ident.to_string() == format!("'{}", segment.ident) => { + hir::Path { segments, res: hir::def::Res::Err, .. }, + )) if let [segment] = segments.as_slice() && label.ident.to_string() == format!("'{}", segment.ident) => { // This error is redundant, we will have already emitted a // suggestion to use the label when `segment` wasn't found // (hence the `Res::Err` check). diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index b7e07aff42bf2..54a6ddf585858 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -8,6 +8,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(iter_intersperse)] #![feature(let_chains)] +#![feature(if_let_guard)] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(try_blocks)] diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index a8471ce3b6fb2..210b77816ccd4 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -331,7 +331,7 @@ impl<'tcx> IrMaps<'tcx> { pats.extend(inner_pat.iter()); } Struct(_, fields, _) => { - let (short, not_short): (Vec<_>, _) = + let (short, not_short): (Vec>, _) = fields.iter().partition(|f| f.is_shorthand); shorthand_field_ids.extend(short.iter().map(|f| f.pat.hir_id)); pats.extend(not_short.iter().map(|f| f.pat)); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 296fd1ed5248f..e5aaeb8e52354 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2399,7 +2399,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { res: rustc_hir::def::Res::Def(_, item_id), .. } - ] = path.segments + ] = path.segments.as_slice() && data.trait_ref.def_id == *trait_id && self.tcx.trait_of_item(*item_id) == Some(*trait_id) && let None = self.tainted_by_errors() diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index be0817472ea41..a87c54a987a8a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -11,6 +11,7 @@ use crate::traits::{NormalizeExt, ObligationCtxt}; use hir::def::CtorOf; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_errors::{ error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, Style, @@ -491,13 +492,14 @@ fn suggest_restriction<'tcx>( return; } // Trivial case: `T` needs an extra bound: `T: Bound`. - let (sp, suggestion) = match ( - hir_generics - .params - .iter() - .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })), - super_traits, - ) { + let type_param = hir_generics + .params + .iter() + .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })); + + let super_traits = super_traits.map(|(ident, bounds)| (ident, bounds.as_slice())); + + let (sp, suggestion) = match (type_param, super_traits) { (_, None) => predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)), (None, Some((ident, []))) => ( ident.span.shrink_to_hi(), @@ -4082,7 +4084,7 @@ pub trait NextTypeParamName { fn next_type_param_name(&self, name: Option<&str>) -> String; } -impl NextTypeParamName for &[hir::GenericParam<'_>] { +impl NextTypeParamName for &ThinSlice> { fn next_type_param_name(&self, name: Option<&str>) -> String { // This is the list of possible parameter names that we might suggest. let name = name.and_then(|n| n.chars().next()).map(|c| c.to_string().to_uppercase()); diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 04fdb15f5acb2..31e5c1eb0ba4a 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -84,6 +84,7 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT python3 ../src/ci/stage-build.py python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ + --exclude clippy \ build-manifest bootstrap ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c00fa5994bfce..32bde51e68a78 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -15,6 +15,7 @@ use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry}; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; @@ -1508,7 +1509,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type // Otherwise, this is an inherent associated type. _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None), }; - let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx); + let trait_ = clean_path(&hir::Path { span, res, segments: ThinSlice::empty() }, cx); register_res(cx, trait_.res); let self_def_id = res.opt_def_id(); let self_type = clean_ty(qself, cx); @@ -2083,7 +2084,7 @@ fn get_path_parent_def_id( def_id: DefId, path: &hir::UsePath<'_>, ) -> Option { - if let [.., parent_segment, _] = &path.segments { + if let [.., parent_segment, _] = &path.segments.as_slice() { match parent_segment.res { hir::def::Res::Def(_, parent_def_id) => Some(parent_def_id), _ if parent_segment.ident.name == kw::Crate => { diff --git a/src/tools/clippy/clippy_lints/src/size_of_ref.rs b/src/tools/clippy/clippy_lints/src/size_of_ref.rs index 8abec06c641cc..59875f6142c3f 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_ref.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_ref.rs @@ -54,7 +54,8 @@ declare_lint_pass!(SizeOfRef => [SIZE_OF_REF]); impl LateLintPass<'_> for SizeOfRef { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { - if let ExprKind::Call(path, [arg]) = expr.kind + if let ExprKind::Call(path, args) = expr.kind + && let [arg] = args.as_slice() && let Some(def_id) = path_def_id(cx, path) && cx.tcx.is_diagnostic_item(sym::mem_size_of_val, def_id) && let arg_ty = cx.typeck_results().expr_ty(arg) diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index a2109038a0578..7770fdb9086d1 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -122,7 +122,8 @@ impl SlowVectorInit { /// of the first argument of `with_capacity` call if it matches or `None` if it does not. fn is_vec_with_capacity<'tcx>(cx: &LateContext<'_>, expr: &Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { if_chain! { - if let ExprKind::Call(func, [arg]) = expr.kind; + if let ExprKind::Call(func, args) = expr.kind; + if let [arg] = args.as_slice(); if let ExprKind::Path(QPath::TypeRelative(ty, name)) = func.kind; if name.ident.as_str() == "with_capacity"; if is_type_diagnostic_item(cx, cx.typeck_results().node_type(ty.hir_id), sym::Vec); @@ -202,7 +203,8 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) { if_chain! { if self.initialization_found; - if let ExprKind::MethodCall(path, self_arg, [extend_arg], _) = expr.kind; + if let ExprKind::MethodCall(path, self_arg, args, _) = expr.kind; + if let [extend_arg] = args.as_slice(); if path_to_local_id(self_arg, self.vec_alloc.local_id); if path.ident.name == sym!(extend); if self.is_repeat_take(extend_arg); @@ -216,7 +218,8 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Checks if the given expression is resizing a vector with 0 fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) { if self.initialization_found - && let ExprKind::MethodCall(path, self_arg, [len_arg, fill_arg], _) = expr.kind + && let ExprKind::MethodCall(path, self_arg, args, _) = expr.kind + && let [len_arg, fill_arg] = args.as_slice() && path_to_local_id(self_arg, self.vec_alloc.local_id) && path.ident.name == sym!(resize) // Check that is filled with 0 @@ -253,7 +256,8 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> { /// Returns `true` if given expression is `repeat(0)` fn is_repeat_zero(&self, expr: &Expr<'_>) -> bool { if_chain! { - if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind; + if let ExprKind::Call(fn_expr, args) = expr.kind; + if let [repeat_arg] = args.as_slice(); if is_path_diagnostic_item(self.cx, fn_expr, sym::iter_repeat); if is_integer_literal(repeat_arg, 0); then { diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index a13bc7a518871..5e7e9563c4c51 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -141,7 +141,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { /// If this is a global path (such as `::std::fmt::Debug`), then the segment after [`kw::PathRoot`] /// is returned. fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>> { - match path.segments { + match path.segments.as_slice() { // A global path will have PathRoot as the first segment. In this case, return the segment after. [x, y, ..] if x.ident.name == kw::PathRoot => Some(y), [x, ..] => Some(x), diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index b2f4b310915a6..486230a200d71 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -343,9 +343,11 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { } if_chain! { - if let ExprKind::MethodCall(path, recv, [], _) = &e.kind; + if let ExprKind::MethodCall(path, recv, args, _) = &e.kind; + if args.is_empty(); if path.ident.name == sym!(into_bytes); - if let ExprKind::MethodCall(path, recv, [], _) = &recv.kind; + if let ExprKind::MethodCall(path, recv, args, _) = &recv.kind; + if args.is_empty(); if matches!(path.ident.name.as_str(), "to_owned" | "to_string"); if let ExprKind::Lit(lit) = &recv.kind; if let LitKind::Str(lit_content, _) = &lit.node; @@ -497,11 +499,13 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { let tyckres = cx.typeck_results(); if_chain! { - if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind; + if let ExprKind::MethodCall(path, split_recv, args, split_ws_span) = expr.kind; + if args.is_empty(); if path.ident.name == sym!(split_whitespace); if let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id); if cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id); - if let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind; + if let ExprKind::MethodCall(path, _trim_recv, args, trim_span) = split_recv.kind; + if args.is_empty(); if let trim_fn_name @ ("trim" | "trim_start" | "trim_end") = path.ident.name.as_str(); if let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id); if is_one_of_trim_diagnostic_items(cx, trim_def_id); diff --git a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs index 03324c66e8efc..ca59f3163889f 100644 --- a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs +++ b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs @@ -43,11 +43,13 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { if_chain! { if !expr.span.from_expansion(); - if let ExprKind::Call(func, [recv]) = expr.kind; + if let ExprKind::Call(func, args) = expr.kind; + if let [recv] = args.as_slice(); if let ExprKind::Path(path) = &func.kind; if let Some(did) = cx.qpath_res(path, func.hir_id).opt_def_id(); if match_libc_symbol(cx, did, "strlen"); - if let ExprKind::MethodCall(path, self_arg, [], _) = recv.kind; + if let ExprKind::MethodCall(path, self_arg, args, _) = recv.kind; + if args.is_empty(); if !recv.span.from_expansion(); if path.ident.name == sym::as_ptr; then { diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index f7eef03d1d473..6779623f6434f 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -225,7 +225,7 @@ fn is_same(cx: &LateContext<'_>, lhs: ExprOrIdent<'_>, rhs: &Expr<'_>) -> bool { ExprOrIdent::Expr(expr) => eq_expr_value(cx, expr, rhs), ExprOrIdent::Ident(ident) => { if let ExprKind::Path(QPath::Resolved(None, path)) = rhs.kind - && let [segment] = &path.segments + && let [segment] = &path.segments.as_slice() && segment.ident == ident { true diff --git a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs index d085dda3582be..7debd3d81cfdc 100644 --- a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs @@ -40,7 +40,8 @@ declare_lint_pass!(SwapPtrToRef => [SWAP_PTR_TO_REF]); impl LateLintPass<'_> for SwapPtrToRef { fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) { - if let ExprKind::Call(fn_expr, [arg1, arg2]) = e.kind + if let ExprKind::Call(fn_expr, args) = e.kind + && let [arg1, arg2] = args.as_slice() && let Some(fn_id) = path_def_id(cx, fn_expr) && match_def_path(cx, fn_id, &paths::MEM_SWAP) && let ctxt = e.span.ctxt() diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs index 2512500a6be73..b25f6f76d5741 100644 --- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs +++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs @@ -39,11 +39,14 @@ declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]); impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { if_chain! { - if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, [], _) = &expr.kind; + if let hir::ExprKind::MethodCall(is_some_path, to_digit_expr, args, _) = &expr.kind; + if args.is_empty(); if is_some_path.ident.name.as_str() == "is_some"; then { let match_result = match &to_digit_expr.kind { - hir::ExprKind::MethodCall(to_digits_path, char_arg, [radix_arg], _) => { + hir::ExprKind::MethodCall(to_digits_path, char_arg, args, _) + if let [radix_arg] = args.as_slice() => + { if_chain! { if to_digits_path.ident.name.as_str() == "to_digit"; let char_arg_ty = cx.typeck_results().expr_ty_adjusted(char_arg); @@ -57,7 +60,7 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome { } hir::ExprKind::Call(to_digits_call, to_digit_args) => { if_chain! { - if let [char_arg, radix_arg] = *to_digit_args; + if let [char_arg, radix_arg] = *to_digit_args.as_slice(); if let hir::ExprKind::Path(to_digits_path) = &to_digits_call.kind; if let to_digits_call_res = cx.qpath_res(to_digits_path, to_digits_call.hir_id); if let Some(to_digits_def_id) = to_digits_call_res.opt_def_id(); diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs index 0dc30f7a93554..31ddd157d754a 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs @@ -495,7 +495,8 @@ impl Transmute { impl<'tcx> LateLintPass<'tcx> for Transmute { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { if_chain! { - if let ExprKind::Call(path_expr, [arg]) = e.kind; + if let ExprKind::Call(path_expr, args) = e.kind; + if let [arg] = args.as_slice(); if let ExprKind::Path(QPath::Resolved(None, path)) = path_expr.kind; if let Some(def_id) = path.res.opt_def_id(); if cx.tcx.is_diagnostic_item(sym::transmute, def_id); diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs index e75d7f6bf1d52..6a7531f8061e9 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs @@ -47,7 +47,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t // Catching: // `std::mem::transmute(std::ptr::null::())` - ExprKind::Call(func1, []) if is_path_diagnostic_item(cx, func1, sym::ptr_null) => { + ExprKind::Call(func1, args) if args.is_empty() && is_path_diagnostic_item(cx, func1, sym::ptr_null) => { lint_expr(cx, expr); true }, diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs index 1e407fc4138c1..2061e6a3c3119 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs @@ -33,8 +33,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t // Catching: // `std::mem::transmute(std::ptr::null::())` - if let ExprKind::Call(func1, []) = arg.kind && - is_path_diagnostic_item(cx, func1, sym::ptr_null) + if let ExprKind::Call(func1, args) = arg.kind + && args.is_empty() + && is_path_diagnostic_item(cx, func1, sym::ptr_null) { span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG); return true; diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index 65dfe7637ea99..0baabdc470169 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m if let Some(def_id) = def.opt_def_id(); if Some(def_id) == cx.tcx.lang_items().owned_box(); if let QPath::Resolved(None, path) = *qpath; - if let [ref bx] = *path.segments; + if let [ref bx] = *path.segments.as_slice(); if let Some(params) = bx.args; if !params.parenthesized; if let Some(inner) = params.args.iter().find_map(|arg| match arg { diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs index 1ab0162a88134..2c7a3d79524ff 100644 --- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs +++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs @@ -177,7 +177,7 @@ fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt }); } }, - ExprKind::MethodCall(path, self_expr, [_], _) if is_reserve(cx, path, self_expr) => { + ExprKind::MethodCall(path, self_expr, args, _) if args.len() == 1 && is_reserve(cx, path, self_expr) => { return Some(TargetVec { location: VecLocation::Expr(self_expr), init_kind: None, @@ -211,7 +211,9 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt } }); match expr.kind { - ExprKind::MethodCall(path, self_expr, [arg], _) => { + ExprKind::MethodCall(path, self_expr, args, _) + if let [arg] = args.as_slice() => + { let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs(); if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs index cc7c2b039f2d7..725ed8a13e7b7 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs @@ -19,11 +19,11 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) { && cx.typeck_results().pat_ty(local.pat).is_unit() { if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer)) - || matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none())) + || matches!(local.pat.kind, PatKind::Tuple(pats, ddpos) if pats.is_empty() && ddpos.as_opt_usize().is_none())) && expr_needs_inferred_result(cx, init) { if !matches!(local.pat.kind, PatKind::Wild) - && !matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()) + && !matches!(local.pat.kind, PatKind::Tuple(args, ddpos) if args.is_empty() && ddpos.as_opt_usize().is_none()) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs index 0bcafde658a43..6aae0d2bc60ca 100644 --- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs +++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs @@ -93,7 +93,8 @@ impl LateLintPass<'_> for UnnamedAddress { } if_chain! { - if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind; + if let ExprKind::Call(func, args) = expr.kind; + if let [ref _left, ref _right] = args.as_slice(); if let ExprKind::Path(ref func_qpath) = func.kind; if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); if match_def_path(cx, def_id, &paths::PTR_EQ) || diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs index 6e802794f5aa3..f3cdf309eefa3 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings { } else { if_chain! { if cx.tcx.is_diagnostic_item(sym::from_fn, fun_def_id); - if let [.., last_arg] = args; + if let [.., last_arg] = args.as_slice(); if let ExprKind::Lit(spanned) = &last_arg.kind; if let LitKind::Str(symbol, _) = spanned.node; if symbol.is_empty(); diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index 8b0e0ce5a3001..710dea9b66b1f 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -121,7 +121,8 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { if_chain! { if !ret_expr.span.from_expansion(); // Check if a function call. - if let ExprKind::Call(func, [arg]) = ret_expr.kind; + if let ExprKind::Call(func, args) = ret_expr.kind; + if let [arg] = args.as_slice(); if is_res_lang_ctor(cx, path_res(cx, func), lang_item); // Make sure the function argument does not contain a return expression. if !contains_return(arg); diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 0e526c216beea..fc24dcbe456f7 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -53,7 +53,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { match expr.kind { hir::ExprKind::Match(res, _, _) if is_try(cx, expr).is_some() => { - if let hir::ExprKind::Call(func, [ref arg_0, ..]) = res.kind { + if let hir::ExprKind::Call(func, args) = res.kind + && let [ref arg_0, ..] = args.as_slice() + { if matches!( func.kind, hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..)) @@ -79,7 +81,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { /// waited on. Otherwise return None. fn try_remove_await<'a>(expr: &'a hir::Expr<'a>) -> Option<&hir::Expr<'a>> { if let hir::ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind { - if let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind { + if let hir::ExprKind::Call(func, args) = expr.kind + && let [ref arg_0, ..] = args.as_slice() + { if matches!( func.kind, hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..)) diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 8ea5475fb2527..e795b44e1aefb 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -312,7 +312,7 @@ fn check_path(cx: &LateContext<'_>, path: &Path<'_>) { } fn lint_path_to_variant(cx: &LateContext<'_>, path: &Path<'_>) { - if let [.., self_seg, _variant] = path.segments { + if let [.., self_seg, _variant] = path.segments.as_slice() { let span = path .span .with_hi(self_seg.args().span_ext().unwrap_or(self_seg.ident.span).hi()); diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index ddbe6b2c7904d..c9e344f38c663 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -58,7 +58,9 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { let (ExprKind::Ret(Some(e)) | ExprKind::Break(_, Some(e))) = arms[0].body.kind else { return }; - if let ExprKind::Call(_, [arg, ..]) = e.kind { + if let ExprKind::Call(_, args) = e.kind + && let [arg, ..] = args.as_slice() + { self.try_desugar_arm.push(arg.hir_id); } }, @@ -134,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { } }, - ExprKind::Call(path, [arg]) => { + ExprKind::Call(path, args) if let [arg] = args.as_slice() => { if_chain! { if let ExprKind::Path(ref qpath) = path.kind; if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id(); diff --git a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs index bd5be0c9d7eda..0df2c6de5b7d2 100644 --- a/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs +++ b/src/tools/clippy/clippy_lints/src/vec_init_then_push.rs @@ -179,7 +179,7 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush { if self.searcher.is_none() && let ExprKind::Assign(left, right, _) = expr.kind && let ExprKind::Path(QPath::Resolved(None, path)) = left.kind - && let [name] = &path.segments + && let [name] = &path.segments.as_slice() && let Res::Local(id) = path.res && !in_external_macro(cx.sess(), expr.span) && let Some(init) = get_vec_init_kind(cx, right) @@ -201,7 +201,8 @@ impl<'tcx> LateLintPass<'tcx> for VecInitThenPush { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if let Some(searcher) = self.searcher.take() { if let StmtKind::Expr(expr) | StmtKind::Semi(expr) = stmt.kind - && let ExprKind::MethodCall(name, self_arg, [_], _) = expr.kind + && let ExprKind::MethodCall(name, self_arg, args, _) = expr.kind + && let [_] = args.as_slice() && path_to_local_id(self_arg, searcher.local_id) && name.ident.as_str() == "push" { diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index d3a6929f67e2c..666dd537bdd47 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -119,10 +119,12 @@ fn expr_search_pat(tcx: TyCtxt<'_>, e: &Expr<'_>) -> (Pat, Pat) { ExprKind::Unary(UnOp::Neg, e) => (Pat::Str("-"), expr_search_pat(tcx, e).1), ExprKind::Lit(ref lit) => lit_search_pat(&lit.node), ExprKind::Array(_) | ExprKind::Repeat(..) => (Pat::Str("["), Pat::Str("]")), - ExprKind::Call(e, []) | ExprKind::MethodCall(_, e, [], _) => (expr_search_pat(tcx, e).0, Pat::Str("(")), - ExprKind::Call(first, [.., last]) - | ExprKind::MethodCall(_, first, [.., last], _) - | ExprKind::Binary(_, first, last) + ExprKind::Call(e, args) | ExprKind::MethodCall(_, e, args, _) + if args.is_empty() => (expr_search_pat(tcx, e).0, Pat::Str("(")), + ExprKind::Call(first, args) + | ExprKind::MethodCall(_, first, args, _) + if let [.., last] = args.as_slice() => (expr_search_pat(tcx, first).0, expr_search_pat(tcx, last).1), + ExprKind::Binary(_, first, last) | ExprKind::Tup([first, .., last]) | ExprKind::Assign(first, last, _) | ExprKind::AssignOp(_, first, last) => (expr_search_pat(tcx, first).0, expr_search_pat(tcx, last).1), diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs index 50bef3709309d..6ca249b5b4e82 100644 --- a/src/tools/clippy/clippy_utils/src/higher.rs +++ b/src/tools/clippy/clippy_utils/src/higher.rs @@ -33,12 +33,14 @@ impl<'tcx> ForLoop<'tcx> { if_chain! { if let hir::ExprKind::DropTemps(e) = expr.kind; if let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind; - if let hir::ExprKind::Call(_, [arg]) = iterexpr.kind; + if let hir::ExprKind::Call(_, args) = iterexpr.kind; + if let [arg] = args.as_slice(); if let hir::ExprKind::Loop(block, ..) = arm.body.kind; if let [stmt] = block.stmts; if let hir::StmtKind::Expr(e) = stmt.kind; if let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind; - if let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind; + if let hir::PatKind::Struct(_, fields, _) = some_arm.pat.kind; + if let [field] = fields.as_slice(); then { return Some(Self { pat: field.pat, @@ -287,7 +289,8 @@ impl<'a> VecArgs<'a> { Some(VecArgs::Repeat(&args[0], &args[1])) } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 { // `vec![a, b, c]` case - if let hir::ExprKind::Call(_, [arg]) = &args[0].kind + if let hir::ExprKind::Call(_, inner_args) = &args[0].kind + && let [arg] = inner_args.as_slice() && let hir::ExprKind::Array(args) = arg.kind { Some(VecArgs::Vec(args)) } else { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 29830557a4454..025f7f119ecf3 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2,6 +2,7 @@ #![feature(box_patterns)] #![feature(let_chains)] #![feature(lint_reasons)] +#![feature(if_let_guard)] #![feature(never_type)] #![feature(once_cell)] #![feature(rustc_private)] @@ -81,6 +82,7 @@ use if_chain::if_chain; use rustc_ast::ast::{self, LitKind}; use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::thin_slice::ThinSlice; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; @@ -856,8 +858,8 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { false } }, - ExprKind::Call(repl_func, []) => is_default_equivalent_call(cx, repl_func), - ExprKind::Call(from_func, [ref arg]) => is_default_equivalent_from(cx, from_func, arg), + ExprKind::Call(repl_func, args) if args.is_empty() => is_default_equivalent_call(cx, repl_func), + ExprKind::Call(from_func, args) if let [ref arg] = args.as_slice() => is_default_equivalent_from(cx, from_func, arg), ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone), ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])), _ => false, @@ -1173,7 +1175,7 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<' } /// Arguments of a method: the receiver and all the additional arguments. -pub type MethodArguments<'tcx> = Vec<(&'tcx Expr<'tcx>, &'tcx [Expr<'tcx>])>; +pub type MethodArguments<'tcx> = Vec<(&'tcx Expr<'tcx>, &'tcx ThinSlice>)>; /// Returns the method names and argument list of nested method call expressions that make up /// `expr`. method/span lists are sorted with the most recent call first. @@ -1206,7 +1208,7 @@ pub fn method_calls<'tcx>(expr: &'tcx Expr<'tcx>, max_depth: usize) -> (Vec(expr: &'a Expr<'_>, methods: &[&str]) -> Option, &'a [Expr<'a>])>> { +pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option> { let mut current = expr; let mut matched = Vec::with_capacity(methods.len()); for method_name in methods.iter().rev() { diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs index c0e32068ecacc..43e0eedc73fb9 100644 --- a/src/tools/clippy/clippy_utils/src/macros.rs +++ b/src/tools/clippy/clippy_utils/src/macros.rs @@ -231,7 +231,8 @@ pub enum PanicExpn<'a> { impl<'a> PanicExpn<'a> { pub fn parse(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option { - let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else { return None }; + let ExprKind::Call(callee, args) = &expr.kind else { return None }; + let [arg, rest @ ..] = args.as_slice() else { return None }; let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else { return None }; let result = match path.segments.last().unwrap().ident.as_str() { "panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty, @@ -252,7 +253,8 @@ impl<'a> PanicExpn<'a> { // `msg_arg` is either `None` (no custom message) or `Some(format_args!(..))` (custom message) let msg_arg = &rest[2]; match msg_arg.kind { - ExprKind::Call(_, [fmt_arg]) => Self::Format(FormatArgsExpn::parse(cx, fmt_arg)?), + ExprKind::Call(_, args) + if let [fmt_arg] = args.as_slice() => Self::Format(FormatArgsExpn::parse(cx, fmt_arg)?), _ => Self::Empty, } }, @@ -548,7 +550,8 @@ impl<'tcx> FormatArgsValues<'tcx> { if expr.span.ctxt() == args.span.ctxt() { // ArgumentV1::new_() // ArgumentV1::from_usize() - if let ExprKind::Call(callee, [val]) = expr.kind + if let ExprKind::Call(callee, args) = expr.kind + && let [val] = args.as_slice() && let ExprKind::Path(QPath::TypeRelative(ty, _)) = callee.kind && let TyKind::Path(QPath::LangItem(LangItem::FormatArgument, _, _)) = ty.kind { @@ -617,7 +620,8 @@ impl<'tcx> Visitor<'tcx> for ParamPosition { fn parse_count(expr: &Expr<'_>) -> Option { // <::core::fmt::rt::v1::Count>::Param(1usize), - if let ExprKind::Call(ctor, [val]) = expr.kind + if let ExprKind::Call(ctor, args) = expr.kind + && let [val] = args.as_slice() && let ExprKind::Path(QPath::TypeRelative(_, path)) = ctor.kind && path.ident.name == sym::Param && let ExprKind::Lit(lit) = &val.kind @@ -639,7 +643,7 @@ fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option FormatArgsExpn<'tcx> { // ::core::fmt::Arguments::new_const(pieces) // ::core::fmt::Arguments::new_v1(pieces, args) // ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg) - if let ExprKind::Call(callee, [pieces, rest @ ..]) = expr.kind + if let ExprKind::Call(callee, args) = expr.kind + && let [pieces, rest @ ..] = args.as_slice() && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind && let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind && matches!(seg.ident.as_str(), "new_const" | "new_v1" | "new_v1_formatted") diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs index 88837d8a143ed..8d6e37569bcb1 100644 --- a/src/tools/clippy/clippy_utils/src/ptr.rs +++ b/src/tools/clippy/clippy_utils/src/ptr.rs @@ -32,7 +32,8 @@ fn extract_clone_suggestions<'tcx>( ) -> Option)>> { let mut spans = Vec::new(); for_each_expr(body, |e| { - if let ExprKind::MethodCall(seg, recv, [], _) = e.kind + if let ExprKind::MethodCall(seg, recv, args, _) = e.kind + && args.is_empty() && path_to_local_id(recv, id) { if seg.ident.as_str() == "capacity" { diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index a5a4a921d94ec..7beddd3420fa8 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -943,7 +943,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { }, // item is used in a call // i.e.: `Call`: `|x| please(x)` or `MethodCall`: `|x| [1, 2, 3].contains(x)` - ExprKind::Call(_, [call_args @ ..]) | ExprKind::MethodCall(_, _, [call_args @ ..], _) => { + ExprKind::Call(_, call_args) | ExprKind::MethodCall(_, _, call_args, _) => { let expr = self.cx.tcx.hir().expect_expr(cmt.hir_id); let arg_ty_kind = self.cx.typeck_results().expr_ty(expr).kind();