diff options
204 files changed, 2751 insertions, 956 deletions
diff --git a/compiler/rustc_arena/src/tests.rs b/compiler/rustc_arena/src/tests.rs index ad61464343a..49a070badc6 100644 --- a/compiler/rustc_arena/src/tests.rs +++ b/compiler/rustc_arena/src/tests.rs @@ -52,19 +52,15 @@ fn test_arena_alloc_nested() { impl<'a> Wrap<'a> { fn alloc_inner<F: Fn() -> Inner>(&self, f: F) -> &Inner { - let r: &EI<'_> = self.0.alloc(EI::I(f())); - if let &EI::I(ref i) = r { - i - } else { - panic!("mismatch"); + match self.0.alloc(EI::I(f())) { + EI::I(i) => i, + _ => panic!("mismatch"), } } fn alloc_outer<F: Fn() -> Outer<'a>>(&self, f: F) -> &Outer<'_> { - let r: &EI<'_> = self.0.alloc(EI::O(f())); - if let &EI::O(ref o) = r { - o - } else { - panic!("mismatch"); + match self.0.alloc(EI::O(f())) { + EI::O(o) => o, + _ => panic!("mismatch"), } } } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 54bd25d6471..28072f153a4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1376,7 +1376,7 @@ pub enum ExprKind { /// Conditionless loop (can be exited with `break`, `continue`, or `return`). /// /// `'label: loop { block }` - Loop(P<Block>, Option<Label>), + Loop(P<Block>, Option<Label>, Span), /// A `match` block. Match(P<Expr>, Vec<Arm>), /// A closure (e.g., `move |a, b, c| a + b + c`). diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 2f7c7a29492..3e012953115 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -618,9 +618,12 @@ impl MetaItemKind { }) => MetaItemKind::list_from_tokens(tokens.clone()), AttrArgs::Delimited(..) => None, AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind { - ast::ExprKind::Lit(token_lit) => Some(MetaItemKind::NameValue( - Lit::from_token_lit(token_lit, expr.span).expect("token_lit in from_attr_args"), - )), + ast::ExprKind::Lit(token_lit) => { + // Turn failures to `None`, we'll get parse errors elsewhere. + Lit::from_token_lit(token_lit, expr.span) + .ok() + .map(|lit| MetaItemKind::NameValue(lit)) + } _ => None, }, AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())), diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4e1dcb2842f..a5b24c403dd 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1355,9 +1355,10 @@ pub fn noop_visit_expr<T: MutVisitor>( vis.visit_block(body); visit_opt(label, |label| vis.visit_label(label)); } - ExprKind::Loop(body, label) => { + ExprKind::Loop(body, label, span) => { vis.visit_block(body); visit_opt(label, |label| vis.visit_label(label)); + vis.visit_span(span); } ExprKind::Match(expr, arms) => { vis.visit_expr(expr); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 5c69e535212..c528118be08 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -824,7 +824,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { visitor.visit_expr(subexpression); visitor.visit_block(block); } - ExprKind::Loop(block, opt_label) => { + ExprKind::Loop(block, opt_label, _) => { walk_list!(visitor, visit_label, opt_label); visitor.visit_block(block); } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index db0d8b08a94..2a0338adc9c 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -123,7 +123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .operands .iter() .map(|(op, op_sp)| { - let lower_reg = |reg| match reg { + let lower_reg = |®: &_| match reg { InlineAsmRegOrRegClass::Reg(reg) => { asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch { asm::InlineAsmReg::parse(asm_arch, reg).unwrap_or_else(|error| { @@ -152,32 +152,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } }; - let op = match *op { - InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In { + let op = match op { + InlineAsmOperand::In { reg, expr } => hir::InlineAsmOperand::In { reg: lower_reg(reg), expr: self.lower_expr(expr), }, - InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out { + InlineAsmOperand::Out { reg, late, expr } => hir::InlineAsmOperand::Out { reg: lower_reg(reg), - late, + late: *late, expr: expr.as_ref().map(|expr| self.lower_expr(expr)), }, - InlineAsmOperand::InOut { reg, late, ref expr } => { - hir::InlineAsmOperand::InOut { - reg: lower_reg(reg), - late, - expr: self.lower_expr(expr), - } - } - InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => { + InlineAsmOperand::InOut { reg, late, expr } => hir::InlineAsmOperand::InOut { + reg: lower_reg(reg), + late: *late, + expr: self.lower_expr(expr), + }, + InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => { hir::InlineAsmOperand::SplitInOut { reg: lower_reg(reg), - late, + late: *late, in_expr: self.lower_expr(in_expr), out_expr: out_expr.as_ref().map(|expr| self.lower_expr(expr)), } } - InlineAsmOperand::Const { ref anon_const } => { + InlineAsmOperand::Const { anon_const } => { if !self.tcx.features().asm_const { feature_err( &sess.parse_sess, @@ -191,7 +189,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { anon_const: self.lower_anon_const(anon_const), } } - InlineAsmOperand::Sym { ref sym } => { + InlineAsmOperand::Sym { sym } => { let static_def_id = self .resolver .get_partial_res(sym.id) @@ -347,7 +345,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { skip = true; let idx2 = *o.get(); - let &(ref op2, op_sp2) = &operands[idx2]; + let (ref op2, op_sp2) = operands[idx2]; let Some(asm::InlineAsmRegOrRegClass::Reg(reg2)) = op2.reg() else { unreachable!(); }; diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 12a0cc0d255..d310f72f7a3 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -31,8 +31,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new(); let mut expr = None; while let [s, tail @ ..] = ast_stmts { - match s.kind { - StmtKind::Local(ref local) => { + match &s.kind { + StmtKind::Local(local) => { let hir_id = self.lower_node_id(s.id); let local = self.lower_local(local); self.alias_attrs(hir_id, local.hir_id); @@ -40,7 +40,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let span = self.lower_span(s.span); stmts.push(hir::Stmt { hir_id, kind, span }); } - StmtKind::Item(ref it) => { + StmtKind::Item(it) => { stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map( |(i, item_id)| { let hir_id = match i { @@ -53,7 +53,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }, )); } - StmtKind::Expr(ref e) => { + StmtKind::Expr(e) => { let e = self.lower_expr(e); if tail.is_empty() { expr = Some(e); @@ -65,7 +65,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { stmts.push(hir::Stmt { hir_id, kind, span }); } } - StmtKind::Semi(ref e) => { + StmtKind::Semi(e) => { let e = self.lower_expr(e); let hir_id = self.lower_node_id(s.id); self.alias_attrs(hir_id, e.hir_id); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 6855344356a..3c217c0249a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -31,20 +31,20 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { ensure_sufficient_stack(|| { - let kind = match e.kind { - ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)), - ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), - ExprKind::ConstBlock(ref anon_const) => { + let kind = match &e.kind { + ExprKind::Box(inner) => hir::ExprKind::Box(self.lower_expr(inner)), + ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), + ExprKind::ConstBlock(anon_const) => { let anon_const = self.lower_anon_const(anon_const); hir::ExprKind::ConstBlock(anon_const) } - ExprKind::Repeat(ref expr, ref count) => { + ExprKind::Repeat(expr, count) => { let expr = self.lower_expr(expr); let count = self.lower_array_length(count); hir::ExprKind::Repeat(expr, count) } - ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), - ExprKind::Call(ref f, ref args) => { + ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), + ExprKind::Call(f, args) => { if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) { if let [inner] = &args[..] && e.attrs.len() == 1 { let kind = hir::ExprKind::Box(self.lower_expr(&inner)); @@ -61,7 +61,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Call(f, self.lower_exprs(args)) } } - ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, span }) => { + ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => { let hir_seg = self.arena.alloc(self.lower_path_segment( e.span, seg, @@ -72,92 +72,88 @@ impl<'hir> LoweringContext<'_, 'hir> { let receiver = self.lower_expr(receiver); let args = self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x))); - hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span)) + hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(*span)) } - ExprKind::Binary(binop, ref lhs, ref rhs) => { - let binop = self.lower_binop(binop); + ExprKind::Binary(binop, lhs, rhs) => { + let binop = self.lower_binop(*binop); let lhs = self.lower_expr(lhs); let rhs = self.lower_expr(rhs); hir::ExprKind::Binary(binop, lhs, rhs) } - ExprKind::Unary(op, ref ohs) => { - let op = self.lower_unop(op); + ExprKind::Unary(op, ohs) => { + let op = self.lower_unop(*op); let ohs = self.lower_expr(ohs); hir::ExprKind::Unary(op, ohs) } ExprKind::Lit(token_lit) => { - let lit_kind = match LitKind::from_token_lit(token_lit) { + let lit_kind = match LitKind::from_token_lit(*token_lit) { Ok(lit_kind) => lit_kind, Err(err) => { - report_lit_error(&self.tcx.sess.parse_sess, err, token_lit, e.span); + report_lit_error(&self.tcx.sess.parse_sess, err, *token_lit, e.span); LitKind::Err } }; hir::ExprKind::Lit(respan(self.lower_span(e.span), lit_kind)) } - ExprKind::IncludedBytes(ref bytes) => hir::ExprKind::Lit(respan( + ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan( self.lower_span(e.span), LitKind::ByteStr(bytes.clone()), )), - ExprKind::Cast(ref expr, ref ty) => { + ExprKind::Cast(expr, ty) => { let expr = self.lower_expr(expr); let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Cast(expr, ty) } - ExprKind::Type(ref expr, ref ty) => { + ExprKind::Type(expr, ty) => { let expr = self.lower_expr(expr); let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); hir::ExprKind::Type(expr, ty) } - ExprKind::AddrOf(k, m, ref ohs) => { + ExprKind::AddrOf(k, m, ohs) => { let ohs = self.lower_expr(ohs); - hir::ExprKind::AddrOf(k, m, ohs) + hir::ExprKind::AddrOf(*k, *m, ohs) } - ExprKind::Let(ref pat, ref scrutinee, span) => { + ExprKind::Let(pat, scrutinee, span) => { hir::ExprKind::Let(self.arena.alloc(hir::Let { hir_id: self.next_id(), - span: self.lower_span(span), + span: self.lower_span(*span), pat: self.lower_pat(pat), ty: None, init: self.lower_expr(scrutinee), })) } - ExprKind::If(ref cond, ref then, ref else_opt) => { + ExprKind::If(cond, then, else_opt) => { self.lower_expr_if(cond, then, else_opt.as_deref()) } - ExprKind::While(ref cond, ref body, opt_label) => { - self.with_loop_scope(e.id, |this| { - let span = - this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); - this.lower_expr_while_in_loop_scope(span, cond, body, opt_label) - }) - } - ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| { + ExprKind::While(cond, body, opt_label) => self.with_loop_scope(e.id, |this| { + let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); + this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label) + }), + ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| { hir::ExprKind::Loop( this.lower_block(body, false), - this.lower_label(opt_label), + this.lower_label(*opt_label), hir::LoopSource::Loop, - DUMMY_SP, + this.lower_span(*span), ) }), - ExprKind::TryBlock(ref body) => self.lower_expr_try_block(body), - ExprKind::Match(ref expr, ref arms) => hir::ExprKind::Match( + ExprKind::TryBlock(body) => self.lower_expr_try_block(body), + ExprKind::Match(expr, arms) => hir::ExprKind::Match( self.lower_expr(expr), self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))), hir::MatchSource::Normal, ), - ExprKind::Async(capture_clause, closure_node_id, ref block) => self - .make_async_expr( - capture_clause, - closure_node_id, - None, - block.span, - hir::AsyncGeneratorKind::Block, - |this| this.with_new_scopes(|this| this.lower_block_expr(block)), - ), - ExprKind::Await(ref expr) => { + ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr( + *capture_clause, + *closure_node_id, + None, + block.span, + hir::AsyncGeneratorKind::Block, + |this| this.with_new_scopes(|this| this.lower_block_expr(block)), + ), + ExprKind::Await(expr) => { let dot_await_span = if expr.span.hi() < e.span.hi() { let span_with_whitespace = self .tcx @@ -173,65 +169,63 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_expr_await(dot_await_span, expr) } ExprKind::Closure(box Closure { - ref binder, + binder, capture_clause, asyncness, movability, - ref fn_decl, - ref body, + fn_decl, + body, fn_decl_span, }) => { if let Async::Yes { closure_id, .. } = asyncness { self.lower_expr_async_closure( binder, - capture_clause, + *capture_clause, e.id, - closure_id, + *closure_id, fn_decl, body, - fn_decl_span, + *fn_decl_span, ) } else { self.lower_expr_closure( binder, - capture_clause, + *capture_clause, e.id, - movability, + *movability, fn_decl, body, - fn_decl_span, + *fn_decl_span, ) } } - ExprKind::Block(ref blk, opt_label) => { - let opt_label = self.lower_label(opt_label); + ExprKind::Block(blk, opt_label) => { + let opt_label = self.lower_label(*opt_label); hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label) } - ExprKind::Assign(ref el, ref er, span) => { - self.lower_expr_assign(el, er, span, e.span) - } - ExprKind::AssignOp(op, ref el, ref er) => hir::ExprKind::AssignOp( - self.lower_binop(op), + ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span), + ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp( + self.lower_binop(*op), self.lower_expr(el), self.lower_expr(er), ), - ExprKind::Field(ref el, ident) => { - hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(ident)) + ExprKind::Field(el, ident) => { + hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(*ident)) } - ExprKind::Index(ref el, ref er) => { + ExprKind::Index(el, er) => { hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er)) } - ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => { + ExprKind::Range(Some(e1), Some(e2), RangeLimits::Closed) => { self.lower_expr_range_closed(e.span, e1, e2) } - ExprKind::Range(ref e1, ref e2, lims) => { - self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims) + ExprKind::Range(e1, e2, lims) => { + self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims) } ExprKind::Underscore => { self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span }); hir::ExprKind::Err } - ExprKind::Path(ref qself, ref path) => { + ExprKind::Path(qself, path) => { let qpath = self.lower_qpath( e.id, qself, @@ -241,22 +235,22 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ExprKind::Path(qpath) } - ExprKind::Break(opt_label, ref opt_expr) => { + ExprKind::Break(opt_label, opt_expr) => { let opt_expr = opt_expr.as_ref().map(|x| self.lower_expr(x)); - hir::ExprKind::Break(self.lower_jump_destination(e.id, opt_label), opt_expr) + hir::ExprKind::Break(self.lower_jump_destination(e.id, *opt_label), opt_expr) } ExprKind::Continue(opt_label) => { - hir::ExprKind::Continue(self.lower_jump_destination(e.id, opt_label)) + hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label)) } - ExprKind::Ret(ref e) => { + ExprKind::Ret(e) => { let e = e.as_ref().map(|x| self.lower_expr(x)); hir::ExprKind::Ret(e) } - ExprKind::Yeet(ref sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()), - ExprKind::InlineAsm(ref asm) => { + ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()), + ExprKind::InlineAsm(asm) => { hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm)) } - ExprKind::Struct(ref se) => { + ExprKind::Struct(se) => { let rest = match &se.rest { StructRest::Base(e) => Some(self.lower_expr(e)), StructRest::Rest(sp) => { @@ -278,10 +272,10 @@ impl<'hir> LoweringContext<'_, 'hir> { rest, ) } - ExprKind::Yield(ref opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), + ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), ExprKind::Err => hir::ExprKind::Err, - ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr), - ExprKind::Paren(ref ex) => { + ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr), + ExprKind::Paren(ex) => { let mut ex = self.lower_expr_mut(ex); // Include parens in span, but only if it is a super-span. if e.span.contains(ex.span) { @@ -306,8 +300,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // Desugar `ExprForLoop` // from: `[opt_ident]: for <pat> in <head> <body>` - ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => { - return self.lower_expr_for(e, pat, head, body, opt_label); + ExprKind::ForLoop(pat, head, body, opt_label) => { + return self.lower_expr_for(e, pat, head, body, *opt_label); } ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span), }; @@ -358,7 +352,7 @@ impl<'hir> LoweringContext<'_, 'hir> { args: Vec<AstP<Expr>>, legacy_args_idx: &[usize], ) -> hir::ExprKind<'hir> { - let ExprKind::Path(None, ref mut path) = f.kind else { + let ExprKind::Path(None, path) = &mut f.kind else { unreachable!(); }; @@ -552,10 +546,10 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> { let pat = self.lower_pat(&arm.pat); let guard = arm.guard.as_ref().map(|cond| { - if let ExprKind::Let(ref pat, ref scrutinee, span) = cond.kind { + if let ExprKind::Let(pat, scrutinee, span) = &cond.kind { hir::Guard::IfLet(self.arena.alloc(hir::Let { hir_id: self.next_id(), - span: self.lower_span(span), + span: self.lower_span(*span), pat: self.lower_pat(pat), ty: None, init: self.lower_expr(scrutinee), @@ -961,8 +955,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> (hir::ClosureBinder, &'c [GenericParam]) { let (binder, params) = match binder { ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]), - &ClosureBinder::For { span, ref generic_params } => { - let span = self.lower_span(span); + ClosureBinder::For { span, generic_params } => { + let span = self.lower_span(*span); (hir::ClosureBinder::For { span }, &**generic_params) } }; diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 3a0e5f55ec1..695a698e022 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -145,7 +145,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_item(&mut self, i: &'hir Item<'hir>) { debug_assert_eq!(i.owner_id, self.owner); self.with_parent(i.hir_id(), |this| { - if let ItemKind::Struct(ref struct_def, _) = i.kind { + if let ItemKind::Struct(struct_def, _) = &i.kind { // If this is a tuple or unit-like struct, register the constructor. if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def)); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 99b3ac864dd..a1941b5d8d3 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -142,7 +142,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { // This is used to track which lifetimes have already been defined, // and which need to be replicated when lowering an async fn. match parent_hir.node().expect_item().kind { - hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => { + hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { lctx.is_in_trait_impl = of_trait.is_some(); } _ => {} @@ -178,7 +178,7 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { let mut node_ids = smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }]; - if let ItemKind::Use(ref use_tree) = &i.kind { + if let ItemKind::Use(use_tree) = &i.kind { self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); } node_ids @@ -190,8 +190,8 @@ impl<'hir> LoweringContext<'_, 'hir> { base_id: NodeId, vec: &mut SmallVec<[hir::ItemId; 1]>, ) { - match tree.kind { - UseTreeKind::Nested(ref nested_vec) => { + match &tree.kind { + UseTreeKind::Nested(nested_vec) => { for &(ref nested, id) in nested_vec { vec.push(hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, @@ -201,8 +201,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } UseTreeKind::Glob => {} UseTreeKind::Simple(_, id1, id2) => { - for (_, &id) in - iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) + for (_, id) in + iter::zip(self.expect_full_res_from_use(base_id).skip(1), [*id1, *id2]) { vec.push(hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(id) }, @@ -238,26 +238,26 @@ impl<'hir> LoweringContext<'_, 'hir> { vis_span: Span, i: &ItemKind, ) -> hir::ItemKind<'hir> { - match *i { - ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(orig_name), - ItemKind::Use(ref use_tree) => { + match i { + ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(*orig_name), + ItemKind::Use(use_tree) => { // Start with an empty prefix. let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None }; self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) } - ItemKind::Static(ref t, m, ref e) => { + ItemKind::Static(t, m, e) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); - hir::ItemKind::Static(ty, m, body_id) + hir::ItemKind::Static(ty, *m, body_id) } - ItemKind::Const(_, ref t, ref e) => { + ItemKind::Const(_, t, e) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); hir::ItemKind::Const(ty, body_id) } ItemKind::Fn(box Fn { - sig: FnSig { ref decl, header, span: fn_sig_span }, - ref generics, - ref body, + sig: FnSig { decl, header, span: fn_sig_span }, + generics, + body, .. }) => { self.with_new_scopes(|this| { @@ -274,37 +274,30 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, id, &mut itctx, |this| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, Some(id), fn_sig_span, FnDeclKind::Fn, ret_id) + this.lower_fn_decl(&decl, Some(id), *fn_sig_span, FnDeclKind::Fn, ret_id) }); let sig = hir::FnSig { decl, - header: this.lower_fn_header(header), - span: this.lower_span(fn_sig_span), + header: this.lower_fn_header(*header), + span: this.lower_span(*fn_sig_span), }; hir::ItemKind::Fn(sig, generics, body_id) }) } - ItemKind::Mod(_, ref mod_kind) => match mod_kind { + ItemKind::Mod(_, mod_kind) => match mod_kind { ModKind::Loaded(items, _, spans) => { hir::ItemKind::Mod(self.lower_mod(items, spans)) } ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), }, - ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod { + ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod { abi: fm.abi.map_or(abi::Abi::FALLBACK, |abi| self.lower_abi(abi)), items: self .arena .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), }, - ItemKind::GlobalAsm(ref asm) => { - hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)) - } - ItemKind::TyAlias(box TyAlias { - ref generics, - where_clauses, - ty: Some(ref ty), - .. - }) => { + ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)), + ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: Some(ty), .. }) => { // We lower // // type Foo = impl Trait @@ -314,7 +307,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // type Foo = Foo1 // opaque type Foo1: Trait let mut generics = generics.clone(); - add_ty_alias_where_clause(&mut generics, where_clauses, true); + add_ty_alias_where_clause(&mut generics, *where_clauses, true); let (generics, ty) = self.lower_generics( &generics, id, @@ -323,9 +316,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::TyAlias(ty, generics) } - ItemKind::TyAlias(box TyAlias { - ref generics, ref where_clauses, ty: None, .. - }) => { + ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty: None, .. }) => { let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, true); let (generics, ty) = self.lower_generics( @@ -336,7 +327,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::TyAlias(ty, generics) } - ItemKind::Enum(ref enum_definition, ref generics) => { + ItemKind::Enum(enum_definition, generics) => { let (generics, variants) = self.lower_generics( generics, id, @@ -349,7 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Enum(hir::EnumDef { variants }, generics) } - ItemKind::Struct(ref struct_def, ref generics) => { + ItemKind::Struct(struct_def, generics) => { let (generics, struct_def) = self.lower_generics( generics, id, @@ -358,7 +349,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Struct(struct_def, generics) } - ItemKind::Union(ref vdata, ref generics) => { + ItemKind::Union(vdata, generics) => { let (generics, vdata) = self.lower_generics( generics, id, @@ -372,10 +363,10 @@ impl<'hir> LoweringContext<'_, 'hir> { polarity, defaultness, constness, - generics: ref ast_generics, - of_trait: ref trait_ref, - self_ty: ref ty, - items: ref impl_items, + generics: ast_generics, + of_trait: trait_ref, + self_ty: ty, + items: impl_items, }) => { // Lower the "impl header" first. This ordering is important // for in-band lifetimes! Consider `'a` here: @@ -413,30 +404,24 @@ impl<'hir> LoweringContext<'_, 'hir> { // `defaultness.has_value()` is never called for an `impl`, always `true` in order // to not cause an assertion failure inside the `lower_defaultness` function. let has_val = true; - let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val); + let (defaultness, defaultness_span) = self.lower_defaultness(*defaultness, has_val); let polarity = match polarity { ImplPolarity::Positive => ImplPolarity::Positive, - ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)), + ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)), }; hir::ItemKind::Impl(self.arena.alloc(hir::Impl { - unsafety: self.lower_unsafety(unsafety), + unsafety: self.lower_unsafety(*unsafety), polarity, defaultness, defaultness_span, - constness: self.lower_constness(constness), + constness: self.lower_constness(*constness), generics, of_trait: trait_ref, self_ty: lowered_ty, items: new_impl_items, })) } - ItemKind::Trait(box Trait { - is_auto, - unsafety, - ref generics, - ref bounds, - ref items, - }) => { + ItemKind::Trait(box Trait { is_auto, unsafety, generics, bounds, items }) => { let (generics, (unsafety, items, bounds)) = self.lower_generics( generics, id, @@ -449,13 +434,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), ); - let unsafety = this.lower_unsafety(unsafety); + let unsafety = this.lower_unsafety(*unsafety); (unsafety, items, bounds) }, ); - hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, items) + hir::ItemKind::Trait(*is_auto, unsafety, generics, bounds, items) } - ItemKind::TraitAlias(ref generics, ref bounds) => { + ItemKind::TraitAlias(generics, bounds) => { let (generics, bounds) = self.lower_generics( generics, id, @@ -469,10 +454,10 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::TraitAlias(generics, bounds) } - ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => { + ItemKind::MacroDef(MacroDef { body, macro_rules }) => { let body = P(self.lower_delim_args(body)); let macro_kind = self.resolver.decl_macro_kind(self.local_def_id(id)); - hir::ItemKind::Macro(ast::MacroDef { body, macro_rules }, macro_kind) + hir::ItemKind::Macro(ast::MacroDef { body, macro_rules: *macro_rules }, macro_kind) } ItemKind::MacCall(..) => { panic!("`TyMac` should have been expanded by now") @@ -664,8 +649,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let item = hir::ForeignItem { owner_id, ident: self.lower_ident(i.ident), - kind: match i.kind { - ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { + kind: match &i.kind { + ForeignItemKind::Fn(box Fn { sig, generics, .. }) => { let fdec = &sig.decl; let mut itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = @@ -685,10 +670,10 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } - ForeignItemKind::Static(ref t, m, _) => { + ForeignItemKind::Static(t, m, _) => { let ty = self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); - hir::ForeignItemKind::Static(ty, m) + hir::ForeignItemKind::Static(ty, *m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), @@ -725,33 +710,33 @@ impl<'hir> LoweringContext<'_, 'hir> { parent_id: hir::HirId, vdata: &VariantData, ) -> hir::VariantData<'hir> { - match *vdata { - VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct( + match vdata { + VariantData::Struct(fields, recovered) => hir::VariantData::Struct( self.arena .alloc_from_iter(fields.iter().enumerate().map(|f| self.lower_field_def(f))), - recovered, + *recovered, ), - VariantData::Tuple(ref fields, id) => { - let ctor_id = self.lower_node_id(id); + VariantData::Tuple(fields, id) => { + let ctor_id = self.lower_node_id(*id); self.alias_attrs(ctor_id, parent_id); hir::VariantData::Tuple( self.arena.alloc_from_iter( fields.iter().enumerate().map(|f| self.lower_field_def(f)), ), ctor_id, - self.local_def_id(id), + self.local_def_id(*id), ) } VariantData::Unit(id) => { - let ctor_id = self.lower_node_id(id); + let ctor_id = self.lower_node_id(*id); self.alias_attrs(ctor_id, parent_id); - hir::VariantData::Unit(ctor_id, self.local_def_id(id)) + hir::VariantData::Unit(ctor_id, self.local_def_id(*id)) } } } fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> { - let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind { + let ty = if let TyKind::Path(qself, path) = &f.ty.kind { let t = self.lower_path_ty( &f.ty, qself, @@ -783,13 +768,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let hir_id = self.lower_node_id(i.id); let trait_item_def_id = hir_id.expect_owner(); - let (generics, kind, has_default) = match i.kind { - AssocItemKind::Const(_, ref ty, ref default) => { + let (generics, kind, has_default) = match &i.kind { + AssocItemKind::Const(_, ty, default) => { let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } - AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => { + AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => { let asyncness = sig.header.asyncness; let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( @@ -801,7 +786,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } - AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => { + AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => { let asyncness = sig.header.asyncness; let body_id = self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body)); @@ -814,15 +799,9 @@ impl<'hir> LoweringContext<'_, 'hir> { ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) } - AssocItemKind::Type(box TyAlias { - ref generics, - where_clauses, - ref bounds, - ref ty, - .. - }) => { + AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => { let mut generics = generics.clone(); - add_ty_alias_where_clause(&mut generics, where_clauses, false); + add_ty_alias_where_clause(&mut generics, *where_clauses, false); let (generics, kind) = self.lower_generics( &generics, i.id, @@ -1354,7 +1333,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and // where clauses for `?Sized`. for pred in &generics.where_clause.predicates { - let WherePredicate::BoundPredicate(ref bound_pred) = *pred else { + let WherePredicate::BoundPredicate(bound_pred) = pred else { continue; }; let compute_is_param = || { @@ -1515,11 +1494,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> { - match *pred { + match pred { WherePredicate::BoundPredicate(WhereBoundPredicate { - ref bound_generic_params, - ref bounded_ty, - ref bounds, + bound_generic_params, + bounded_ty, + bounds, span, }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { hir_id: self.next_id(), @@ -1532,29 +1511,27 @@ impl<'hir> LoweringContext<'_, 'hir> { &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) })), - span: self.lower_span(span), + span: self.lower_span(*span), origin: PredicateOrigin::WhereClause, }), - WherePredicate::RegionPredicate(WhereRegionPredicate { - ref lifetime, - ref bounds, - span, - }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { - span: self.lower_span(span), - lifetime: self.lower_lifetime(lifetime), - bounds: self.lower_param_bounds( - bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ), - in_where_clause: true, - }), - WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span }) => { + WherePredicate::RegionPredicate(WhereRegionPredicate { lifetime, bounds, span }) => { + hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { + span: self.lower_span(*span), + lifetime: self.lower_lifetime(lifetime), + bounds: self.lower_param_bounds( + bounds, + &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ), + in_where_clause: true, + }) + } + WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty: self .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), rhs_ty: self .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), - span: self.lower_span(span), + span: self.lower_span(*span), }) } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index bd1876d4284..d1666dfbf64 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -932,13 +932,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_attr_args(&self, args: &AttrArgs) -> AttrArgs { - match *args { + match args { AttrArgs::Empty => AttrArgs::Empty, - AttrArgs::Delimited(ref args) => AttrArgs::Delimited(self.lower_delim_args(args)), + AttrArgs::Delimited(args) => AttrArgs::Delimited(self.lower_delim_args(args)), // This is an inert key-value attribute - it will never be visible to macros // after it gets lowered to HIR. Therefore, we can extract literals to handle // nonterminals in `#[doc]` (e.g. `#[doc = $e]`). - AttrArgs::Eq(eq_span, AttrArgsEq::Ast(ref expr)) => { + AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => { // In valid code the value always ends up as a single literal. Otherwise, a dummy // literal suffices because the error is handled elsewhere. let lit = if let ExprKind::Lit(token_lit) = expr.kind { @@ -957,9 +957,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: DUMMY_SP, } }; - AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit)) + AttrArgs::Eq(*eq_span, AttrArgsEq::Hir(lit)) } - AttrArgs::Eq(_, AttrArgsEq::Hir(ref lit)) => { + AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => { unreachable!("in literal form when lowering mac args eq: {:?}", lit) } } @@ -987,12 +987,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint - let gen_args = if let Some(ref gen_args) = constraint.gen_args { + let gen_args = if let Some(gen_args) = &constraint.gen_args { let gen_args_ctor = match gen_args { - GenericArgs::AngleBracketed(ref data) => { + GenericArgs::AngleBracketed(data) => { self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0 } - GenericArgs::Parenthesized(ref data) => { + GenericArgs::Parenthesized(data) => { self.emit_bad_parenthesized_trait_in_assoc_ty(data); let aba = self.ast_arena.aba.alloc(data.as_angle_bracketed_args()); self.lower_angle_bracketed_parameter_data(aba, ParamMode::Explicit, itctx).0 @@ -1004,15 +1004,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let itctx_tait = &ImplTraitContext::TypeAliasesOpaqueTy; - let kind = match constraint.kind { - AssocConstraintKind::Equality { ref term } => { + let kind = match &constraint.kind { + AssocConstraintKind::Equality { term } => { let term = match term { - Term::Ty(ref ty) => self.lower_ty(ty, itctx).into(), - Term::Const(ref c) => self.lower_anon_const(c).into(), + Term::Ty(ty) => self.lower_ty(ty, itctx).into(), + Term::Const(c) => self.lower_anon_const(c).into(), }; hir::TypeBindingKind::Equality { term } } - AssocConstraintKind::Bound { ref bounds } => { + AssocConstraintKind::Bound { bounds } => { // Piggy-back on the `impl Trait` context to figure out the correct behavior. let (desugar_to_impl_trait, itctx) = match itctx { // We are in the return position: @@ -1122,7 +1122,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), ast::GenericArg::Type(ty) => { - match ty.kind { + match &ty.kind { TyKind::Infer if self.tcx.features().generic_arg_infer => { return GenericArg::Infer(hir::InferArg { hir_id: self.lower_node_id(ty.id), @@ -1133,7 +1133,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // parsing. We try to resolve that ambiguity by attempting resolution in both the // type and value namespaces. If we resolved the path in the value namespace, we // transform it into a generic const argument. - TyKind::Path(ref qself, ref path) => { + TyKind::Path(qself, path) => { if let Some(res) = self .resolver .get_partial_res(ty.id) @@ -1240,12 +1240,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> { - let kind = match t.kind { + let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => hir::TyKind::Err, - TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), - TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), - TyKind::Rptr(ref region, ref mt) => { + TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), + TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), + TyKind::Rptr(region, mt) => { let region = region.unwrap_or_else(|| { let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) = self.resolver.get_lifetime_res(t.id) @@ -1261,7 +1261,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime = self.lower_lifetime(®ion); hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) } - TyKind::BareFn(ref f) => { + TyKind::BareFn(f) => { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy { generic_params, @@ -1272,13 +1272,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })) } TyKind::Never => hir::TyKind::Never, - TyKind::Tup(ref tys) => hir::TyKind::Tup( + TyKind::Tup(tys) => hir::TyKind::Tup( self.arena.alloc_from_iter(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx))), ), - TyKind::Paren(ref ty) => { + TyKind::Paren(ty) => { return self.lower_ty_direct(ty, itctx); } - TyKind::Path(ref qself, ref path) => { + TyKind::Path(qself, path) => { return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx); } TyKind::ImplicitSelf => { @@ -1298,48 +1298,46 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), )) } - TyKind::Array(ref ty, ref length) => { + TyKind::Array(ty, length) => { hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) } - TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), - TyKind::TraitObject(ref bounds, kind) => { + TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), + TyKind::TraitObject(bounds, kind) => { let mut lifetime_bound = None; let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { let bounds = - this.arena.alloc_from_iter(bounds.iter().filter_map( - |bound| match *bound { - GenericBound::Trait( - ref ty, - TraitBoundModifier::None | TraitBoundModifier::MaybeConst, - ) => Some(this.lower_poly_trait_ref(ty, itctx)), - // `~const ?Bound` will cause an error during AST validation - // anyways, so treat it like `?Bound` as compilation proceeds. - GenericBound::Trait( - _, - TraitBoundModifier::Maybe | TraitBoundModifier::MaybeConstMaybe, - ) => None, - GenericBound::Outlives(ref lifetime) => { - if lifetime_bound.is_none() { - lifetime_bound = Some(this.lower_lifetime(lifetime)); - } - None + this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound { + GenericBound::Trait( + ty, + TraitBoundModifier::None | TraitBoundModifier::MaybeConst, + ) => Some(this.lower_poly_trait_ref(ty, itctx)), + // `~const ?Bound` will cause an error during AST validation + // anyways, so treat it like `?Bound` as compilation proceeds. + GenericBound::Trait( + _, + TraitBoundModifier::Maybe | TraitBoundModifier::MaybeConstMaybe, + ) => None, + GenericBound::Outlives(lifetime) => { + if lifetime_bound.is_none() { + lifetime_bound = Some(this.lower_lifetime(lifetime)); } - }, - )); + None + } + })); let lifetime_bound = lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); (bounds, lifetime_bound) }); - hir::TyKind::TraitObject(bounds, lifetime_bound, kind) + hir::TyKind::TraitObject(bounds, lifetime_bound, *kind) } - TyKind::ImplTrait(def_node_id, ref bounds) => { + TyKind::ImplTrait(def_node_id, bounds) => { let span = t.span; match itctx { ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self .lower_opaque_impl_trait( span, *origin, - def_node_id, + *def_node_id, bounds, *in_trait, itctx, @@ -1347,7 +1345,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait( span, hir::OpaqueTyOrigin::TyAlias, - def_node_id, + *def_node_id, bounds, false, itctx, @@ -1355,13 +1353,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Universal => { self.create_def( self.current_hir_id_owner.def_id, - def_node_id, + *def_node_id, DefPathData::ImplTrait, ); let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); let (param, bounds, path) = - self.lower_generic_and_bounds(def_node_id, span, ident, bounds); + self.lower_generic_and_bounds(*def_node_id, span, ident, bounds); self.impl_trait_defs.push(param); if let Some(bounds) = bounds { self.impl_trait_bounds.push(bounds); @@ -1740,8 +1738,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { matches!(kind, FnDeclKind::Trait), ) } else { - match decl.output { - FnRetTy::Ty(ref ty) => { + match &decl.output { + FnRetTy::Ty(ty) => { let mut context = match fn_node_id { Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => { let fn_def_id = self.local_def_id(fn_node_id); @@ -1763,7 +1761,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; hir::FnRetTy::Return(self.lower_ty(ty, &mut context)) } - FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)), + FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), } }; @@ -1777,18 +1775,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { PatKind::Ident(hir::BindingAnnotation(_, Mutability::Mut), ..) ); - match arg.ty.kind { + match &arg.ty.kind { TyKind::ImplicitSelf if is_mutable_pat => hir::ImplicitSelfKind::Mut, TyKind::ImplicitSelf => hir::ImplicitSelfKind::Imm, // Given we are only considering `ImplicitSelf` types, we needn't consider // the case where we have a mutable pattern to a reference as that would // no longer be an `ImplicitSelf`. - TyKind::Rptr(_, ref mt) + TyKind::Rptr(_, mt) if mt.ty.kind.is_implicit_self() && mt.mutbl == ast::Mutability::Mut => { hir::ImplicitSelfKind::MutRef } - TyKind::Rptr(_, ref mt) if mt.ty.kind.is_implicit_self() => { + TyKind::Rptr(_, mt) if mt.ty.kind.is_implicit_self() => { hir::ImplicitSelfKind::ImmRef } _ => hir::ImplicitSelfKind::None, @@ -2181,7 +2179,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, param: &GenericParam, ) -> (hir::ParamName, hir::GenericParamKind<'hir>) { - match param.kind { + match ¶m.kind { GenericParamKind::Lifetime => { // AST resolution emitted an error on those parameters, so we lower them using // `ParamName::Error`. @@ -2197,7 +2195,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (param_name, kind) } - GenericParamKind::Type { ref default, .. } => { + GenericParamKind::Type { default, .. } => { let kind = hir::GenericParamKind::Type { default: default.as_ref().map(|x| { self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) @@ -2207,7 +2205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(self.lower_ident(param.ident)), kind) } - GenericParamKind::Const { ref ty, kw_span: _, ref default } => { + GenericParamKind::Const { ty, kw_span: _, default } => { let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let default = default.as_ref().map(|def| self.lower_anon_const(def)); ( diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 7fdfc79164b..16b012630da 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -22,16 +22,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ensure_sufficient_stack(|| { // loop here to avoid recursion let node = loop { - match pattern.kind { + match &pattern.kind { PatKind::Wild => break hir::PatKind::Wild, - PatKind::Ident(binding_mode, ident, ref sub) => { - let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); - break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub); + PatKind::Ident(binding_mode, ident, sub) => { + let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(s)); + break self.lower_pat_ident(pattern, *binding_mode, *ident, lower_sub); } - PatKind::Lit(ref e) => { + PatKind::Lit(e) => { break hir::PatKind::Lit(self.lower_expr_within_pat(e, false)); } - PatKind::TupleStruct(ref qself, ref path, ref pats) => { + PatKind::TupleStruct(qself, path, pats) => { let qpath = self.lower_qpath( pattern.id, qself, @@ -42,12 +42,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); break hir::PatKind::TupleStruct(qpath, pats, ddpos); } - PatKind::Or(ref pats) => { + PatKind::Or(pats) => { break hir::PatKind::Or( self.arena.alloc_from_iter(pats.iter().map(|x| self.lower_pat_mut(x))), ); } - PatKind::Path(ref qself, ref path) => { + PatKind::Path(qself, path) => { let qpath = self.lower_qpath( pattern.id, qself, @@ -57,7 +57,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); break hir::PatKind::Path(qpath); } - PatKind::Struct(ref qself, ref path, ref fields, etc) => { + PatKind::Struct(qself, path, fields, etc) => { let qpath = self.lower_qpath( pattern.id, qself, @@ -78,32 +78,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: self.lower_span(f.span), } })); - break hir::PatKind::Struct(qpath, fs, etc); + break hir::PatKind::Struct(qpath, fs, *etc); } - PatKind::Tuple(ref pats) => { + PatKind::Tuple(pats) => { let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple"); break hir::PatKind::Tuple(pats, ddpos); } - PatKind::Box(ref inner) => { + PatKind::Box(inner) => { break hir::PatKind::Box(self.lower_pat(inner)); } - PatKind::Ref(ref inner, mutbl) => { - break hir::PatKind::Ref(self.lower_pat(inner), mutbl); + PatKind::Ref(inner, mutbl) => { + break hir::PatKind::Ref(self.lower_pat(inner), *mutbl); } - PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => { + PatKind::Range(e1, e2, Spanned { node: end, .. }) => { break hir::PatKind::Range( e1.as_deref().map(|e| self.lower_expr_within_pat(e, true)), e2.as_deref().map(|e| self.lower_expr_within_pat(e, true)), self.lower_range_end(end, e2.is_some()), ); } - PatKind::Slice(ref pats) => break self.lower_pat_slice(pats), + PatKind::Slice(pats) => break self.lower_pat_slice(pats), PatKind::Rest => { // If we reach here the `..` pattern is not semantically allowed. break self.ban_illegal_rest_pat(pattern.span); } // return inner to be processed in next loop - PatKind::Paren(ref inner) => pattern = inner, + PatKind::Paren(inner) => pattern = inner, PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), } }; @@ -126,7 +126,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Note that unlike for slice patterns, // where `xs @ ..` is a legal sub-slice pattern, // it is not a legal sub-tuple pattern. - match pat.kind { + match &pat.kind { // Found a sub-tuple rest pattern PatKind::Rest => { rest = Some((idx, pat.span)); @@ -134,12 +134,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // Found a sub-tuple pattern `$binding_mode $ident @ ..`. // This is not allowed as a sub-tuple pattern - PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => { + PatKind::Ident(_, ident, Some(sub)) if sub.is_rest() => { let sp = pat.span; self.tcx.sess.emit_err(SubTupleBinding { span: sp, ident_name: ident.name, - ident, + ident: *ident, ctx, }); } @@ -176,7 +176,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut prev_rest_span = None; // Lowers `$bm $ident @ ..` to `$bm $ident @ _`. - let lower_rest_sub = |this: &mut Self, pat, ann, ident, sub| { + let lower_rest_sub = |this: &mut Self, pat, &ann, &ident, sub| { let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); let node = this.lower_pat_ident(pat, ann, ident, lower_sub); this.pat_with_node_id_of(pat, node) @@ -185,7 +185,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut iter = pats.iter(); // Lower all the patterns until the first occurrence of a sub-slice pattern. for pat in iter.by_ref() { - match pat.kind { + match &pat.kind { // Found a sub-slice pattern `..`. Record, lower it to `_`, and stop here. PatKind::Rest => { prev_rest_span = Some(pat.span); @@ -194,7 +194,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // Found a sub-slice pattern `$binding_mode $ident @ ..`. // Record, lower it to `$binding_mode $ident @ _`, and stop here. - PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => { + PatKind::Ident(ann, ident, Some(sub)) if sub.is_rest() => { prev_rest_span = Some(sub.span); slice = Some(self.arena.alloc(lower_rest_sub(self, pat, ann, ident, sub))); break; @@ -207,9 +207,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Lower all the patterns after the first sub-slice pattern. for pat in iter { // There was a previous subslice pattern; make sure we don't allow more. - let rest_span = match pat.kind { + let rest_span = match &pat.kind { PatKind::Rest => Some(pat.span), - PatKind::Ident(ann, ident, Some(ref sub)) if sub.is_rest() => { + PatKind::Ident(ann, ident, Some(sub)) if sub.is_rest() => { // #69103: Lower into `binding @ _` as above to avoid ICEs. after.push(lower_rest_sub(self, pat, ann, ident, sub)); Some(sub.span) @@ -322,13 +322,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // m!(S); // ``` fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> { - match expr.kind { + match &expr.kind { ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::IncludedBytes(..) | ExprKind::Err => {} ExprKind::Path(..) if allow_paths => {} - ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} + ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} _ => { self.tcx.sess.emit_err(ArbitraryExpressionInPattern { span: expr.span }); return self.arena.alloc(self.expr_err(expr.span)); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 83d459d899b..27b44c0b6a2 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -185,12 +185,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { itctx: &ImplTraitContext, ) -> hir::PathSegment<'hir> { debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,); - let (mut generic_args, infer_args) = if let Some(ref generic_args) = segment.args { - match **generic_args { - GenericArgs::AngleBracketed(ref data) => { + let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() { + match generic_args { + GenericArgs::AngleBracketed(data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } - GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { + GenericArgs::Parenthesized(data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => { self.lower_parenthesized_parameter_data(data, itctx) } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 712fb5ac71f..acd7eb69ffc 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1637,7 +1637,7 @@ fn deny_equality_constraints( // Remove `Bar` from `Foo::Bar`. assoc_path.segments.pop(); let len = assoc_path.segments.len() - 1; - let gen_args = args.as_ref().map(|p| (**p).clone()); + let gen_args = args.as_deref().cloned(); // Build `<Bar = RhsTy>`. let arg = AngleBracketedArg::Constraint(AssocConstraint { id: rustc_ast::node_id::DUMMY_NODE_ID, diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 1da40d2302e..4b37fa027f5 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -377,7 +377,7 @@ impl<'a> State<'a> { self.space(); self.print_block_with_attrs(blk, attrs); } - ast::ExprKind::Loop(ref blk, opt_label) => { + ast::ExprKind::Loop(ref blk, opt_label, _) => { if let Some(label) = opt_label { self.print_ident(label.ident); self.word_space(":"); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5f99d86b4ea..5c645c66cd7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -167,10 +167,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } - self.add_moved_or_invoked_closure_note(location, used_place, &mut err); + let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err); let mut is_loop_move = false; let mut in_pattern = false; + let mut seen_spans = FxHashSet::default(); for move_site in &move_site_vec { let move_out = self.move_data.moves[(*move_site).moi]; @@ -191,37 +192,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { is_loop_move = true; } - self.explain_captures( - &mut err, - span, - move_span, - move_spans, - *moved_place, - partially_str, - loop_message, - move_msg, - is_loop_move, - maybe_reinitialized_locations.is_empty(), - ); - - if let (UseSpans::PatUse(span), []) = - (move_spans, &maybe_reinitialized_locations[..]) - { - if maybe_reinitialized_locations.is_empty() { - err.span_suggestion_verbose( - span.shrink_to_lo(), - &format!( - "borrow this field in the pattern to avoid moving {}", - self.describe_place(moved_place.as_ref()) - .map(|n| format!("`{}`", n)) - .unwrap_or_else(|| "the value".to_string()) - ), - "ref ", - Applicability::MachineApplicable, - ); - in_pattern = true; + if !seen_spans.contains(&move_span) { + if !closure { + self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern); } + + self.explain_captures( + &mut err, + span, + move_span, + move_spans, + *moved_place, + partially_str, + loop_message, + move_msg, + is_loop_move, + maybe_reinitialized_locations.is_empty(), + ); } + seen_spans.insert(move_span); } use_spans.var_path_only_subdiag(&mut err, desired_action); @@ -317,6 +306,160 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } + fn suggest_ref_or_clone( + &mut self, + mpi: MovePathIndex, + move_span: Span, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + in_pattern: &mut bool, + ) { + struct ExpressionFinder<'hir> { + expr_span: Span, + expr: Option<&'hir hir::Expr<'hir>>, + pat: Option<&'hir hir::Pat<'hir>>, + parent_pat: Option<&'hir hir::Pat<'hir>>, + } + impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> { + fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { + if e.span == self.expr_span { + self.expr = Some(e); + } + hir::intravisit::walk_expr(self, e); + } + fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) { + if p.span == self.expr_span { + self.pat = Some(p); + } + if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, i, sub) = p.kind { + if i.span == self.expr_span || p.span == self.expr_span { + self.pat = Some(p); + } + // Check if we are in a situation of `ident @ ident` where we want to suggest + // `ref ident @ ref ident` or `ref ident @ Struct { ref ident }`. + if let Some(subpat) = sub && self.pat.is_none() { + self.visit_pat(subpat); + if self.pat.is_some() { + self.parent_pat = Some(p); + } + return; + } + } + hir::intravisit::walk_pat(self, p); + } + } + let hir = self.infcx.tcx.hir(); + if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(_, _, body_id), + .. + })) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id())) + && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) + { + let place = &self.move_data.move_paths[mpi].place; + let span = place.as_local() + .map(|local| self.body.local_decls[local].source_info.span); + let mut finder = ExpressionFinder { + expr_span: move_span, + expr: None, + pat: None, + parent_pat: None, + }; + finder.visit_expr(expr); + if let Some(span) = span && let Some(expr) = finder.expr { + for (_, expr) in hir.parent_iter(expr.hir_id) { + if let hir::Node::Expr(expr) = expr { + if expr.span.contains(span) { + // If the let binding occurs within the same loop, then that + // loop isn't relevant, like in the following, the outermost `loop` + // doesn't play into `x` being moved. + // ``` + // loop { + // let x = String::new(); + // loop { + // foo(x); + // } + // } + // ``` + break; + } + if let hir::ExprKind::Loop(.., loop_span) = expr.kind { + err.span_label(loop_span, "inside of this loop"); + } + } + } + let typeck = self.infcx.tcx.typeck(self.mir_def_id()); + let hir_id = hir.get_parent_node(expr.hir_id); + if let Some(parent) = hir.find(hir_id) { + let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind + && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id) + { + (def_id.as_local(), args, 1) + } else if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call, args) = parent_expr.kind + && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind() + { + (def_id.as_local(), args, 0) + } else { + (None, &[][..], 0) + }; + if let Some(def_id) = def_id + && let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id)) + && let Some(fn_sig) = node.fn_sig() + && let Some(ident) = node.ident() + && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) + && let Some(arg) = fn_sig.decl.inputs.get(pos + offset) + { + let mut span: MultiSpan = arg.span.into(); + span.push_span_label( + arg.span, + "this parameter takes ownership of the value".to_string(), + ); + let descr = match node.fn_kind() { + Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function", + Some(hir::intravisit::FnKind::Method(..)) => "method", + Some(hir::intravisit::FnKind::Closure) => "closure", + }; + span.push_span_label( + ident.span, + format!("in this {descr}"), + ); + err.span_note( + span, + format!( + "consider changing this parameter type in {descr} `{ident}` to \ + borrow instead if owning the value isn't necessary", + ), + ); + } + let place = &self.move_data.move_paths[mpi].place; + let ty = place.ty(self.body, self.infcx.tcx).ty; + if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind + && let hir::ExprKind::Path( + hir::QPath::LangItem(LangItem::IntoIterIntoIter, _, _) + ) = call_expr.kind + { + // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. + } else { + self.suggest_cloning(err, ty, move_span); + } + } + } + if let Some(pat) = finder.pat { + *in_pattern = true; + let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())]; + if let Some(pat) = finder.parent_pat { + sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string())); + } + err.multipart_suggestion_verbose( + "borrow this binding in the pattern to avoid moving the value", + sugg, + Applicability::MachineApplicable, + ); + } + } + } + fn report_use_of_uninitialized( &self, mpi: MovePathIndex, @@ -590,6 +733,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { true } + fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { + let tcx = self.infcx.tcx; + // Try to find predicates on *generic params* that would allow copying `ty` + let infcx = tcx.infer_ctxt().build(); + if infcx + .type_implements_trait( + tcx.lang_items().clone_trait().unwrap(), + [tcx.erase_regions(ty)], + self.param_env, + ) + .must_apply_modulo_regions() + { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider cloning the value if the performance cost is acceptable", + ".clone()".to_string(), + Applicability::MachineApplicable, + ); + } + } + fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { let tcx = self.infcx.tcx; let generics = tcx.generics_of(self.mir_def_id()); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 4c3216d9878..c500cbc49e4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -70,7 +70,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, place: PlaceRef<'tcx>, diag: &mut Diagnostic, - ) { + ) -> bool { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); let mut target = place.local_or_deref_local(); for stmt in &self.body[location.block].statements[location.statement_index..] { @@ -106,7 +106,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { place.local_or_deref_local().unwrap() } - _ => return, + _ => return false, }; debug!("add_moved_or_invoked_closure_note: closure={:?}", closure); @@ -125,7 +125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::place_to_string_for_capture(self.infcx.tcx, hir_place) ), ); - return; + return true; } } } @@ -149,9 +149,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::place_to_string_for_capture(self.infcx.tcx, hir_place) ), ); + return true; } } } + false } /// End-user visible description of `place` if one can be found. diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index a34c17a4258..900c4427424 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -564,7 +564,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok(); template_strs.push(( template_str, - template_snippet.as_ref().map(|s| Symbol::intern(s)), + template_snippet.as_deref().map(Symbol::intern), template_sp, )); let template_str = template_str.as_str(); diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 220b7a8ad0f..9f42a0c2d58 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -307,7 +307,7 @@ impl<'cx, 'a> Context<'cx, 'a> { | ExprKind::InlineAsm(_) | ExprKind::Let(_, _, _) | ExprKind::Lit(_) - | ExprKind::Loop(_, _) + | ExprKind::Loop(_, _, _) | ExprKind::MacCall(_) | ExprKind::Match(_, _) | ExprKind::Path(_, _) diff --git a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs index fc7442470ac..df773910dbc 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs @@ -100,7 +100,7 @@ fn test_iter() { let s = "The %d'th word %% is: `%.*s` %!\n"; let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect(); assert_eq!( - subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(), + subs.iter().map(Option::as_deref).collect::<Vec<_>>(), vec![Some("{}"), None, Some("{:.*}"), None] ); } diff --git a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs index f5f82732f20..93a7afcd6e8 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs @@ -39,7 +39,7 @@ fn test_iter() { let s = "The $0'th word $$ is: `$WORD` $!\n"; let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect(); assert_eq!( - subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(), + subs.iter().map(Option::as_deref).collect::<Vec<_>>(), vec![Some("{0}"), None, Some("{WORD}")] ); } diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs index 48da64906e2..c627af4e62f 100644 --- a/compiler/rustc_codegen_cranelift/build_system/utils.rs +++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs @@ -104,5 +104,5 @@ pub(crate) fn copy_dir_recursively(from: &Path, to: &Path) { } pub(crate) fn is_ci() -> bool { - env::var("CI").as_ref().map(|val| &**val) == Ok("true") + env::var("CI").as_deref() == Ok("true") } diff --git a/compiler/rustc_codegen_cranelift/src/config.rs b/compiler/rustc_codegen_cranelift/src/config.rs index e59a0cb0a23..45522fb1a4c 100644 --- a/compiler/rustc_codegen_cranelift/src/config.rs +++ b/compiler/rustc_codegen_cranelift/src/config.rs @@ -2,7 +2,7 @@ use std::env; use std::str::FromStr; fn bool_env_var(key: &str) -> bool { - env::var(key).as_ref().map(|val| &**val) == Ok("1") + env::var(key).as_deref() == Ok("1") } /// The mode to use for compilation. diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 8a8d889a298..86580d05d41 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -174,7 +174,7 @@ impl CoverageMapGenerator { counter_regions.sort_unstable_by_key(|(_counter, region)| *region); for (counter, region) in counter_regions { let CodeRegion { file_name, start_line, start_col, end_line, end_col } = *region; - let same_file = current_file_name.as_ref().map_or(false, |p| *p == file_name); + let same_file = current_file_name.map_or(false, |p| p == file_name); if !same_file { if current_file_name.is_some() { current_file_id += 1; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 7822d924c01..03d833fbba8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -938,7 +938,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // that is understood elsewhere in the compiler as a method on // `dyn Trait`. // To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until - // we get a value of a built-in pointer type + // we get a value of a built-in pointer type. + // + // This is also relevant for `Pin<&mut Self>`, where we need to peel the `Pin`. 'descend_newtypes: while !op.layout.ty.is_unsafe_ptr() && !op.layout.ty.is_region_ptr() { @@ -980,13 +982,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { continue; } Immediate(_) => { - let ty::Ref(_, ty, _) = op.layout.ty.kind() else { - span_bug!(span, "can't codegen a virtual call on {:#?}", op); - }; - if !ty.is_dyn_star() { + // See comment above explaining why we peel these newtypes + 'descend_newtypes: while !op.layout.ty.is_unsafe_ptr() + && !op.layout.ty.is_region_ptr() + { + for i in 0..op.layout.fields.count() { + let field = op.extract_field(bx, i); + if !field.layout.is_zst() { + // we found the one non-zero-sized field that is allowed + // now find *its* non-zero-sized field, or stop if it's a + // pointer + op = field; + continue 'descend_newtypes; + } + } + + span_bug!(span, "receiver has no non-zero-sized fields {:?}", op); + } + + // Make sure that we've actually unwrapped the rcvr down + // to a pointer or ref to `dyn* Trait`. + if !op.layout.ty.builtin_deref(true).unwrap().ty.is_dyn_star() { span_bug!(span, "can't codegen a virtual call on {:#?}", op); } - // FIXME(dyn-star): Make sure this is done on a &dyn* receiver let place = op.deref(bx.cx()); let data_ptr = place.project_field(bx, 0); let meta_ptr = place.project_field(bx, 1); diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 8a712cec852..8e176efb2a9 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -318,7 +318,7 @@ fn run_compiler( compiler.input(), &*expanded_crate, *ppm, - compiler.output_file().as_ref().map(|p| &**p), + compiler.output_file().as_deref(), ); Ok(()) })?; @@ -329,7 +329,7 @@ fn run_compiler( compiler.input(), &krate, *ppm, - compiler.output_file().as_ref().map(|p| &**p), + compiler.output_file().as_deref(), ); } trace!("finished pretty-printing"); @@ -383,10 +383,7 @@ fn run_compiler( &crate_name, compiler.input(), None, - DumpHandler::new( - compiler.output_dir().as_ref().map(|p| &**p), - &crate_name, - ), + DumpHandler::new(compiler.output_dir().as_deref(), &crate_name), ) }); } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index bc136aea44d..bf20c7431e4 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -248,7 +248,7 @@ pub trait Emitter: Translate { fluent_args: &FluentArgs<'_>, ) -> (MultiSpan, &'a [CodeSuggestion]) { let mut primary_span = diag.span.clone(); - let suggestions = diag.suggestions.as_ref().map_or(&[][..], |suggestions| &suggestions[..]); + let suggestions = diag.suggestions.as_deref().unwrap_or(&[]); if let Some((sugg, rest)) = suggestions.split_first() { let msg = self.translate_message(&sugg.msg, fluent_args); if rest.is_empty() && diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index bd5b93293a9..473a04f33a9 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3594,9 +3594,16 @@ mod size_asserts { static_assert_size!(Res, 12); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); + // tidy-alphabetical-end + // FIXME: move the tidy directive to the end after the next bootstrap bump + #[cfg(bootstrap)] static_assert_size!(TraitItem<'_>, 88); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItem<'_>, 80); + #[cfg(bootstrap)] static_assert_size!(TraitItemKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(TraitItemKind<'_>, 40); static_assert_size!(Ty<'_>, 48); static_assert_size!(TyKind<'_>, 32); - // tidy-alphabetical-end } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 9b8cc884e18..5d63d90f304 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -2157,7 +2157,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> { .emit(); } let meta_item_list = attr.meta_item_list(); - let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref); + let meta_item_list = meta_item_list.as_deref(); let sole_meta_list = match meta_item_list { Some([item]) => item.literal(), Some(_) => { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 42aa3bcee49..25b6cf4ef2e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -30,7 +30,7 @@ use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::DefIdOrName; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; -use std::iter; +use std::{iter, slice}; /// Checks that it is legal to call methods of the trait corresponding /// to `trait_id` (this only cares about the trait, not the specific @@ -227,22 +227,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ] { let Some(trait_def_id) = opt_trait_def_id else { continue }; - let opt_input_types = opt_arg_exprs.map(|arg_exprs| { - [self.tcx.mk_tup(arg_exprs.iter().map(|e| { + let opt_input_type = opt_arg_exprs.map(|arg_exprs| { + self.tcx.mk_tup(arg_exprs.iter().map(|e| { self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span: e.span, }) - }))] + })) }); - let opt_input_types = opt_input_types.as_ref().map(AsRef::as_ref); if let Some(ok) = self.lookup_method_in_trait( call_expr.span, method_name, trait_def_id, adjusted_ty, - opt_input_types, + opt_input_type.as_ref().map(slice::from_ref), ) { let method = self.register_infer_ok_obligations(ok); let mut autoref = None; diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 43c7127b0d4..82784bb8a66 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -46,7 +46,7 @@ use rustc_hir::Expr; use rustc_hir_analysis::astconv::AstConv; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; -use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::Obligation; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, @@ -62,8 +62,7 @@ use rustc_span::{self, BytePos, DesugaringKind, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; -use rustc_trait_selection::traits::TraitEngineExt as _; -use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt}; use smallvec::{smallvec, SmallVec}; use std::ops::Deref; @@ -589,7 +588,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } _ => None, }; - let coerce_source = reborrow.as_ref().map_or(source, |&(_, ref r)| r.target); + let coerce_source = reborrow.as_ref().map_or(source, |(_, r)| r.target); // Setup either a subtyping or a LUB relationship between // the `CoerceUnsized` target type and the expected type. @@ -756,20 +755,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { if let ty::Dynamic(a_data, _, _) = a.kind() && let ty::Dynamic(b_data, _, _) = b.kind() + && a_data.principal_def_id() == b_data.principal_def_id() { - if a_data.principal_def_id() == b_data.principal_def_id() { - return self.unify_and(a, b, |_| vec![]); - } else if !self.tcx().features().trait_upcasting { - let mut err = feature_err( - &self.tcx.sess.parse_sess, - sym::trait_upcasting, - self.cause.span, - &format!( - "cannot cast `{a}` to `{b}`, trait upcasting coercion is experimental" - ), - ); - err.emit(); - } + return self.unify_and(a, b, |_| vec![]); } // Check the obligations of the cast -- for example, when casting @@ -797,19 +785,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { ]) .collect(); - // Enforce that the type is `usize`/pointer-sized. For now, only those - // can be coerced to `dyn*`, except for `dyn* -> dyn*` upcasts. - if !a.is_dyn_star() { - obligations.push(Obligation::new( - self.tcx, - self.cause.clone(), - self.param_env, - ty::Binder::dummy( - self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]), - ) - .to_poly_trait_predicate(), - )); - } + // Enforce that the type is `usize`/pointer-sized. + obligations.push(Obligation::new( + self.tcx, + self.cause.clone(), + self.param_env, + ty::Binder::dummy( + self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]), + ) + .to_poly_trait_predicate(), + )); Ok(InferOk { value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b), @@ -1055,9 +1040,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(ok) = coerce.coerce(source, target) else { return false; }; - let mut fcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx); - fcx.register_predicate_obligations(self, ok.obligations); - fcx.select_where_possible(&self).is_empty() + let ocx = ObligationCtxt::new_in_snapshot(self); + ocx.register_obligations(ok.obligations); + ocx.select_where_possible().is_empty() }) } diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs index a78b294181c..fd8ea1ad7bf 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs @@ -9,9 +9,10 @@ use hir::{ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_index::vec::IndexVec; +use rustc_infer::infer::InferCtxt; use rustc_middle::{ hir::map::Map, - ty::{TyCtxt, TypeckResults}, + ty::{ParamEnv, TyCtxt, TypeVisitable, TypeckResults}, }; use std::mem::swap; @@ -21,20 +22,29 @@ use std::mem::swap; /// The resulting structure still needs to be iterated to a fixed point, which /// can be done with propagate_to_fixpoint in cfg_propagate. pub(super) fn build_control_flow_graph<'tcx>( - hir: Map<'tcx>, - tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'tcx>, typeck_results: &TypeckResults<'tcx>, + param_env: ParamEnv<'tcx>, consumed_borrowed_places: ConsumedAndBorrowedPlaces, body: &'tcx Body<'tcx>, num_exprs: usize, ) -> (DropRangesBuilder, FxHashSet<HirId>) { - let mut drop_range_visitor = - DropRangeVisitor::new(hir, tcx, typeck_results, consumed_borrowed_places, num_exprs); + let mut drop_range_visitor = DropRangeVisitor::new( + infcx, + typeck_results, + param_env, + consumed_borrowed_places, + num_exprs, + ); intravisit::walk_body(&mut drop_range_visitor, body); drop_range_visitor.drop_ranges.process_deferred_edges(); - if let Some(filename) = &tcx.sess.opts.unstable_opts.dump_drop_tracking_cfg { - super::cfg_visualize::write_graph_to_file(&drop_range_visitor.drop_ranges, filename, tcx); + if let Some(filename) = &infcx.tcx.sess.opts.unstable_opts.dump_drop_tracking_cfg { + super::cfg_visualize::write_graph_to_file( + &drop_range_visitor.drop_ranges, + filename, + infcx.tcx, + ); } (drop_range_visitor.drop_ranges, drop_range_visitor.places.borrowed_temporaries) @@ -82,40 +92,44 @@ pub(super) fn build_control_flow_graph<'tcx>( /// ``` struct DropRangeVisitor<'a, 'tcx> { - hir: Map<'tcx>, + typeck_results: &'a TypeckResults<'tcx>, + infcx: &'a InferCtxt<'tcx>, + param_env: ParamEnv<'tcx>, places: ConsumedAndBorrowedPlaces, drop_ranges: DropRangesBuilder, expr_index: PostOrderId, - tcx: TyCtxt<'tcx>, - typeck_results: &'a TypeckResults<'tcx>, label_stack: Vec<(Option<rustc_ast::Label>, PostOrderId)>, } impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { fn new( - hir: Map<'tcx>, - tcx: TyCtxt<'tcx>, + infcx: &'a InferCtxt<'tcx>, typeck_results: &'a TypeckResults<'tcx>, + param_env: ParamEnv<'tcx>, places: ConsumedAndBorrowedPlaces, num_exprs: usize, ) -> Self { debug!("consumed_places: {:?}", places.consumed); let drop_ranges = DropRangesBuilder::new( places.consumed.iter().flat_map(|(_, places)| places.iter().cloned()), - hir, + infcx.tcx.hir(), num_exprs, ); Self { - hir, + infcx, + typeck_results, + param_env, places, drop_ranges, expr_index: PostOrderId::from_u32(0), - typeck_results, - tcx, label_stack: vec![], } } + fn tcx(&self) -> TyCtxt<'tcx> { + self.infcx.tcx + } + fn record_drop(&mut self, value: TrackedValue) { if self.places.borrowed.contains(&value) { debug!("not marking {:?} as dropped because it is borrowed at some point", value); @@ -137,7 +151,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { .map_or(vec![], |places| places.iter().cloned().collect()); for place in places { trace!(?place, "consuming place"); - for_each_consumable(self.hir, place, |value| self.record_drop(value)); + for_each_consumable(self.tcx().hir(), place, |value| self.record_drop(value)); } } @@ -214,10 +228,15 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { /// return. fn handle_uninhabited_return(&mut self, expr: &Expr<'tcx>) { let ty = self.typeck_results.expr_ty(expr); - let ty = self.tcx.erase_regions(ty); - let m = self.tcx.parent_module(expr.hir_id).to_def_id(); - let param_env = self.tcx.param_env(m.expect_local()); - if !ty.is_inhabited_from(self.tcx, m, param_env) { + let ty = self.infcx.resolve_vars_if_possible(ty); + if ty.has_non_region_infer() { + self.tcx() + .sess + .delay_span_bug(expr.span, format!("could not resolve infer vars in `{ty}`")); + } + let ty = self.tcx().erase_regions(ty); + let m = self.tcx().parent_module(expr.hir_id).to_def_id(); + if !ty.is_inhabited_from(self.tcx(), m, self.param_env) { // This function will not return. We model this fact as an infinite loop. self.drop_ranges.add_control_edge(self.expr_index + 1, self.expr_index + 1); } @@ -238,7 +257,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { destination: hir::Destination, ) -> Result<HirId, LoopIdError> { destination.target_id.map(|target| { - let node = self.hir.get(target); + let node = self.tcx().hir().get(target); match node { hir::Node::Expr(_) => target, hir::Node::Block(b) => find_last_block_expression(b), diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs index 4f3bdfbe758..2abcadcc9ce 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs @@ -43,9 +43,9 @@ pub fn compute_drop_ranges<'a, 'tcx>( let typeck_results = &fcx.typeck_results.borrow(); let num_exprs = fcx.tcx.region_scope_tree(def_id).body_expr_count(body.id()).unwrap_or(0); let (mut drop_ranges, borrowed_temporaries) = build_control_flow_graph( - fcx.tcx.hir(), - fcx.tcx, + &fcx, typeck_results, + fcx.param_env, consumed_borrowed_places, body, num_exprs, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 89aaa0b95e4..99c934862c4 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -304,7 +304,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se parse_sess_created(&mut sess.parse_sess); } - let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o)); + let temps_dir = sess.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let compiler = Compiler { sess: Lrc::new(sess), diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 91d180e1eb7..fc0b11183f7 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -33,11 +33,7 @@ pub struct Query<T> { impl<T> Query<T> { fn compute<F: FnOnce() -> Result<T>>(&self, f: F) -> Result<&Query<T>> { - let mut result = self.result.borrow_mut(); - if result.is_none() { - *result = Some(f()); - } - result.as_ref().unwrap().as_ref().map(|_| self).map_err(|err| *err) + self.result.borrow_mut().get_or_insert_with(f).as_ref().map(|_| self).map_err(|&err| err) } /// Takes ownership of the query result. Further attempts to take or peek the query diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 2fe3fb2fa56..4142964a0da 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -68,10 +68,7 @@ pub fn create_session( let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { make_codegen_backend(&sopts) } else { - get_codegen_backend( - &sopts.maybe_sysroot, - sopts.unstable_opts.codegen_backend.as_ref().map(|name| &name[..]), - ) + get_codegen_backend(&sopts.maybe_sysroot, sopts.unstable_opts.codegen_backend.as_deref()) }; // target_override is documented to be called before init(), so this is okay @@ -260,7 +257,7 @@ pub fn rustc_path<'a>() -> Option<&'a Path> { const BIN_PATH: &str = env!("RUSTC_INSTALL_BINDIR"); - RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_ref().map(|v| &**v) + RUSTC_PATH.get_or_init(|| get_rustc_path_inner(BIN_PATH)).as_deref() } fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> { diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs index c7ca8fd16ae..1c25b03fdb2 100644 --- a/compiler/rustc_lexer/src/unescape/tests.rs +++ b/compiler/rustc_lexer/src/unescape/tests.rs @@ -132,8 +132,7 @@ fn test_unescape_str_good() { } } }); - let buf = buf.as_ref().map(|it| it.as_ref()); - assert_eq!(buf, Ok(expected)) + assert_eq!(buf.as_deref(), Ok(expected)) } check("foo", "foo"); @@ -250,8 +249,7 @@ fn test_unescape_byte_str_good() { } } }); - let buf = buf.as_ref().map(|it| it.as_ref()); - assert_eq!(buf, Ok(expected)) + assert_eq!(buf.as_deref(), Ok(expected)) } check("foo", b"foo"); diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 589b4d6a10f..67cf66f4708 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1245,6 +1245,23 @@ impl<'tcx> LateContext<'tcx> { AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]).unwrap() } + + /// Returns the associated type `name` for `self_ty` as an implementation of `trait_id`. + /// Do not invoke without first verifying that the type implements the trait. + pub fn get_associated_type( + &self, + self_ty: Ty<'tcx>, + trait_id: DefId, + name: &str, + ) -> Option<Ty<'tcx>> { + let tcx = self.tcx; + tcx.associated_items(trait_id) + .find_by_name_and_kind(tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) + .and_then(|assoc| { + let proj = tcx.mk_projection(assoc.def_id, tcx.mk_substs_trait(self_ty, [])); + tcx.try_normalize_erasing_regions(self.param_env, proj).ok() + }) + } } impl<'tcx> abi::HasDataLayout for LateContext<'tcx> { diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs new file mode 100644 index 00000000000..1d29a234a3c --- /dev/null +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -0,0 +1,92 @@ +use crate::{LateContext, LateLintPass, LintContext}; + +use rustc_errors::DelayDm; +use rustc_hir as hir; +use rustc_middle::{traits::util::supertraits, ty}; +use rustc_span::sym; + +declare_lint! { + /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the + /// `Deref` implementation with a `dyn SuperTrait` type as `Output`. + /// + /// These implementations will become shadowed when the `trait_upcasting` feature is stabilized. + /// The `deref` functions will no longer be called implicitly, so there might be behavior change. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(deref_into_dyn_supertrait)] + /// #![allow(dead_code)] + /// + /// use core::ops::Deref; + /// + /// trait A {} + /// trait B: A {} + /// impl<'a> Deref for dyn 'a + B { + /// type Target = dyn A; + /// fn deref(&self) -> &Self::Target { + /// todo!() + /// } + /// } + /// + /// fn take_a(_: &dyn A) { } + /// + /// fn take_b(b: &dyn B) { + /// take_a(b); + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The dyn upcasting coercion feature adds new coercion rules, taking priority + /// over certain other coercion rules, which will cause some behavior change. + pub DEREF_INTO_DYN_SUPERTRAIT, + Warn, + "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>", + }; +} + +declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]); + +impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { + // `Deref` is being implemented for `t` + if let hir::ItemKind::Impl(impl_) = item.kind + && let Some(trait_) = &impl_.of_trait + && let t = cx.tcx.type_of(item.owner_id) + && let opt_did @ Some(did) = trait_.trait_def_id() + && opt_did == cx.tcx.lang_items().deref_trait() + // `t` is `dyn t_principal` + && let ty::Dynamic(data, _, ty::Dyn) = t.kind() + && let Some(t_principal) = data.principal() + // `<T as Deref>::Target` is `dyn target_principal` + && let Some(target) = cx.get_associated_type(t, did, "Target") + && let ty::Dynamic(data, _, ty::Dyn) = target.kind() + && let Some(target_principal) = data.principal() + // `target_principal` is a supertrait of `t_principal` + && supertraits(cx.tcx, t_principal.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self)) + .any(|sup| sup.map_bound(|x| ty::ExistentialTraitRef::erase_self_ty(cx.tcx, x)) == target_principal) + { + cx.struct_span_lint( + DEREF_INTO_DYN_SUPERTRAIT, + cx.tcx.def_span(item.owner_id.def_id), + DelayDm(|| { + format!( + "`{t}` implements `Deref` with supertrait `{target_principal}` as target" + ) + }), + |lint| { + if let Some(target_span) = impl_.items.iter().find_map(|i| (i.ident.name == sym::Target).then_some(i.span)) { + lint.span_label(target_span, "target type is set here"); + } + + lint + }, + ) + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ebb7de70e05..b6027476adf 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -49,6 +49,7 @@ extern crate tracing; mod array_into_iter; pub mod builtin; mod context; +mod deref_into_dyn_supertrait; mod early; mod enum_intrinsics_non_enums; mod errors; @@ -87,6 +88,7 @@ use rustc_span::Span; use array_into_iter::ArrayIntoIter; use builtin::*; +use deref_into_dyn_supertrait::*; use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums; use for_loops_over_fallibles::*; use hidden_unicode_codepoints::*; @@ -192,6 +194,7 @@ macro_rules! late_lint_mod_passes { $args, [ ForLoopsOverFallibles: ForLoopsOverFallibles, + DerefIntoDynSupertrait: DerefIntoDynSupertrait, HardwiredLints: HardwiredLints, ImproperCTypesDeclarations: ImproperCTypesDeclarations, ImproperCTypesDefinitions: ImproperCTypesDefinitions, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index b80facb1759..df0e17dea3c 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3262,7 +3262,6 @@ declare_lint_pass! { UNUSED_TUPLE_STRUCT_FIELDS, NON_EXHAUSTIVE_OMITTED_PATTERNS, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, - DEREF_INTO_DYN_SUPERTRAIT, DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, DUPLICATE_MACRO_ATTRIBUTES, SUSPICIOUS_AUTO_TRAIT_IMPLS, @@ -3765,51 +3764,6 @@ declare_lint! { } declare_lint! { - /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the - /// `Deref` implementation with a `dyn SuperTrait` type as `Output`. - /// - /// These implementations will become shadowed when the `trait_upcasting` feature is stabilized. - /// The `deref` functions will no longer be called implicitly, so there might be behavior change. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![deny(deref_into_dyn_supertrait)] - /// #![allow(dead_code)] - /// - /// use core::ops::Deref; - /// - /// trait A {} - /// trait B: A {} - /// impl<'a> Deref for dyn 'a + B { - /// type Target = dyn A; - /// fn deref(&self) -> &Self::Target { - /// todo!() - /// } - /// } - /// - /// fn take_a(_: &dyn A) { } - /// - /// fn take_b(b: &dyn B) { - /// take_a(b); - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// The dyn upcasting coercion feature adds new coercion rules, taking priority - /// over certain other coercion rules, which will cause some behavior change. - pub DEREF_INTO_DYN_SUPERTRAIT, - Warn, - "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future", - @future_incompatible = FutureIncompatibleInfo { - reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>", - }; -} - -declare_lint! { /// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro /// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test` /// and `test_case`. diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 18d37d95a83..5f02bb6c307 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -800,7 +800,7 @@ LLVMRustOptimize( auto Plugin = PassPlugin::Load(PluginPath.str()); if (!Plugin) { LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str()); - continue; + return LLVMRustResult::Failure; } Plugin->registerPassBuilderCallbacks(PB); } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index d4c457975a8..1a2389c7a84 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -162,7 +162,7 @@ impl CStore { pub(crate) fn iter_crate_data(&self) -> impl Iterator<Item = (CrateNum, &CrateMetadata)> { self.metas .iter_enumerated() - .filter_map(|(cnum, data)| data.as_ref().map(|data| (cnum, &**data))) + .filter_map(|(cnum, data)| data.as_deref().map(|data| (cnum, data))) } fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index af4be12fe3a..0602b7fc3bd 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2166,7 +2166,7 @@ impl EncodedMetadata { #[inline] pub fn raw_data(&self) -> &[u8] { - self.mmap.as_ref().map(|mmap| mmap.as_ref()).unwrap_or_default() + self.mmap.as_deref().unwrap_or_default() } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 396782d45d2..edd52728626 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -65,7 +65,7 @@ pub(crate) enum PlaceBase { /// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a /// place by pushing more and more projections onto the end, and then convert the final set into a -/// place using the `into_place` method. +/// place using the `to_place` method. /// /// This is used internally when building a place for an expression like `a.b.c`. The fields `b` /// and `c` can be progressively pushed onto the place builder that is created when converting `a`. @@ -167,59 +167,54 @@ fn find_capture_matching_projections<'a, 'tcx>( }) } -/// Takes a PlaceBuilder and resolves the upvar (if any) within it, so that the -/// `PlaceBuilder` now starts from `PlaceBase::Local`. -/// -/// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found. +/// Takes an upvar place and tries to resolve it into a `PlaceBuilder` +/// with `PlaceBase::Local` #[instrument(level = "trace", skip(cx), ret)] fn to_upvars_resolved_place_builder<'tcx>( - from_builder: PlaceBuilder<'tcx>, cx: &Builder<'_, 'tcx>, -) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> { - match from_builder.base { - PlaceBase::Local(_) => Ok(from_builder), - PlaceBase::Upvar { var_hir_id, closure_def_id } => { - let Some((capture_index, capture)) = - find_capture_matching_projections( - &cx.upvars, - var_hir_id, - &from_builder.projection, - ) else { - let closure_span = cx.tcx.def_span(closure_def_id); - if !enable_precise_capture(cx.tcx, closure_span) { - bug!( - "No associated capture found for {:?}[{:#?}] even though \ - capture_disjoint_fields isn't enabled", - var_hir_id, - from_builder.projection - ) - } else { - debug!( - "No associated capture found for {:?}[{:#?}]", - var_hir_id, from_builder.projection, - ); - } - return Err(from_builder); - }; + var_hir_id: LocalVarId, + closure_def_id: LocalDefId, + projection: &[PlaceElem<'tcx>], +) -> Option<PlaceBuilder<'tcx>> { + let Some((capture_index, capture)) = + find_capture_matching_projections( + &cx.upvars, + var_hir_id, + &projection, + ) else { + let closure_span = cx.tcx.def_span(closure_def_id); + if !enable_precise_capture(cx.tcx, closure_span) { + bug!( + "No associated capture found for {:?}[{:#?}] even though \ + capture_disjoint_fields isn't enabled", + var_hir_id, + projection + ) + } else { + debug!( + "No associated capture found for {:?}[{:#?}]", + var_hir_id, projection, + ); + } + return None; + }; - // Access the capture by accessing the field within the Closure struct. - let capture_info = &cx.upvars[capture_index]; + // Access the capture by accessing the field within the Closure struct. + let capture_info = &cx.upvars[capture_index]; - let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place); + let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place); - // We used some of the projections to build the capture itself, - // now we apply the remaining to the upvar resolved place. - trace!(?capture.captured_place, ?from_builder.projection); - let remaining_projections = strip_prefix( - capture.captured_place.place.base_ty, - from_builder.projection, - &capture.captured_place.place.projections, - ); - upvar_resolved_place_builder.projection.extend(remaining_projections); + // We used some of the projections to build the capture itself, + // now we apply the remaining to the upvar resolved place. + trace!(?capture.captured_place, ?projection); + let remaining_projections = strip_prefix( + capture.captured_place.place.base_ty, + projection, + &capture.captured_place.place.projections, + ); + upvar_resolved_place_builder.projection.extend(remaining_projections); - Ok(upvar_resolved_place_builder) - } - } + Some(upvar_resolved_place_builder) } /// Returns projections remaining after stripping an initial prefix of HIR @@ -228,13 +223,14 @@ fn to_upvars_resolved_place_builder<'tcx>( /// Supports only HIR projection kinds that represent a path that might be /// captured by a closure or a generator, i.e., an `Index` or a `Subslice` /// projection kinds are unsupported. -fn strip_prefix<'tcx>( +fn strip_prefix<'a, 'tcx>( mut base_ty: Ty<'tcx>, - projections: Vec<PlaceElem<'tcx>>, + projections: &'a [PlaceElem<'tcx>], prefix_projections: &[HirProjection<'tcx>], -) -> impl Iterator<Item = PlaceElem<'tcx>> { +) -> impl Iterator<Item = PlaceElem<'tcx>> + 'a { let mut iter = projections - .into_iter() + .iter() + .copied() // Filter out opaque casts, they are unnecessary in the prefix. .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..))); for projection in prefix_projections { @@ -258,21 +254,21 @@ fn strip_prefix<'tcx>( } impl<'tcx> PlaceBuilder<'tcx> { - pub(in crate::build) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> { - if let PlaceBase::Local(local) = self.base { - Place { local, projection: cx.tcx.intern_place_elems(&self.projection) } - } else { - self.expect_upvars_resolved(cx).into_place(cx) - } + pub(in crate::build) fn to_place(&self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> { + self.try_to_place(cx).unwrap() } - fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> { - to_upvars_resolved_place_builder(self, cx).unwrap() + /// Creates a `Place` or returns `None` if an upvar cannot be resolved + pub(in crate::build) fn try_to_place(&self, cx: &Builder<'_, 'tcx>) -> Option<Place<'tcx>> { + let resolved = self.resolve_upvar(cx); + let builder = resolved.as_ref().unwrap_or(self); + let PlaceBase::Local(local) = builder.base else { return None }; + let projection = cx.tcx.intern_place_elems(&builder.projection); + Some(Place { local, projection }) } /// Attempts to resolve the `PlaceBuilder`. - /// On success, it will return the resolved `PlaceBuilder`. - /// On failure, it will return itself. + /// Returns `None` if this is not an upvar. /// /// Upvars resolve may fail for a `PlaceBuilder` when attempting to /// resolve a disjoint field whose root variable is not captured @@ -281,11 +277,14 @@ impl<'tcx> PlaceBuilder<'tcx> { /// not captured. This can happen because the final mir that will be /// generated doesn't require a read for this place. Failures will only /// happen inside closures. - pub(in crate::build) fn try_upvars_resolved( - self, + pub(in crate::build) fn resolve_upvar( + &self, cx: &Builder<'_, 'tcx>, - ) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> { - to_upvars_resolved_place_builder(self, cx) + ) -> Option<PlaceBuilder<'tcx>> { + let PlaceBase::Upvar { var_hir_id, closure_def_id } = self.base else { + return None; + }; + to_upvars_resolved_place_builder(cx, var_hir_id, closure_def_id, &self.projection) } pub(crate) fn base(&self) -> PlaceBase { @@ -316,6 +315,14 @@ impl<'tcx> PlaceBuilder<'tcx> { self.projection.push(elem); self } + + /// Same as `.clone().project(..)` but more efficient + pub(crate) fn clone_project(&self, elem: PlaceElem<'tcx>) -> Self { + Self { + base: self.base, + projection: Vec::from_iter(self.projection.iter().copied().chain([elem])), + } + } } impl<'tcx> From<Local> for PlaceBuilder<'tcx> { @@ -355,7 +362,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr: &Expr<'tcx>, ) -> BlockAnd<Place<'tcx>> { let place_builder = unpack!(block = self.as_place_builder(block, expr)); - block.and(place_builder.into_place(self)) + block.and(place_builder.to_place(self)) } /// This is used when constructing a compound `Place`, so that we can avoid creating @@ -379,7 +386,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr: &Expr<'tcx>, ) -> BlockAnd<Place<'tcx>> { let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); - block.and(place_builder.into_place(self)) + block.and(place_builder.to_place(self)) } /// This is used when constructing a compound `Place`, so that we can avoid creating @@ -474,7 +481,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { inferred_ty: expr.ty, }); - let place = place_builder.clone().into_place(this); + let place = place_builder.to_place(this); this.cfg.push( block, Statement { @@ -599,7 +606,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let is_outermost_index = fake_borrow_temps.is_none(); let fake_borrow_temps = fake_borrow_temps.unwrap_or(base_fake_borrow_temps); - let mut base_place = + let base_place = unpack!(block = self.expr_as_place(block, base, mutability, Some(fake_borrow_temps),)); // Making this a *fresh* temporary means we do not have to worry about @@ -607,14 +614,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // The "retagging" transformation (for Stacked Borrows) relies on this. let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not,)); - block = self.bounds_check(block, base_place.clone(), idx, expr_span, source_info); + block = self.bounds_check(block, &base_place, idx, expr_span, source_info); if is_outermost_index { self.read_fake_borrows(block, fake_borrow_temps, source_info) } else { - base_place = base_place.expect_upvars_resolved(self); self.add_fake_borrows_of_base( - &base_place, + base_place.to_place(self), block, fake_borrow_temps, expr_span, @@ -628,7 +634,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn bounds_check( &mut self, block: BasicBlock, - slice: PlaceBuilder<'tcx>, + slice: &PlaceBuilder<'tcx>, index: Local, expr_span: Span, source_info: SourceInfo, @@ -640,7 +646,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let lt = self.temp(bool_ty, expr_span); // len = len(slice) - self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.into_place(self))); + self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.to_place(self))); // lt = idx < len self.cfg.push_assign( block, @@ -658,19 +664,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn add_fake_borrows_of_base( &mut self, - base_place: &PlaceBuilder<'tcx>, + base_place: Place<'tcx>, block: BasicBlock, fake_borrow_temps: &mut Vec<Local>, expr_span: Span, source_info: SourceInfo, ) { let tcx = self.tcx; - let local = match base_place.base { - PlaceBase::Local(local) => local, - PlaceBase::Upvar { .. } => bug!("Expected PlacseBase::Local found Upvar"), - }; - let place_ty = Place::ty_from(local, &base_place.projection, &self.local_decls, tcx); + let place_ty = base_place.ty(&self.local_decls, tcx); if let ty::Slice(_) = place_ty.ty.kind() { // We need to create fake borrows to ensure that the bounds // check that we just did stays valid. Since we can't assign to @@ -680,7 +682,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match elem { ProjectionElem::Deref => { let fake_borrow_deref_ty = Place::ty_from( - local, + base_place.local, &base_place.projection[..idx], &self.local_decls, tcx, @@ -698,14 +700,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Rvalue::Ref( tcx.lifetimes.re_erased, BorrowKind::Shallow, - Place { local, projection }, + Place { local: base_place.local, projection }, ), ); fake_borrow_temps.push(fake_borrow_temp); } ProjectionElem::Index(_) => { let index_ty = Place::ty_from( - local, + base_place.local, &base_place.projection[..idx], &self.local_decls, tcx, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 5c82fb1ddc0..0814793f277 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -369,8 +369,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let place_builder = unpack!(block = this.as_place_builder(block, &this.thir[*thir_place])); - if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) { - let mir_place = place_builder_resolved.into_place(this); + if let Some(mir_place) = place_builder.try_to_place(this) { this.cfg.push_fake_read( block, this.source_info(this.tcx.hir().span(*hir_id)), @@ -661,7 +660,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // by the parent itself. The mutability of the current capture // is same as that of the capture in the parent closure. PlaceBase::Upvar { .. } => { - let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this); + let enclosing_upvars_resolved = arg_place_builder.to_place(this); match enclosing_upvars_resolved.as_ref() { PlaceRef { @@ -698,7 +697,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false }, }; - let arg_place = arg_place_builder.into_place(this); + let arg_place = arg_place_builder.to_place(this); this.cfg.push_assign( block, diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 33e4fa58399..218a26e6279 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -358,10 +358,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .map(|(n, ty)| match fields_map.get(&n) { Some(v) => v.clone(), None => { - let place_builder = place_builder.clone(); - this.consume_by_copy_or_move( - place_builder.field(n, *ty).into_place(this), - ) + let place = place_builder.clone_project(PlaceElem::Field(n, *ty)); + this.consume_by_copy_or_move(place.to_place(this)) } }) .collect() diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 802704d6ca7..691cbee2c73 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -169,7 +169,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let scrutinee_place = unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,)); - let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms); + let mut arm_candidates = self.create_match_candidates(&scrutinee_place, &arms); let match_has_guard = arm_candidates.iter().any(|(_, candidate)| candidate.has_guard); let mut candidates = @@ -221,8 +221,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let cause_matched_place = FakeReadCause::ForMatchedPlace(None); let source_info = self.source_info(scrutinee_span); - if let Ok(scrutinee_builder) = scrutinee_place_builder.clone().try_upvars_resolved(self) { - let scrutinee_place = scrutinee_builder.into_place(self); + if let Some(scrutinee_place) = scrutinee_place_builder.try_to_place(self) { self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place); } @@ -232,7 +231,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Create the initial `Candidate`s for a `match` expression. fn create_match_candidates<'pat>( &mut self, - scrutinee: PlaceBuilder<'tcx>, + scrutinee: &PlaceBuilder<'tcx>, arms: &'pat [ArmId], ) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)> where @@ -335,7 +334,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let arm_scope = (arm.scope, arm_source_info); let match_scope = self.local_scope(); self.in_scope(arm_scope, arm.lint_level, |this| { - // `try_upvars_resolved` may fail if it is unable to resolve the given + // `try_to_place` may fail if it is unable to resolve the given // `PlaceBuilder` inside a closure. In this case, we don't want to include // a scrutinee place. `scrutinee_place_builder` will fail to be resolved // if the only match arm is a wildcard (`_`). @@ -346,14 +345,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // match foo { _ => () }; // }; // ``` - let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None; - let scrutinee_place: Place<'tcx>; - if let Ok(scrutinee_builder) = - scrutinee_place_builder.clone().try_upvars_resolved(this) - { - scrutinee_place = scrutinee_builder.into_place(this); - opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span)); - } + let scrutinee_place = scrutinee_place_builder.try_to_place(this); + let opt_scrutinee_place = + scrutinee_place.as_ref().map(|place| (Some(place), scrutinee_span)); let scope = this.declare_bindings( None, arm.span, @@ -592,7 +586,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { while let Some(next) = { for binding in &candidate_ref.bindings { let local = self.var_local_id(binding.var_id, OutsideGuard); - // `try_upvars_resolved` may fail if it is unable to resolve the given + // `try_to_place` may fail if it is unable to resolve the given // `PlaceBuilder` inside a closure. In this case, we don't want to include // a scrutinee place. `scrutinee_place_builder` will fail for destructured // assignments. This is because a closure only captures the precise places @@ -606,9 +600,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // let (v1, v2) = foo; // }; // ``` - if let Ok(match_pair_resolved) = initializer.clone().try_upvars_resolved(self) { - let place = match_pair_resolved.into_place(self); - + if let Some(place) = initializer.try_to_place(self) { let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. }, )))) = self.local_decls[local].local_info else { @@ -1345,7 +1337,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bug!("Or-patterns should have been sorted to the end"); }; let or_span = match_pair.pattern.span; - let place = match_pair.place; first_candidate.visit_leaves(|leaf_candidate| { self.test_or_pattern( @@ -1353,7 +1344,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut otherwise, pats, or_span, - place.clone(), + &match_pair.place, fake_borrows, ); }); @@ -1381,7 +1372,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise: &mut Option<BasicBlock>, pats: &'pat [Box<Pat<'tcx>>], or_span: Span, - place: PlaceBuilder<'tcx>, + place: &PlaceBuilder<'tcx>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>, ) { debug!("candidate={:#?}\npats={:#?}", candidate, pats); @@ -1599,10 +1590,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } // Insert a Shallow borrow of any places that is switched on. - if let Some(fb) = fake_borrows && let Ok(match_place_resolved) = - match_place.clone().try_upvars_resolved(self) + if let Some(fb) = fake_borrows + && let Some(resolved_place) = match_place.try_to_place(self) { - let resolved_place = match_place_resolved.into_place(self); fb.insert(resolved_place); } @@ -1621,7 +1611,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // encounter a candidate where the test is not relevant; at // that point, we stop sorting. while let Some(candidate) = candidates.first_mut() { - let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) else { + let Some(idx) = self.sort_candidate(&match_place, &test, candidate) else { break; }; let (candidate, rest) = candidates.split_first_mut().unwrap(); @@ -1690,7 +1680,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { target_blocks }; - self.perform_test(span, scrutinee_span, block, match_place, &test, make_target_blocks); + self.perform_test(span, scrutinee_span, block, &match_place, &test, make_target_blocks); } /// Determine the fake borrows that are needed from a set of places that @@ -1796,12 +1786,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { false, &mut [&mut guard_candidate, &mut otherwise_candidate], ); - let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None; - let expr_place: Place<'tcx>; - if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) { - expr_place = expr_builder.into_place(self); - opt_expr_place = Some((Some(&expr_place), expr_span)); - } + let expr_place = expr_place_builder.try_to_place(self); + let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span)); let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap(); self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span)); diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index caf27eb39d7..f6b1955fdec 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -73,8 +73,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { { existing_bindings.extend_from_slice(&new_bindings); mem::swap(&mut candidate.bindings, &mut existing_bindings); - candidate.subcandidates = - self.create_or_subcandidates(candidate, place.clone(), pats); + candidate.subcandidates = self.create_or_subcandidates(candidate, &place, pats); return true; } @@ -127,7 +126,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn create_or_subcandidates<'pat>( &mut self, candidate: &Candidate<'pat, 'tcx>, - place: PlaceBuilder<'tcx>, + place: &PlaceBuilder<'tcx>, pats: &'pat [Box<Pat<'tcx>>], ) -> Vec<Candidate<'pat, 'tcx>> { pats.iter() @@ -156,10 +155,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ascription: thir::Ascription { ref annotation, variance }, } => { // Apply the type ascription to the value at `match_pair.place`, which is the - if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) { + if let Some(source) = match_pair.place.try_to_place(self) { candidate.ascriptions.push(Ascription { annotation: annotation.clone(), - source: place_resolved.into_place(self), + source, variance, }); } @@ -183,10 +182,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ref subpattern, is_primary: _, } => { - if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) { + if let Some(source) = match_pair.place.try_to_place(self) { candidate.bindings.push(Binding { span: match_pair.pattern.span, - source: place_resolved.into_place(self), + source, var_id: var, binding_mode: mode, }); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index a62cfecf78b..58513bde2aa 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -150,11 +150,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_start_span: Span, scrutinee_span: Span, block: BasicBlock, - place_builder: PlaceBuilder<'tcx>, + place_builder: &PlaceBuilder<'tcx>, test: &Test<'tcx>, make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>, ) { - let place = place_builder.into_place(self); + let place = place_builder.to_place(self); let place_ty = place.ty(&self.local_decls, self.tcx); debug!(?place, ?place_ty,); @@ -760,7 +760,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)` let consequent_match_pairs = subpatterns.iter().map(|subpattern| { // e.g., `(x as Variant).0` - let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty); + let place = downcast_place + .clone_project(PlaceElem::Field(subpattern.field, subpattern.pattern.ty)); // e.g., `(x as Variant).0 @ P1` MatchPair::new(place, &subpattern.pattern, self) }); diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index b854ba47f8f..bd435f9ab00 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -18,7 +18,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { subpatterns .iter() .map(|fieldpat| { - let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty); + let place = + place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty)); MatchPair::new(place, &fieldpat.pattern, self) }) .collect() @@ -33,26 +34,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { suffix: &'pat [Box<Pat<'tcx>>], ) { let tcx = self.tcx; - let (min_length, exact_size) = - if let Ok(place_resolved) = place.clone().try_upvars_resolved(self) { - match place_resolved.into_place(self).ty(&self.local_decls, tcx).ty.kind() { - ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), - _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), - } - } else { - ((prefix.len() + suffix.len()).try_into().unwrap(), false) - }; + let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) { + match place_resolved.ty(&self.local_decls, tcx).ty.kind() { + ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), + _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), + } + } else { + ((prefix.len() + suffix.len()).try_into().unwrap(), false) + }; match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| { let elem = ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false }; - let place = place.clone().project(elem); - MatchPair::new(place, subpattern, self) + MatchPair::new(place.clone_project(elem), subpattern, self) })); if let Some(subslice_pat) = opt_slice { let suffix_len = suffix.len() as u64; - let subslice = place.clone().project(ProjectionElem::Subslice { + let subslice = place.clone_project(PlaceElem::Subslice { from: prefix.len() as u64, to: if exact_size { min_length - suffix_len } else { suffix_len }, from_end: !exact_size, @@ -67,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { min_length, from_end: !exact_size, }; - let place = place.clone().project(elem); + let place = place.clone_project(elem); MatchPair::new(place, subpattern, self) })); } @@ -97,15 +96,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { pub(in crate::build) fn new( - place: PlaceBuilder<'tcx>, + mut place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, cx: &Builder<'_, 'tcx>, ) -> MatchPair<'pat, 'tcx> { // Force the place type to the pattern's type. // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks? - let mut place = match place.try_upvars_resolved(cx) { - Ok(val) | Err(val) => val, - }; + if let Some(resolved) = place.resolve_upvar(cx) { + place = resolved; + } // Only add the OpaqueCast projection if the given place is an opaque type and the // expected type from the pattern is not. diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 60e64b45963..5fa41ebeb6e 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -486,7 +486,7 @@ impl<'tcx> Cx<'tcx> { substs, user_ty, fields: self.field_refs(fields), - base: base.as_ref().map(|base| FruInfo { + base: base.map(|base| FruInfo { base: self.mirror_expr(base), field_types: self.typeck_results().fru_field_types()[expr.hir_id] .iter() @@ -589,7 +589,7 @@ impl<'tcx> Cx<'tcx> { InlineAsmOperand::Out { reg, late, - expr: expr.as_ref().map(|expr| self.mirror_expr(expr)), + expr: expr.map(|expr| self.mirror_expr(expr)), } } hir::InlineAsmOperand::InOut { reg, late, ref expr } => { @@ -604,7 +604,7 @@ impl<'tcx> Cx<'tcx> { reg, late, in_expr: self.mirror_expr(in_expr), - out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)), + out_expr: out_expr.map(|expr| self.mirror_expr(expr)), }, hir::InlineAsmOperand::Const { ref anon_const } => { let value = mir::ConstantKind::from_anon_const( @@ -656,13 +656,11 @@ impl<'tcx> Cx<'tcx> { ExprKind::Repeat { value: self.mirror_expr(v), count: *count } } - hir::ExprKind::Ret(ref v) => { - ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr(v)) } - } + hir::ExprKind::Ret(ref v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) }, hir::ExprKind::Break(dest, ref value) => match dest.target_id { Ok(target_id) => ExprKind::Break { label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node }, - value: value.as_ref().map(|value| self.mirror_expr(value)), + value: value.map(|value| self.mirror_expr(value)), }, Err(err) => bug!("invalid loop id for break: {}", err), }, 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 ba04cb6eef8..e369dba5524 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1044,11 +1044,19 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa name, typeck_results.node_type(pat.hir_id), ); - sess.struct_span_err(pat.span, "borrow of moved value") - .span_label(binding_span, format!("value moved into `{}` here", name)) + let mut err = sess.struct_span_err(pat.span, "borrow of moved value"); + err.span_label(binding_span, format!("value moved into `{}` here", name)) .span_label(binding_span, occurs_because) - .span_labels(conflicts_ref, "value borrowed here after move") - .emit(); + .span_labels(conflicts_ref, "value borrowed here after move"); + if pat.span.contains(binding_span) { + err.span_suggestion_verbose( + binding_span.shrink_to_lo(), + "borrow this binding in the pattern to avoid moving the value", + "ref ".to_string(), + Applicability::MachineApplicable, + ); + } + err.emit(); } return; } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 4b6608faba6..4c2a80e523f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -216,7 +216,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lo = lo_expr.map(|e| self.lower_range_expr(e)); let hi = hi_expr.map(|e| self.lower_range_expr(e)); - let (lp, hp) = (lo.as_ref().map(|x| &x.0), hi.as_ref().map(|x| &x.0)); + let (lp, hp) = (lo.as_ref().map(|(x, _)| x), hi.as_ref().map(|(x, _)| x)); let mut kind = match self.normalize_range_pattern_ends(ty, lp, hp) { Some((lc, hc)) => self.lower_pattern_range(ty, lc, hc, end, lo_span), None => { @@ -358,7 +358,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { &mut self, pat: &'tcx Option<&'tcx hir::Pat<'tcx>>, ) -> Option<Box<Pat<'tcx>>> { - pat.as_ref().map(|p| self.lower_pattern(p)) + pat.map(|p| self.lower_pattern(p)) } fn slice_or_array_pattern( diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index fb2cee9e346..0ed24fe849c 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -245,9 +245,9 @@ impl<'a> Parser<'a> { /// PATH `=` UNSUFFIXED_LIT /// The delimiters or `=` are still put into the resulting token stream. pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::AttrItem> { - let item = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - Nonterminal::NtMeta(ref item) => Some(item.clone().into_inner()), + let item = match &self.token.kind { + token::Interpolated(nt) => match &**nt { + Nonterminal::NtMeta(item) => Some(item.clone().into_inner()), _ => None, }, _ => None, @@ -364,9 +364,9 @@ impl<'a> Parser<'a> { /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; /// ``` pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> { - let nt_meta = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - token::NtMeta(ref e) => Some(e.clone()), + let nt_meta = match &self.token.kind { + token::Interpolated(nt) => match &**nt { + token::NtMeta(e) => Some(e.clone()), _ => None, }, _ => None, diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 4c626539238..3f5baf343c9 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -973,7 +973,7 @@ impl<'a> Parser<'a> { inner_op: &Expr, outer_op: &Spanned<AssocOp>, ) -> bool /* advanced the cursor */ { - if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind { + if let ExprKind::Binary(op, l1, r1) = &inner_op.kind { if let ExprKind::Field(_, ident) = l1.kind && ident.as_str().parse::<i32>().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) @@ -1079,8 +1079,8 @@ impl<'a> Parser<'a> { let mk_err_expr = |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err))); - match inner_op.kind { - ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => { + match &inner_op.kind { + ExprKind::Binary(op, l1, r1) if op.node.is_comparison() => { let mut err = ComparisonOperatorsCannotBeChained { span: vec![op.span, self.prev_token.span], suggest_turbofish: None, @@ -1237,8 +1237,8 @@ impl<'a> Parser<'a> { let bounds = self.parse_generic_bounds(None)?; let sum_span = ty.span.to(self.prev_token.span); - let sub = match ty.kind { - TyKind::Rptr(ref lifetime, ref mut_ty) => { + let sub = match &ty.kind { + TyKind::Rptr(lifetime, mut_ty) => { let sum_with_parens = pprust::to_string(|s| { s.s.word("&"); s.print_opt_lifetime(lifetime); @@ -2565,7 +2565,7 @@ impl<'a> Parser<'a> { if let [a, b] = segments { let (a_span, b_span) = (a.span(), b.span()); let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo()); - if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") { + if self.span_to_snippet(between_span).as_deref() == Ok(":: ") { return Err(DoubleColonInBound { span: path.span.shrink_to_hi(), between: between_span, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index ba73fbd3e12..9f2267efb82 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -414,7 +414,7 @@ impl<'a> Parser<'a> { self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); false } - (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => false, + (true, Some(op)) if !op.can_continue_expr_unambiguously() => false, (true, Some(_)) => { self.error_found_expr_would_be_stmt(lhs); true @@ -1728,13 +1728,13 @@ impl<'a> Parser<'a> { || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) { let expr = self.parse_expr_opt()?; - if let Some(ref expr) = expr { + if let Some(expr) = &expr { if label.is_some() && matches!( expr.kind, ExprKind::While(_, _, None) | ExprKind::ForLoop(_, _, _, None) - | ExprKind::Loop(_, None) + | ExprKind::Loop(_, None, _) | ExprKind::Block(_, None) ) { @@ -2444,10 +2444,11 @@ impl<'a> Parser<'a> { /// Parses `loop { ... }` (`loop` token already eaten). fn parse_loop_expr(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { + let loop_span = self.prev_token.span; let (attrs, body) = self.parse_inner_attrs_and_block()?; Ok(self.mk_expr_with_attrs( lo.to(self.prev_token.span), - ExprKind::Loop(body, opt_label), + ExprKind::Loop(body, opt_label, loop_span), attrs, )) } @@ -2590,8 +2591,8 @@ impl<'a> Parser<'a> { // Used to check the `let_chains` and `if_let_guard` features mostly by scanning // `&&` tokens. fn check_let_expr(expr: &Expr) -> (bool, bool) { - match expr.kind { - ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, ref lhs, ref rhs) => { + match &expr.kind { + ExprKind::Binary(BinOp { node: BinOpKind::And, .. }, lhs, rhs) => { let lhs_rslt = check_let_expr(lhs); let rhs_rslt = check_let_expr(rhs); (lhs_rslt.0 || rhs_rslt.0, false) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 20b01f554f2..767fb9378be 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -222,7 +222,8 @@ impl<'a> Parser<'a> { self.parse_use_item()? } else if self.check_fn_front_matter(def_final, case) { // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis)?; + let (ident, sig, generics, body) = + self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?; (ident, ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, body }))) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { @@ -1255,8 +1256,8 @@ impl<'a> Parser<'a> { } }; - match impl_info.1 { - ItemKind::Impl(box Impl { of_trait: Some(ref trai), ref mut constness, .. }) => { + match &mut impl_info.1 { + ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => { *constness = Const::Yes(const_span); let before_trait = trai.path.span.shrink_to_lo(); @@ -1793,7 +1794,13 @@ impl<'a> Parser<'a> { }; // We use `parse_fn` to get a span for the function let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; - match self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis) { + match self.parse_fn( + &mut AttrVec::new(), + fn_parse_mode, + lo, + &inherited_vis, + Case::Insensitive, + ) { Ok(_) => { let mut err = self.struct_span_err( lo.to(self.prev_token.span), @@ -2114,8 +2121,9 @@ impl<'a> Parser<'a> { fn_parse_mode: FnParseMode, sig_lo: Span, vis: &Visibility, + case: Case, ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> { - let header = self.parse_fn_front_matter(vis)?; // `const ... fn` + let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn` let ident = self.parse_ident()?; // `foo` let mut generics = self.parse_generics()?; // `<'a, T, ...>` let decl = @@ -2239,24 +2247,28 @@ impl<'a> Parser<'a> { /// /// `vis` represents the visibility that was already parsed, if any. Use /// `Visibility::Inherited` when no visibility is known. - pub(super) fn parse_fn_front_matter(&mut self, orig_vis: &Visibility) -> PResult<'a, FnHeader> { + pub(super) fn parse_fn_front_matter( + &mut self, + orig_vis: &Visibility, + case: Case, + ) -> PResult<'a, FnHeader> { let sp_start = self.token.span; - let constness = self.parse_constness(Case::Insensitive); + let constness = self.parse_constness(case); let async_start_sp = self.token.span; - let asyncness = self.parse_asyncness(Case::Insensitive); + let asyncness = self.parse_asyncness(case); let unsafe_start_sp = self.token.span; - let unsafety = self.parse_unsafety(Case::Insensitive); + let unsafety = self.parse_unsafety(case); let ext_start_sp = self.token.span; - let ext = self.parse_extern(Case::Insensitive); + let ext = self.parse_extern(case); if let Async::Yes { span, .. } = asyncness { self.ban_async_in_2015(span); } - if !self.eat_keyword_case(kw::Fn, Case::Insensitive) { + if !self.eat_keyword_case(kw::Fn, case) { // It is possible for `expect_one_of` to recover given the contents of // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't // account for this. @@ -2585,8 +2597,8 @@ impl<'a> Parser<'a> { } fn is_named_param(&self) -> bool { - let offset = match self.token.kind { - token::Interpolated(ref nt) => match **nt { + let offset = match &self.token.kind { + token::Interpolated(nt) => match **nt { token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), _ => 0, }, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 8878c404c58..4d8bff28b05 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -384,8 +384,8 @@ enum TokenType { impl TokenType { fn to_string(&self) -> String { - match *self { - TokenType::Token(ref t) => format!("`{}`", pprust::token_kind_to_string(t)), + match self { + TokenType::Token(t) => format!("`{}`", pprust::token_kind_to_string(t)), TokenType::Keyword(kw) => format!("`{}`", kw), TokenType::Operator => "an operator".to_string(), TokenType::Lifetime => "lifetime".to_string(), @@ -738,8 +738,8 @@ impl<'a> Parser<'a> { fn check_inline_const(&self, dist: usize) -> bool { self.is_keyword_ahead(dist, &[kw::Const]) - && self.look_ahead(dist + 1, |t| match t.kind { - token::Interpolated(ref nt) => matches!(**nt, token::NtBlock(..)), + && self.look_ahead(dist + 1, |t| match &t.kind { + token::Interpolated(nt) => matches!(**nt, token::NtBlock(..)), token::OpenDelim(Delimiter::Brace) => true, _ => false, }) @@ -860,7 +860,7 @@ impl<'a> Parser<'a> { if let token::CloseDelim(..) | token::Eof = self.token.kind { break; } - if let Some(ref t) = sep.sep { + if let Some(t) = &sep.sep { if first { first = false; } else { @@ -895,7 +895,7 @@ impl<'a> Parser<'a> { _ => { // Attempt to keep parsing if it was a similar separator. - if let Some(ref tokens) = t.similar_tokens() { + if let Some(tokens) = t.similar_tokens() { if tokens.contains(&self.token.kind) && !unclosed_delims { self.bump(); } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 103dd801257..239ed79ce2f 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -42,9 +42,9 @@ impl<'a> Parser<'a> { token::Comma | token::Ident(..) | token::Interpolated(..) => true, _ => token.can_begin_type(), }, - NonterminalKind::Block => match token.kind { + NonterminalKind::Block => match &token.kind { token::OpenDelim(Delimiter::Brace) => true, - token::Interpolated(ref nt) => !matches!( + token::Interpolated(nt) => !matches!( **nt, token::NtItem(_) | token::NtPat(_) @@ -56,16 +56,16 @@ impl<'a> Parser<'a> { ), _ => false, }, - NonterminalKind::Path | NonterminalKind::Meta => match token.kind { + NonterminalKind::Path | NonterminalKind::Meta => match &token.kind { token::ModSep | token::Ident(..) => true, - token::Interpolated(ref nt) => match **nt { + token::Interpolated(nt) => match **nt { token::NtPath(_) | token::NtMeta(_) => true, _ => may_be_ident(&nt), }, _ => false, }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => { - match token.kind { + match &token.kind { token::Ident(..) | // box, ref, mut, and other identifiers (can stricten) token::OpenDelim(Delimiter::Parenthesis) | // tuple pattern token::OpenDelim(Delimiter::Bracket) | // slice pattern @@ -80,13 +80,13 @@ impl<'a> Parser<'a> { token::BinOp(token::Shl) => true, // path (double UFCS) // leading vert `|` or-pattern token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr {..}), - token::Interpolated(ref nt) => may_be_ident(nt), + token::Interpolated(nt) => may_be_ident(nt), _ => false, } } - NonterminalKind::Lifetime => match token.kind { + NonterminalKind::Lifetime => match &token.kind { token::Lifetime(_) => true, - token::Interpolated(ref nt) => { + token::Interpolated(nt) => { matches!(**nt, token::NtLifetime(_)) } _ => false, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index bf52febb107..cbeec951e2d 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -485,7 +485,7 @@ impl<'a> Parser<'a> { let mut rhs = self.parse_pat_no_top_alt(None)?; let sp = lhs.span.to(rhs.span); - if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind { + if let PatKind::Ident(_, _, sub @ None) = &mut rhs.kind { // The user inverted the order, so help them fix that. let mut applicability = Applicability::MachineApplicable; // FIXME(bindings_after_at): Remove this code when stabilizing the feature. @@ -595,7 +595,7 @@ impl<'a> Parser<'a> { self.recover_additional_muts(); // Make sure we don't allow e.g. `let mut $p;` where `$p:pat`. - if let token::Interpolated(ref nt) = self.token.kind { + if let token::Interpolated(nt) = &self.token.kind { if let token::NtPat(_) = **nt { self.expected_ident_found().emit(); } @@ -796,7 +796,7 @@ impl<'a> Parser<'a> { /// expression syntax `...expr` for splatting in expressions. fn parse_pat_range_to(&mut self, mut re: Spanned<RangeEnd>) -> PResult<'a, PatKind> { let end = self.parse_pat_range_end()?; - if let RangeEnd::Included(ref mut syn @ RangeSyntax::DotDotDot) = &mut re.node { + if let RangeEnd::Included(syn @ RangeSyntax::DotDotDot) = &mut re.node { *syn = RangeSyntax::DotDotEq; self.struct_span_err(re.span, "range-to patterns with `...` are not allowed") .span_suggestion_short( diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 73de86820d8..1b56cd72db0 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -563,9 +563,9 @@ impl<'a> Parser<'a> { }; let mut eat_semi = true; - match stmt.kind { + match &mut stmt.kind { // Expression without semicolon. - StmtKind::Expr(ref mut expr) + StmtKind::Expr(expr) if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => { // Just check for errors and recover; do not eat semicolon yet. // `expect_one_of` returns PResult<'a, bool /* recovered */> @@ -611,7 +611,7 @@ impl<'a> Parser<'a> { } } StmtKind::Expr(_) | StmtKind::MacCall(_) => {} - StmtKind::Local(ref mut local) if let Err(e) = self.expect_semi() => { + StmtKind::Local(local) if let Err(e) = self.expect_semi() => { // We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover. match &mut local.kind { LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index fecf67cb596..b7206b57642 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -536,7 +536,7 @@ impl<'a> Parser<'a> { }; let span_start = self.token.span; let ast::FnHeader { ext, unsafety, constness, asyncness } = - self.parse_fn_front_matter(&inherited_vis)?; + self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?; if self.may_recover() && self.token.kind == TokenKind::Lt { self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?; } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 58e1fe937a6..2234837050b 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -922,8 +922,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // v v // ( succ ) // - let else_ln = - self.propagate_through_opt_expr(else_opt.as_ref().map(|e| &**e), succ); + let else_ln = self.propagate_through_opt_expr(else_opt.as_deref(), succ); let then_ln = self.propagate_through_expr(&then, succ); let ln = self.live_node(expr.hir_id, expr.span); self.init_from_succ(ln, else_ln); @@ -966,7 +965,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::Ret(ref o_e) => { // Ignore succ and subst exit_ln. - self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), self.exit_ln) + self.propagate_through_opt_expr(o_e.as_deref(), self.exit_ln) } hir::ExprKind::Break(label, ref opt_expr) => { @@ -981,7 +980,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // look it up in the break loop nodes table match target { - Some(b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b), + Some(b) => self.propagate_through_opt_expr(opt_expr.as_deref(), b), None => span_bug!(expr.span, "`break` to unknown label"), } } @@ -1026,7 +1025,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::Array(ref exprs) => self.propagate_through_exprs(exprs, succ), hir::ExprKind::Struct(_, ref fields, ref with_expr) => { - let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ); + let succ = self.propagate_through_opt_expr(with_expr.as_deref(), succ); fields .iter() .rev() diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5072d2aad16..93b0f5814de 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3841,7 +3841,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } } - ExprKind::Loop(ref block, label) => self.resolve_labeled_block(label, expr.id, &block), + ExprKind::Loop(ref block, label, _) => { + self.resolve_labeled_block(label, expr.id, &block) + } ExprKind::While(ref cond, ref block, label) => { self.with_resolved_label(label, expr.id, |this| { diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 0e579379ec8..fae20c2ba5f 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1029,7 +1029,7 @@ impl<'tcx> DumpVisitor<'tcx> { trait_item.hir_id(), trait_item.ident, Some(bounds), - default_ty.as_ref().map(|ty| &**ty), + default_ty.as_deref(), &self.save_ctxt, ), attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt), diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index be084adb7b7..1ce3a613dc7 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1480,7 +1480,7 @@ pub fn get_cmd_lint_options( /// Parses the `--color` flag. pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { - match matches.opt_str("color").as_ref().map(|s| &s[..]) { + match matches.opt_str("color").as_deref() { Some("auto") => ColorConfig::Auto, Some("always") => ColorConfig::Always, Some("never") => ColorConfig::Never, @@ -1589,7 +1589,7 @@ pub fn parse_error_format( // is unstable, it will not be present. We have to use `opts_present` not // `opt_present` because the latter will panic. let error_format = if matches.opts_present(&["error-format".to_owned()]) { - match matches.opt_str("error-format").as_ref().map(|s| &s[..]) { + match matches.opt_str("error-format").as_deref() { None | Some("human") => { ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d602acec53e..fb0b62e025e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1357,7 +1357,7 @@ pub fn build_session( let profiler = SelfProfiler::new( directory, sopts.crate_name.as_deref(), - sopts.unstable_opts.self_profile_events.as_ref().map(|xs| &xs[..]), + sopts.unstable_opts.self_profile_events.as_deref(), &sopts.unstable_opts.self_profile_counter, ); match profiler { @@ -1391,7 +1391,7 @@ pub fn build_session( local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0); let optimization_fuel = Lock::new(OptimizationFuel { - remaining: sopts.unstable_opts.fuel.as_ref().map_or(0, |i| i.1), + remaining: sopts.unstable_opts.fuel.as_ref().map_or(0, |&(_, i)| i), out_of_fuel: false, }); let print_fuel = AtomicU64::new(0); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 322c7104be4..7ccfa600ec3 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -217,9 +217,7 @@ impl RealFileName { pub fn local_path(&self) -> Option<&Path> { match self { RealFileName::LocalPath(p) => Some(p), - RealFileName::Remapped { local_path: p, virtual_name: _ } => { - p.as_ref().map(PathBuf::as_path) - } + RealFileName::Remapped { local_path, virtual_name: _ } => local_path.as_deref(), } } 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 ef3d300020a..59d017545c0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -4,13 +4,12 @@ pub mod suggestions; use super::{ FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, ObligationCause, - ObligationCauseCode, OutputTypeParameterMismatch, Overflow, PredicateObligation, - SelectionContext, SelectionError, TraitNotObjectSafe, + ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow, + PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt, TyCtxtInferExt}; -use crate::traits::engine::TraitEngineExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::normalize::AtExt as _; use crate::traits::specialize::to_pretty_impl_header; @@ -30,7 +29,6 @@ use rustc_hir::Item; use rustc_hir::Node; use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::TypeTrace; -use rustc_infer::traits::TraitEngine; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; @@ -354,9 +352,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { param_env, ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }), ); - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(self.tcx); - fulfill_cx.register_predicate_obligation(self, obligation); - if fulfill_cx.select_all_or_error(self).is_empty() { + let ocx = ObligationCtxt::new_in_snapshot(self); + ocx.register_obligation(obligation); + if ocx.select_all_or_error().is_empty() { return Ok(( ty::ClosureKind::from_def_id(self.tcx, trait_def_id) .expect("expected to map DefId to ClosureKind"), @@ -2546,7 +2544,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let obligation = Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred); - self.predicate_may_hold(&obligation) + // We don't use `InferCtxt::predicate_may_hold` because that + // will re-run predicates that overflow locally, which ends up + // taking a really long time to compute. + self.evaluate_obligation(&obligation).map_or(false, |eval| eval.may_apply()) }) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 82f0440b307..9bfe527647d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -460,7 +460,7 @@ impl<'tcx> OnUnimplementedDirective { info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); let options_map: FxHashMap<Symbol, String> = - options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); + options.iter().filter_map(|(k, v)| v.clone().map(|v| (*k, v))).collect(); for command in self.subcommands.iter().chain(Some(self)).rev() { if let Some(ref condition) = command.condition && !attr::eval_condition( 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 186109e7075..bb6d7d0e8df 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1340,9 +1340,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligation.param_env, trait_pred_and_suggested_ty, ); - let suggested_ty_would_satisfy_obligation = self - .evaluate_obligation_no_overflow(&new_obligation) - .must_apply_modulo_regions(); + let suggested_ty_would_satisfy_obligation = + self.predicate_must_hold_modulo_regions(&new_obligation); if suggested_ty_would_satisfy_obligation { let sp = self .tcx diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index ff18aa1f9e9..548ca1c1d7f 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -31,7 +31,6 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ @@ -403,9 +402,7 @@ pub fn fully_solve_obligation<'tcx>( infcx: &InferCtxt<'tcx>, obligation: PredicateObligation<'tcx>, ) -> Vec<FulfillmentError<'tcx>> { - let mut engine = <dyn TraitEngine<'tcx>>::new(infcx.tcx); - engine.register_predicate_obligation(infcx, obligation); - engine.select_all_or_error(infcx) + fully_solve_obligations(infcx, [obligation]) } /// Process a set of obligations (and any nested obligations that come from them) @@ -414,9 +411,9 @@ pub fn fully_solve_obligations<'tcx>( infcx: &InferCtxt<'tcx>, obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>, ) -> Vec<FulfillmentError<'tcx>> { - let mut engine = <dyn TraitEngine<'tcx>>::new(infcx.tcx); - engine.register_predicate_obligations(infcx, obligations); - engine.select_all_or_error(infcx) + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligations(obligations); + ocx.select_all_or_error() } /// Process a bound (and any nested obligations that come from it) to completion. @@ -429,9 +426,16 @@ pub fn fully_solve_bound<'tcx>( ty: Ty<'tcx>, bound: DefId, ) -> Vec<FulfillmentError<'tcx>> { - let mut engine = <dyn TraitEngine<'tcx>>::new(infcx.tcx); - engine.register_bound(infcx, param_env, ty, bound, cause); - engine.select_all_or_error(infcx) + let tcx = infcx.tcx; + let trait_ref = ty::TraitRef { def_id: bound, substs: tcx.mk_substs_trait(ty, []) }; + let obligation = Obligation { + cause, + recursion_depth: 0, + param_env, + predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + }; + + fully_solve_obligation(infcx, obligation) } /// Normalizes the predicates and checks whether they hold in an empty environment. If this diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 9f19b0092c0..7b2329b1ddd 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -566,22 +566,6 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { .flatten() .unwrap_or_else(|| ty.super_fold_with(self).into()) }; - // For cases like #95134 we would like to catch overflows early - // otherwise they slip away and cause ICE. - let recursion_limit = self.tcx().recursion_limit(); - if !recursion_limit.value_within_limit(self.depth) - // HACK: Don't overflow when running cargo doc see #100991 - && !self.tcx().sess.opts.actually_rustdoc - { - let obligation = Obligation::with_depth( - self.selcx.tcx(), - self.cause.clone(), - recursion_limit.0, - self.param_env, - ty, - ); - self.selcx.infcx().err_ctxt().report_overflow_error(&obligation, true); - } debug!( ?self.depth, ?ty, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3b107d9570f..cd4a0447391 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -6,11 +6,9 @@ //! //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly use hir::LangItem; -use rustc_errors::DelayDm; use rustc_hir as hir; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; -use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TypeVisitable}; use rustc_target::spec::abi::Abi; @@ -776,9 +774,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match (source.kind(), target.kind()) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). - (&ty::Dynamic(ref data_a, _, dyn_a), &ty::Dynamic(ref data_b, _, dyn_b)) - if dyn_a == dyn_b => - { + (&ty::Dynamic(ref data_a, _, ty::Dyn), &ty::Dynamic(ref data_b, _, ty::Dyn)) => { // Upcast coercions permit several things: // // 1. Dropping auto traits, e.g., `Foo + Send` to `Foo` @@ -811,16 +807,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &obligation.cause, ) { if deref_trait_ref.def_id() == target_trait_did { - self.tcx().struct_span_lint_hir( - DEREF_INTO_DYN_SUPERTRAIT, - obligation.cause.body_id, - obligation.cause.span, - DelayDm(|| format!( - "`{}` implements `Deref` with supertrait `{}` as output", - source, deref_trait_ref - )), - |lint| lint, - ); return; } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2ec5d925b69..3cffd2bb780 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -803,9 +803,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let upcast_trait_ref; match (source.kind(), target.kind()) { // TraitA+Kx+'a -> TraitB+Ky+'b (trait upcasting coercion). - (&ty::Dynamic(ref data_a, r_a, repr_a), &ty::Dynamic(ref data_b, r_b, repr_b)) - if repr_a == repr_b => - { + ( + &ty::Dynamic(ref data_a, r_a, repr_a @ ty::Dyn), + &ty::Dynamic(ref data_b, r_b, ty::Dyn), + ) => { // See `assemble_candidates_for_unsizing` for more info. // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`. let principal_a = data_a.principal().unwrap(); @@ -831,7 +832,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map(ty::Binder::dummy), ); let existential_predicates = tcx.mk_poly_existential_predicates(iter); - let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_b); + let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_a); // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 7cc12eff20e..9a3c0707c7c 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -10,14 +10,14 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html pub mod specialization_graph; -use rustc_infer::traits::{TraitEngine, TraitEngineExt as _}; use specialization_graph::GraphExt; use crate::errors::NegativePositiveConflict; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; -use crate::traits::engine::TraitEngineExt as _; use crate::traits::select::IntercrateAmbiguityCause; -use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause}; +use crate::traits::{ + self, coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt, +}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{error_code, DelayDm, Diagnostic}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -204,12 +204,12 @@ fn fulfill_implication<'tcx>( // Needs to be `in_snapshot` because this function is used to rebase // substitutions, which may happen inside of a select within a probe. - let mut engine = <dyn TraitEngine<'tcx>>::new_in_snapshot(infcx.tcx); + let ocx = ObligationCtxt::new_in_snapshot(infcx); // attempt to prove all of the predicates for impl2 given those for impl1 // (which are packed up in penv) - engine.register_predicate_obligations(infcx, obligations.chain(more_obligations)); + ocx.register_obligations(obligations.chain(more_obligations)); - let errors = engine.select_all_or_error(infcx); + let errors = ocx.select_all_or_error(); if !errors.is_empty() { // no dice! debug!( diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 932dbbb81e5..40dbe0b3ff0 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -1,6 +1,5 @@ use crate::infer::{InferCtxt, TyCtxtInferExt}; -use crate::traits::ObligationCause; -use crate::traits::{TraitEngine, TraitEngineExt}; +use crate::traits::{ObligationCause, ObligationCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; @@ -72,28 +71,16 @@ fn type_marked_structural<'tcx>( adt_ty: Ty<'tcx>, cause: ObligationCause<'tcx>, ) -> bool { - let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx); + let ocx = ObligationCtxt::new(infcx); // require `#[derive(PartialEq)]` let structural_peq_def_id = infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span)); - fulfillment_cx.register_bound( - infcx, - ty::ParamEnv::empty(), - adt_ty, - structural_peq_def_id, - cause.clone(), - ); + ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id); // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.) let structural_teq_def_id = infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span)); - fulfillment_cx.register_bound( - infcx, - ty::ParamEnv::empty(), - adt_ty, - structural_teq_def_id, - cause, - ); + ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id); // We deliberately skip *reporting* fulfillment errors (via // `report_fulfillment_errors`), for two reasons: @@ -104,7 +91,7 @@ fn type_marked_structural<'tcx>( // // 2. We are sometimes doing future-incompatibility lints for // now, so we do not want unconditional errors here. - fulfillment_cx.select_all_or_error(infcx).is_empty() + ocx.select_all_or_error().is_empty() } /// This implements the traversal over the structure of a given type to try to diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 2d1a3869926..3ab353c9638 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -5,16 +5,15 @@ use rustc_hir as hir; use rustc_infer::infer::canonical::{self, Canonical}; use rustc_infer::infer::outlives::components::{push_outlives_components, Component}; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::query::OutlivesBound; -use rustc_infer::traits::TraitEngineExt as _; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use rustc_span::source_map::DUMMY_SP; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; use rustc_trait_selection::traits::wf; -use rustc_trait_selection::traits::{TraitEngine, TraitEngineExt}; +use rustc_trait_selection::traits::ObligationCtxt; use smallvec::{smallvec, SmallVec}; pub(crate) fn provide(p: &mut Providers) { @@ -30,16 +29,16 @@ fn implied_outlives_bounds<'tcx>( > { tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| { let (param_env, ty) = key.into_parts(); - compute_implied_outlives_bounds(&ocx.infcx, param_env, ty) + compute_implied_outlives_bounds(ocx, param_env, ty) }) } fn compute_implied_outlives_bounds<'tcx>( - infcx: &InferCtxt<'tcx>, + ocx: &ObligationCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, ) -> Fallible<Vec<OutlivesBound<'tcx>>> { - let tcx = infcx.tcx; + let tcx = ocx.infcx.tcx; // Sometimes when we ask what it takes for T: WF, we get back that // U: WF is required; in that case, we push U onto this stack and @@ -52,8 +51,6 @@ fn compute_implied_outlives_bounds<'tcx>( let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> = vec![]; - let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx); - while let Some(arg) = wf_args.pop() { if !checked_wf_args.insert(arg) { continue; @@ -70,15 +67,15 @@ fn compute_implied_outlives_bounds<'tcx>( // FIXME(@lcnr): It's not really "always fine", having fewer implied // bounds can be backward incompatible, e.g. #101951 was caused by // us not dealing with inference vars in `TypeOutlives` predicates. - let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP) - .unwrap_or_default(); + let obligations = + wf::obligations(ocx.infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP) + .unwrap_or_default(); // While these predicates should all be implied by other parts of // the program, they are still relevant as they may constrain // inference variables, which is necessary to add the correct // implied bounds in some cases, mostly when dealing with projections. - fulfill_cx.register_predicate_obligations( - infcx, + ocx.register_obligations( obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(), ); @@ -116,9 +113,9 @@ fn compute_implied_outlives_bounds<'tcx>( })); } - // Ensure that those obligations that we had to solve - // get solved *here*. - match fulfill_cx.select_all_or_error(infcx).as_slice() { + // This call to `select_all_or_error` is necessary to constrain inference variables, which we + // use further down when computing the implied bounds. + match ocx.select_all_or_error().as_slice() { [] => (), _ => return Err(NoSolution), } @@ -130,7 +127,7 @@ fn compute_implied_outlives_bounds<'tcx>( .flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() { ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)], ty::GenericArgKind::Type(ty_a) => { - let ty_a = infcx.resolve_vars_if_possible(ty_a); + let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a); let mut components = smallvec![]; push_outlives_components(tcx, ty_a, &mut components); implied_bounds_from_components(r_b, components) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 92e8542795f..07af3dc5164 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -138,8 +138,18 @@ fn univariant_uninterned<'tcx>( if optimize { let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; let optimizing = &mut inverse_memory_index[..end]; - let field_align = |f: &TyAndLayout<'_>| { - if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi } + let effective_field_align = |f: &TyAndLayout<'_>| { + if let Some(pack) = pack { + // return the packed alignment in bytes + f.align.abi.min(pack).bytes() + } else { + // returns log2(effective-align). + // This is ok since `pack` applies to all fields equally. + // The calculation assumes that size is an integer multiple of align, except for ZSTs. + // + // group [u8; 4] with align-4 or [u8; 6] with align-2 fields + f.align.abi.bytes().max(f.size.bytes()).trailing_zeros() as u64 + } }; // If `-Z randomize-layout` was enabled for the type definition we can shuffle @@ -160,15 +170,23 @@ fn univariant_uninterned<'tcx>( optimizing.sort_by_key(|&x| { // Place ZSTs first to avoid "interesting offsets", // especially with only one or two non-ZST fields. + // Then place largest alignments first, largest niches within an alignment group last let f = &fields[x as usize]; - (!f.is_zst(), cmp::Reverse(field_align(f))) + let niche_size = f.largest_niche.map_or(0, |n| n.available(cx)); + (!f.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size) }); } StructKind::Prefixed(..) => { // Sort in ascending alignment so that the layout stays optimal - // regardless of the prefix - optimizing.sort_by_key(|&x| field_align(&fields[x as usize])); + // regardless of the prefix. + // And put the largest niche in an alignment group at the end + // so it can be used as discriminant in jagged enums + optimizing.sort_by_key(|&x| { + let f = &fields[x as usize]; + let niche_size = f.largest_niche.map_or(0, |n| n.available(cx)); + (effective_field_align(f), niche_size) + }); } } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 8d999302a6d..251431a15eb 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1094,7 +1094,13 @@ impl<'a> Builder<'a> { let my_out = match mode { // This is the intended out directory for compiler documentation. Mode::Rustc | Mode::ToolRustc => self.compiler_doc_out(target), - Mode::Std => out_dir.join(target.triple).join("doc"), + Mode::Std => { + if self.config.cmd.json() { + out_dir.join(target.triple).join("json-doc") + } else { + out_dir.join(target.triple).join("doc") + } + } _ => panic!("doc mode {:?} not expected", mode), }; let rustdoc = self.rustdoc(compiler); diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 3180a12c85b..571396eb835 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -564,27 +564,22 @@ fn doc_std( ); } let compiler = builder.compiler(stage, builder.config.build); + + let target_doc_dir_name = if format == DocumentationFormat::JSON { "json-doc" } else { "doc" }; + let target_dir = + builder.stage_out(compiler, Mode::Std).join(target.triple).join(target_doc_dir_name); + // This is directory where the compiler will place the output of the command. // We will then copy the files from this directory into the final `out` directory, the specified // as a function parameter. - let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc"); - // `cargo` uses the same directory for both JSON docs and HTML docs. - // This could lead to cross-contamination when copying files into the specified `out` directory. - // For example: - // ```bash - // x doc std - // x doc std --json - // ``` - // could lead to HTML docs being copied into the JSON docs output directory. - // To avoid this issue, we clean the doc folder before invoking `cargo`. - if out_dir.exists() { - builder.remove_dir(&out_dir); - } + let out_dir = target_dir.join(target.triple).join("doc"); let run_cargo_rustdoc_for = |package: &str| { let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc"); compile::std_cargo(builder, target, compiler.stage, &mut cargo); cargo + .arg("--target-dir") + .arg(&*target_dir.to_string_lossy()) .arg("-p") .arg(package) .arg("-Zskip-rustdoc-fingerprint") diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d4e881ad832..63530b924c2 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -701,6 +701,8 @@ a { } .small-section-header { + /* fields use <span> tags, but should get their own lines */ + display: block; position: relative; } diff --git a/src/test/codegen/issue-37945.rs b/src/test/codegen/issue-37945.rs index 12fa1e9e56b..fe54375bbf6 100644 --- a/src/test/codegen/issue-37945.rs +++ b/src/test/codegen/issue-37945.rs @@ -15,7 +15,7 @@ use std::slice::Iter; pub fn is_empty_1(xs: Iter<f32>) -> bool { // CHECK-LABEL: @is_empty_1( // CHECK-NEXT: start: -// CHECK-NEXT: [[A:%.*]] = icmp ne {{i32\*|ptr}} %xs.1, null +// CHECK-NEXT: [[A:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null // CHECK-NEXT: tail call void @llvm.assume(i1 [[A]]) // The order between %xs.0 and %xs.1 on the next line doesn't matter // and different LLVM versions produce different order. @@ -28,7 +28,7 @@ pub fn is_empty_1(xs: Iter<f32>) -> bool { pub fn is_empty_2(xs: Iter<f32>) -> bool { // CHECK-LABEL: @is_empty_2 // CHECK-NEXT: start: -// CHECK-NEXT: [[C:%.*]] = icmp ne {{i32\*|ptr}} %xs.1, null +// CHECK-NEXT: [[C:%.*]] = icmp ne {{i32\*|ptr}} {{%xs.0|%xs.1}}, null // CHECK-NEXT: tail call void @llvm.assume(i1 [[C]]) // The order between %xs.0 and %xs.1 on the next line doesn't matter // and different LLVM versions produce different order. diff --git a/src/test/codegen/mem-replace-direct-memcpy.rs b/src/test/codegen/mem-replace-direct-memcpy.rs index 4318e926e47..e8bbf0e1bbd 100644 --- a/src/test/codegen/mem-replace-direct-memcpy.rs +++ b/src/test/codegen/mem-replace-direct-memcpy.rs @@ -18,7 +18,7 @@ pub fn replace_byte(dst: &mut u8, src: u8) -> u8 { // CHECK-NOT: call void @llvm.memcpy // CHECK: ; core::mem::replace // CHECK-NOT: call void @llvm.memcpy -// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %dest, i{{.*}} 1, i1 false) +// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false) // CHECK-NOT: call void @llvm.memcpy -// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %dest, {{i8\*|ptr}} align 1 %src{{.*}}, i{{.*}} 1, i1 false) +// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false) // CHECK-NOT: call void @llvm.memcpy diff --git a/src/test/codegen/slice-iter-len-eq-zero.rs b/src/test/codegen/slice-iter-len-eq-zero.rs index 1124028253d..894b0ec3de4 100644 --- a/src/test/codegen/slice-iter-len-eq-zero.rs +++ b/src/test/codegen/slice-iter-len-eq-zero.rs @@ -9,7 +9,7 @@ type Demo = [u8; 3]; #[no_mangle] pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool { // CHECK-NOT: sub - // CHECK: %2 = icmp eq {{i8\*|ptr}} %1, %0 + // CHECK: %2 = icmp eq {{i8\*|ptr}} {{%1|%0}}, {{%1|%0}} // CHECK: ret i1 %2 y.len() == 0 } diff --git a/src/test/run-make/rustdoc-verify-output-files/Makefile b/src/test/run-make/rustdoc-verify-output-files/Makefile new file mode 100644 index 00000000000..bfabbbc6586 --- /dev/null +++ b/src/test/run-make/rustdoc-verify-output-files/Makefile @@ -0,0 +1,36 @@ +include ../../run-make-fulldeps/tools.mk + +OUTPUT_DIR := "$(TMPDIR)/rustdoc" +TMP_OUTPUT_DIR := "$(TMPDIR)/tmp-rustdoc" + +all: + # Generate html docs + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) + + # Copy first output for to check if it's exactly same after second compilation + cp -R $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) + + # Generate html docs once again on same output + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) + + # Check if everything exactly same + $(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) + + # Generate json doc on the same output + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) -Z unstable-options --output-format json + + # Check if expected json file is generated + [ -e $(OUTPUT_DIR)/foobar.json ] + + # TODO + # We should re-generate json doc once again and compare the diff with previously + # generated one. Because layout of json docs changes in each compilation, we can't + # do that currently. + # + # See https://github.com/rust-lang/rust/issues/103785#issuecomment-1307425590 for details. + + # remove generated json doc + rm $(OUTPUT_DIR)/foobar.json + + # Check if json doc compilation broke any of the html files generated previously + $(DIFF) -r -q $(OUTPUT_DIR) $(TMP_OUTPUT_DIR) diff --git a/src/test/run-make/rustdoc-verify-output-files/src/lib.rs b/src/test/run-make/rustdoc-verify-output-files/src/lib.rs new file mode 100644 index 00000000000..5df7576133a --- /dev/null +++ b/src/test/run-make/rustdoc-verify-output-files/src/lib.rs @@ -0,0 +1 @@ +// nothing to see here diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index 8eea5ad01c0..dea154c9319 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -408,6 +408,11 @@ pub struct WithGenerics<T: TraitWithNoDocblocks, S = String, E = WhoLetTheDogOut p: P, } +pub struct StructWithPublicUndocumentedFields { + pub first: u32, + pub second: u32, +} + pub const CONST: u8 = 0; pub trait TraitWithoutGenerics { diff --git a/src/test/rustdoc-gui/struct-fields.goml b/src/test/rustdoc-gui/struct-fields.goml new file mode 100644 index 00000000000..3ec60b58cfd --- /dev/null +++ b/src/test/rustdoc-gui/struct-fields.goml @@ -0,0 +1,5 @@ +goto: "file://" + |DOC_PATH| + "/test_docs/struct.StructWithPublicUndocumentedFields.html" + +// Both fields must be on their own line. In other words, they have display: block. +store-property: (first_top, "//*[@id='structfield.first']", "offsetTop") +assert-property-false: ("//*[@id='structfield.second']", { "offsetTop": |first_top| }) diff --git a/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.rs b/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.rs new file mode 100644 index 00000000000..7f729429581 --- /dev/null +++ b/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.rs @@ -0,0 +1,106 @@ +// compile-flags: -Zdrop-tracking +// incremental +// edition: 2021 + +use std::future::*; +use std::marker::PhantomData; +use std::pin::Pin; +use std::task::*; + +fn send<T: Send>(_: T) {} + +pub trait Stream { + type Item; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>; +} + +struct Empty<T>(PhantomData<fn() -> T>); + +impl<T> Stream for Empty<T> { + type Item = T; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { + todo!() + } +} + +pub trait FnOnce1<A> { + type Output; + fn call_once(self, arg: A) -> Self::Output; +} + +impl<T, A, R> FnOnce1<A> for T +where + T: FnOnce(A) -> R, +{ + type Output = R; + fn call_once(self, arg: A) -> R { + self(arg) + } +} + +pub trait FnMut1<A>: FnOnce1<A> { + fn call_mut(&mut self, arg: A) -> Self::Output; +} + +impl<T, A, R> FnMut1<A> for T +where + T: FnMut(A) -> R, +{ + fn call_mut(&mut self, arg: A) -> R { + self(arg) + } +} + +struct Map<St, F>(St, F); + +impl<St, F> Stream for Map<St, F> +where + St: Stream, + F: FnMut1<St::Item>, +{ + type Item = F::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { + todo!() + } +} + +struct FuturesOrdered<T: Future>(PhantomData<fn() -> T::Output>); + +pub struct Buffered<St: Stream>(St, FuturesOrdered<St::Item>, usize) +where + St::Item: Future; + +impl<St> Stream for Buffered<St> +where + St: Stream, + St::Item: Future, +{ + type Item = <St::Item as Future>::Output; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { + todo!() + } +} + +struct Next<'a, T: ?Sized>(&'a T); + +impl<St: ?Sized + Stream + Unpin> Future for Next<'_, St> { + type Output = Option<St::Item>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + todo!() + } +} + +fn main() { + send(async { + //~^ ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + //~| ERROR implementation of `FnOnce` is not general enough + Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await + }); +} diff --git a/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.stderr b/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.stderr new file mode 100644 index 00000000000..aa9a22e9e72 --- /dev/null +++ b/src/test/ui/async-await/drop-tracking-unresolved-typeck-results.stderr @@ -0,0 +1,62 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + | +LL | / send(async { +LL | | +LL | | +LL | | +LL | | +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + | +LL | / send(async { +LL | | +LL | | +LL | | +LL | | +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + | +LL | / send(async { +LL | | +LL | | +LL | | +LL | | +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/drop-tracking-unresolved-typeck-results.rs:99:5 + | +LL | / send(async { +LL | | +LL | | +LL | | +LL | | +LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await +LL | | }); + | |______^ implementation of `FnOnce` is not general enough + | + = note: `fn(&'0 ()) -> std::future::Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/binding/issue-53114-borrow-checks.stderr b/src/test/ui/binding/issue-53114-borrow-checks.stderr index 489bf70d920..0ec2ae8839e 100644 --- a/src/test/ui/binding/issue-53114-borrow-checks.stderr +++ b/src/test/ui/binding/issue-53114-borrow-checks.stderr @@ -17,6 +17,10 @@ LL | match mm { (_, _y) => { } } | ^^ value used here after partial move | = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | match mm { (ref _x, _) => { } } + | +++ error[E0382]: use of partially moved value: `mm` --> $DIR/issue-53114-borrow-checks.rs:29:11 @@ -28,6 +32,10 @@ LL | match mm { (_, _) => { } } | ^^ value used here after partial move | = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | match mm { (_, ref _y) => { } } + | +++ error[E0382]: use of moved value: `m` --> $DIR/issue-53114-borrow-checks.rs:36:16 @@ -48,6 +56,10 @@ LL | if let (_, _y) = mm { } | ^^ value used here after partial move | = note: partial move occurs because `mm.0` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let (ref _x, _) = mm { } + | +++ error[E0382]: use of partially moved value: `mm` --> $DIR/issue-53114-borrow-checks.rs:43:21 @@ -59,6 +71,10 @@ LL | if let (_, _) = mm { } | ^^ value used here after partial move | = note: partial move occurs because `mm.1` has type `M`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | if let (_, ref _y) = mm { } + | +++ error: aborting due to 6 previous errors diff --git a/src/test/ui/binop/binop-move-semantics.stderr b/src/test/ui/binop/binop-move-semantics.stderr index 695b01d5ee3..994eaf9d8c7 100644 --- a/src/test/ui/binop/binop-move-semantics.stderr +++ b/src/test/ui/binop/binop-move-semantics.stderr @@ -32,6 +32,10 @@ LL | + LL | x.clone(); | ^^^^^^^^^ value borrowed here after move | +help: consider cloning the value if the performance cost is acceptable + | +LL | x.clone() + | ++++++++ help: consider further restricting this bound | LL | fn move_then_borrow<T: Add<Output=()> + Clone + Copy>(x: T) { diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr index 1fd1eb12851..50eee1049db 100644 --- a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr +++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr @@ -27,6 +27,11 @@ LL | a @ [.., _] => (), ... LL | &x; | ^^ value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ [.., _] => (), + | +++ error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:28:5 @@ -71,13 +76,15 @@ LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) { | - move occurs because `x` has type `Option<Test>`, which does not implement the `Copy` trait LL | match x { LL | foo @ Some(Test::Foo | Test::Bar) => (), - | --- - | | - | value moved here - | value moved here + | --- value moved here ... LL | &x; | ^^ value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref foo @ Some(Test::Foo | Test::Bar) => (), + | +++ error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:86:5 @@ -122,13 +129,15 @@ LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) | - move occurs because `x` has type `[Option<Test>; 4]`, which does not implement the `Copy` trait LL | match x { LL | a @ [.., Some(Test::Foo | Test::Bar)] => (), - | - - | | - | value moved here - | value moved here + | - value moved here ... LL | &x; | ^^ value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ [.., Some(Test::Foo | Test::Bar)] => (), + | +++ error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:144:5 diff --git a/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr b/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr index 17b93106615..d2e9497d079 100644 --- a/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr +++ b/src/test/ui/borrowck/borrowck-consume-unsize-vec.stderr @@ -7,6 +7,18 @@ LL | consume(b); | - value moved here LL | consume(b); | ^ value used here after move + | +note: consider changing this parameter type in function `consume` to borrow instead if owning the value isn't necessary + --> $DIR/borrowck-consume-unsize-vec.rs:3:15 + | +LL | fn consume(_: Box<[i32]>) { + | ------- ^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | consume(b.clone()); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr b/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr index 4e20bbf1757..ed7e883ca63 100644 --- a/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr +++ b/src/test/ui/borrowck/borrowck-consume-upcast-box.stderr @@ -7,6 +7,14 @@ LL | consume(b); | - value moved here LL | consume(b); | ^ value used here after move + | +note: consider changing this parameter type in function `consume` to borrow instead if owning the value isn't necessary + --> $DIR/borrowck-consume-upcast-box.rs:5:15 + | +LL | fn consume(_: Box<dyn Foo>) { + | ------- ^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr index cd0d2fee942..eaf4bb38bc5 100644 --- a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr +++ b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr @@ -9,6 +9,11 @@ LL | Some(_) if { drop(my_str); false } => {} LL | Some(_) => {} LL | None => { foo(my_str); } | ^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if { drop(my_str.clone()); false } => {} + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr index 0dd720ff6ce..e1b99162088 100644 --- a/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr +++ b/src/test/ui/borrowck/borrowck-loan-in-overloaded-op.stderr @@ -7,6 +7,11 @@ LL | let _y = {x} + x.clone(); // the `{x}` forces a move to occur | - ^^^^^^^^^ value borrowed here after move | | | value moved here + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = {x.clone()} + x.clone(); // the `{x}` forces a move to occur + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr index 346b82a2666..67b00c1dd90 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr @@ -8,6 +8,10 @@ LL | [.., _y] => {} | ^^ value used here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ error[E0382]: use of partially moved value: `a[..]` --> $DIR/borrowck-move-out-from-array-match.rs:23:14 @@ -19,6 +23,10 @@ LL | [.., _y] => {} | ^^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ error[E0382]: use of moved value: `a[..].0` --> $DIR/borrowck-move-out-from-array-match.rs:33:15 @@ -30,6 +38,10 @@ LL | [.., (_y, _)] => {} | ^^ value used here after move | = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-match.rs:44:11 @@ -41,6 +53,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _x, _, _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-match.rs:55:11 @@ -52,6 +68,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., ref _x] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-match.rs:66:11 @@ -63,6 +83,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [(ref _x, _), _, _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-match.rs:77:11 @@ -74,6 +98,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., (ref _x, _)] => {} + | +++ error[E0382]: use of moved value: `a[..].0` --> $DIR/borrowck-move-out-from-array-match.rs:89:11 @@ -85,6 +113,10 @@ LL | [(_x, _), _, _] => {} | ^^ value used here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _y @ .., _, _] => {} + | +++ error[E0382]: use of moved value: `a[..].0` --> $DIR/borrowck-move-out-from-array-match.rs:99:15 @@ -96,6 +128,10 @@ LL | [.., (_x, _)] => {} | ^^ value used here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _y @ ..] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-match.rs:110:11 @@ -107,6 +143,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref x @ .., _] => {} + | +++ error: aborting due to 10 previous errors diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr index 6c6a25c251e..47429ea3eeb 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr @@ -8,6 +8,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11 @@ -19,6 +23,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11 @@ -30,6 +38,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _x, _, _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11 @@ -41,6 +53,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., ref _x] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11 @@ -52,6 +68,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [(ref _x, _), _, _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11 @@ -63,6 +83,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., (ref _x, _)] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11 @@ -74,6 +98,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, ref _y @ ..] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11 @@ -85,6 +113,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _y @ .., _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11 @@ -96,6 +128,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref x @ .., _, _] => {} + | +++ error: aborting due to 9 previous errors diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr index 77702e145df..bfab13d42d2 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr @@ -8,6 +8,10 @@ LL | [.., ref _y] => {} | ^^^^^^ value borrowed here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ error[E0382]: borrow of partially moved value: `a[..]` --> $DIR/borrowck-move-out-from-array-use-match.rs:23:14 @@ -19,6 +23,10 @@ LL | [.., ref _y] => {} | ^^^^^^ value borrowed here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ error[E0382]: borrow of moved value: `a[..].0` --> $DIR/borrowck-move-out-from-array-use-match.rs:33:15 @@ -30,6 +38,10 @@ LL | [.., (ref _y, _)] => {} | ^^^^^^ value borrowed here after move | = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:44:11 @@ -41,6 +53,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _x, _, _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:55:11 @@ -52,6 +68,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., ref _x] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:66:11 @@ -63,6 +83,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [(ref _x, _), _, _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:77:11 @@ -74,6 +98,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., (ref _x, _)] => {} + | +++ error[E0382]: borrow of moved value: `a[..]` --> $DIR/borrowck-move-out-from-array-use-match.rs:89:11 @@ -85,6 +113,10 @@ LL | [(ref _x, _), _, _] => {} | ^^^^^^ value borrowed here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _y @ .., _, _] => {} + | +++ error[E0382]: borrow of moved value: `a[..]` --> $DIR/borrowck-move-out-from-array-use-match.rs:99:15 @@ -96,6 +128,10 @@ LL | [.., (ref _x, _)] => {} | ^^^^^^ value borrowed here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _y @ ..] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:110:11 @@ -107,6 +143,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref x @ .., _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:123:5 @@ -118,6 +158,10 @@ LL | a[2] = Default::default(); | ^^^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:131:5 @@ -129,6 +173,10 @@ LL | a[2].1 = Default::default(); | ^^^^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:139:5 @@ -140,6 +188,10 @@ LL | a[0] = Default::default(); | ^^^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x @ ..] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-match.rs:147:5 @@ -151,6 +203,10 @@ LL | a[0].1 = Default::default(); | ^^^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x @ ..] => {} + | +++ error: aborting due to 14 previous errors diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr index 6cc2c2f7a98..8412c24fe61 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr @@ -8,6 +8,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, ref _x] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11 @@ -19,6 +23,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, _, (ref _x, _)] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11 @@ -30,6 +38,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _x, _, _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11 @@ -41,6 +53,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., ref _x] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11 @@ -52,6 +68,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [(ref _x, _), _, _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11 @@ -63,6 +83,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [.., (ref _x, _)] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11 @@ -74,6 +98,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [_, ref _y @ ..] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11 @@ -85,6 +113,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref _y @ .., _] => {} + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11 @@ -96,6 +128,10 @@ LL | match a { | ^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | [ref x @ .., _, _] => {} + | +++ error: aborting due to 9 previous errors diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr index 9add7553afa..e2aeaafc63c 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr @@ -7,6 +7,10 @@ LL | let [.., ref _y] = a; | ^^^^^^ value borrowed here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x] = a; + | +++ error[E0382]: borrow of partially moved value: `a[..]` --> $DIR/borrowck-move-out-from-array-use.rs:16:14 @@ -17,6 +21,10 @@ LL | let [.., ref _y] = a; | ^^^^^^ value borrowed here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ error[E0382]: borrow of moved value: `a[..].0` --> $DIR/borrowck-move-out-from-array-use.rs:22:15 @@ -27,6 +35,10 @@ LL | let [.., (ref _y, _)] = a; | ^^^^^^ value borrowed here after move | = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ error[E0382]: borrow of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:30:10 @@ -37,6 +49,10 @@ LL | let [ref _y @ .., _, _] = a; | ^^^^^^ value borrowed here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref _x, _, _] = a; + | +++ error[E0382]: borrow of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:36:16 @@ -47,6 +63,10 @@ LL | let [_, _, ref _y @ ..] = a; | ^^^^^^ value borrowed here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [.., ref _x] = a; + | +++ error[E0382]: borrow of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:42:10 @@ -57,6 +77,10 @@ LL | let [ref _y @ .., _, _] = a; | ^^^^^^ value borrowed here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [(ref _x, _), _, _] = a; + | +++ error[E0382]: borrow of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:48:16 @@ -67,6 +91,10 @@ LL | let [_, _, ref _y @ ..] = a; | ^^^^^^ value borrowed here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [.., (ref _x, _)] = a; + | +++ error[E0382]: borrow of moved value: `a[..]` --> $DIR/borrowck-move-out-from-array-use.rs:54:11 @@ -77,6 +105,10 @@ LL | let [(ref _x, _), _, _] = a; | ^^^^^^ value borrowed here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref _y @ .., _, _] = a; + | +++ error[E0382]: borrow of moved value: `a[..]` --> $DIR/borrowck-move-out-from-array-use.rs:60:15 @@ -87,6 +119,10 @@ LL | let [.., (ref _x, _)] = a; | ^^^^^^ value borrowed here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _y @ ..] = a; + | +++ error[E0382]: borrow of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:68:13 @@ -97,6 +133,10 @@ LL | let [_, ref _y @ ..] = a; | ^^^^^^ value borrowed here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref x @ .., _] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:76:5 @@ -107,6 +147,10 @@ LL | a[2] = Default::default(); | ^^^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:82:5 @@ -117,6 +161,10 @@ LL | a[2].1 = Default::default(); | ^^^^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:88:5 @@ -127,6 +175,10 @@ LL | a[0] = Default::default(); | ^^^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x @ ..] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array-use.rs:94:5 @@ -137,6 +189,10 @@ LL | a[0].1 = Default::default(); | ^^^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x @ ..] = a; + | +++ error: aborting due to 14 previous errors diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr index 363effcfe53..dd456681f57 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr @@ -7,6 +7,10 @@ LL | let [.., _y] = a; | ^^ value used here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _x] = a; + | +++ error[E0382]: use of partially moved value: `a[..]` --> $DIR/borrowck-move-out-from-array.rs:16:14 @@ -17,6 +21,10 @@ LL | let [.., _y] = a; | ^^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ error[E0382]: use of moved value: `a[..].0` --> $DIR/borrowck-move-out-from-array.rs:22:15 @@ -27,6 +35,10 @@ LL | let [.., (_y, _)] = a; | ^^ value used here after move | = note: move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, (ref _x, _)] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array.rs:30:10 @@ -37,6 +49,10 @@ LL | let [_y @ .., _, _] = a; | ^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref _x, _, _] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array.rs:36:16 @@ -47,6 +63,10 @@ LL | let [_, _, _y @ ..] = a; | ^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [.., ref _x] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array.rs:42:10 @@ -57,6 +77,10 @@ LL | let [_y @ .., _, _] = a; | ^^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [(ref _x, _), _, _] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array.rs:48:16 @@ -67,6 +91,10 @@ LL | let [_, _, _y @ ..] = a; | ^^ value used here after partial move | = note: partial move occurs because `a[..].0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [.., (ref _x, _)] = a; + | +++ error[E0382]: use of moved value: `a[..].0` --> $DIR/borrowck-move-out-from-array.rs:54:11 @@ -77,6 +105,10 @@ LL | let [(_x, _), _, _] = a; | ^^ value used here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref _y @ .., _, _] = a; + | +++ error[E0382]: use of moved value: `a[..].0` --> $DIR/borrowck-move-out-from-array.rs:60:15 @@ -87,6 +119,10 @@ LL | let [.., (_x, _)] = a; | ^^ value used here after move | = note: move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [_, _, ref _y @ ..] = a; + | +++ error[E0382]: use of partially moved value: `a` --> $DIR/borrowck-move-out-from-array.rs:68:13 @@ -97,6 +133,10 @@ LL | let [_, _y @ ..] = a; | ^^ value used here after partial move | = note: partial move occurs because `a[..]` has type `(String, String)`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let [ref x @ .., _] = a; + | +++ error: aborting due to 10 previous errors diff --git a/src/test/ui/borrowck/borrowck-multiple-captures.stderr b/src/test/ui/borrowck/borrowck-multiple-captures.stderr index 86d2955e236..f94cbc30db4 100644 --- a/src/test/ui/borrowck/borrowck-multiple-captures.stderr +++ b/src/test/ui/borrowck/borrowck-multiple-captures.stderr @@ -40,6 +40,11 @@ LL | thread::spawn(move|| { ... LL | drop(x1); | -- use occurs due to use in closure + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x1.clone()); + | ++++++++ error[E0382]: use of moved value: `x2` --> $DIR/borrowck-multiple-captures.rs:27:19 @@ -53,6 +58,11 @@ LL | thread::spawn(move|| { ... LL | drop(x2); | -- use occurs due to use in closure + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x2.clone()); + | ++++++++ error[E0382]: use of moved value: `x` --> $DIR/borrowck-multiple-captures.rs:41:14 @@ -100,6 +110,11 @@ LL | thread::spawn(move|| { LL | LL | drop(x); | - use occurs due to use in closure + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x.clone()); + | ++++++++ error: aborting due to 8 previous errors diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr index e01c26adcfc..fb0e274c291 100644 --- a/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr +++ b/src/test/ui/borrowck/borrowck-overloaded-index-move-index.stderr @@ -33,6 +33,11 @@ LL | println!("{}", f[s]); ... LL | f[s] = 10; | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | println!("{}", f[s.clone()]); + | ++++++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/borrowck-reinit.stderr b/src/test/ui/borrowck/borrowck-reinit.stderr index 22253cd96f1..f785900d53f 100644 --- a/src/test/ui/borrowck/borrowck-reinit.stderr +++ b/src/test/ui/borrowck/borrowck-reinit.stderr @@ -8,6 +8,11 @@ LL | drop(x); | - value moved here LL | let _ = (1,x); | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x.clone()); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr index d33115988a9..ad898fcabd9 100644 --- a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr +++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr @@ -8,6 +8,11 @@ LL | Some(_) if { drop(a); false } => None, | - value moved here LL | x => x, | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if { drop(a.clone()); false } => None, + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-41962.stderr b/src/test/ui/borrowck/issue-41962.stderr index b20cc6d8cf5..716cc9d0c8b 100644 --- a/src/test/ui/borrowck/issue-41962.stderr +++ b/src/test/ui/borrowck/issue-41962.stderr @@ -5,7 +5,7 @@ LL | if let Some(thing) = maybe { | ^^^^^ value moved here, in previous iteration of loop | = note: move occurs because value has type `Vec<bool>`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `maybe.0` +help: borrow this binding in the pattern to avoid moving the value | LL | if let Some(ref thing) = maybe { | +++ diff --git a/src/test/ui/borrowck/issue-83760.stderr b/src/test/ui/borrowck/issue-83760.stderr index beeda5685dc..2552fff860c 100644 --- a/src/test/ui/borrowck/issue-83760.stderr +++ b/src/test/ui/borrowck/issue-83760.stderr @@ -8,6 +8,10 @@ LL | val = None; | ---------- this reinitialization might get skipped | = note: move occurs because value has type `Struct`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | while let Some(ref foo) = val { + | +++ error[E0382]: use of moved value: `foo` --> $DIR/issue-83760.rs:21:14 diff --git a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr index c6931ba7257..55948afca73 100644 --- a/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr +++ b/src/test/ui/borrowck/move-in-pattern-mut-in-loop.stderr @@ -5,7 +5,7 @@ LL | if let Some(mut _x) = opt {} | ^^^^^^ value moved here, in previous iteration of loop | = note: move occurs because value has type `&mut i32`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `opt.0` +help: borrow this binding in the pattern to avoid moving the value | LL | if let Some(ref mut _x) = opt {} | +++ diff --git a/src/test/ui/borrowck/move-in-pattern-mut.stderr b/src/test/ui/borrowck/move-in-pattern-mut.stderr index 2bf34b32176..dd3471e2c8b 100644 --- a/src/test/ui/borrowck/move-in-pattern-mut.stderr +++ b/src/test/ui/borrowck/move-in-pattern-mut.stderr @@ -8,7 +8,7 @@ LL | foo(s); | ^ value used here after partial move | = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `s.0` +help: borrow this binding in the pattern to avoid moving the value | LL | if let Some(ref mut x) = s { | +++ @@ -23,7 +23,7 @@ LL | bar(e); | ^ value used here after partial move | = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `e.s` +help: borrow this binding in the pattern to avoid moving the value | LL | let E::V { s: ref mut x } = e; | +++ diff --git a/src/test/ui/borrowck/move-in-pattern.stderr b/src/test/ui/borrowck/move-in-pattern.stderr index 6b84c0032cd..250acbe5928 100644 --- a/src/test/ui/borrowck/move-in-pattern.stderr +++ b/src/test/ui/borrowck/move-in-pattern.stderr @@ -8,7 +8,7 @@ LL | foo(s); | ^ value used here after partial move | = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `s.0` +help: borrow this binding in the pattern to avoid moving the value | LL | if let Some(ref x) = s { | +++ @@ -23,7 +23,7 @@ LL | bar(e); | ^ value used here after partial move | = note: partial move occurs because value has type `S`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `e.s` +help: borrow this binding in the pattern to avoid moving the value | LL | let E::V { s: ref x } = e; | +++ diff --git a/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr b/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr index 8b05b238822..74e7067c9af 100644 --- a/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr +++ b/src/test/ui/borrowck/mut-borrow-in-loop-2.stderr @@ -4,9 +4,17 @@ error[E0382]: use of moved value: `value` LL | fn this_does_not<'a, R>(value: &'a mut Events<R>) { | ----- move occurs because `value` has type `&mut Events<R>`, which does not implement the `Copy` trait LL | for _ in 0..3 { + | ------------- inside of this loop LL | Other::handle(value); | ^^^^^ value moved here, in previous iteration of loop | +note: consider changing this parameter type in function `handle` to borrow instead if owning the value isn't necessary + --> $DIR/mut-borrow-in-loop-2.rs:9:22 + | +LL | fn handle(value: T) -> Self; + | ------ ^ this parameter takes ownership of the value + | | + | in this function help: consider creating a fresh reborrow of `value` here | LL | Other::handle(&mut *value); diff --git a/src/test/ui/borrowck/or-patterns.stderr b/src/test/ui/borrowck/or-patterns.stderr index dd5797c3f79..9501798bb06 100644 --- a/src/test/ui/borrowck/or-patterns.stderr +++ b/src/test/ui/borrowck/or-patterns.stderr @@ -8,6 +8,10 @@ LL | &x.0 .0; | ^^^^^^^ value borrowed here after move | = note: move occurs because `x.0.0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ((ref y, _) | (_, y),) => (), + | +++ error[E0382]: borrow of moved value: `x.0.1` --> $DIR/or-patterns.rs:10:5 @@ -19,6 +23,10 @@ LL | &x.0 .1; | ^^^^^^^ value borrowed here after move | = note: move occurs because `x.0.1` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ((y, _) | (_, ref y),) => (), + | +++ error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable --> $DIR/or-patterns.rs:18:5 @@ -77,6 +85,10 @@ LL | &x.0 .0; | ^^^^^^^ value borrowed here after move | = note: move occurs because `x.0.0` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ((ref y, _) | (_, y),) = x; + | +++ error[E0382]: borrow of moved value: `x.0.1` --> $DIR/or-patterns.rs:40:5 @@ -88,6 +100,10 @@ LL | &x.0 .1; | ^^^^^^^ value borrowed here after move | = note: move occurs because `x.0.1` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ((y, _) | (_, ref y),) = x; + | +++ error[E0502]: cannot borrow `x.0.0` as mutable because it is also borrowed as immutable --> $DIR/or-patterns.rs:46:5 diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr index 9072cc925ff..080f6c39449 100644 --- a/src/test/ui/codemap_tests/tab_3.stderr +++ b/src/test/ui/codemap_tests/tab_3.stderr @@ -15,6 +15,10 @@ note: this function takes ownership of the receiver `self`, which moves `some_ve LL | fn into_iter(self) -> Self::IntoIter; | ^^^^ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | some_vec.clone().into_iter(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr index 7357551c4a7..f030228f71a 100644 --- a/src/test/ui/drop/repeat-drop-2.stderr +++ b/src/test/ui/drop/repeat-drop-2.stderr @@ -7,6 +7,11 @@ LL | let _bar = foo; | --- value moved here LL | let _baz = [foo; 0]; | ^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _bar = foo.clone(); + | ++++++++ error[E0493]: destructor of `String` cannot be evaluated at compile-time --> $DIR/repeat-drop-2.rs:7:25 diff --git a/src/test/ui/dyn-star/dispatch-on-pin-mut.rs b/src/test/ui/dyn-star/dispatch-on-pin-mut.rs new file mode 100644 index 00000000000..5774c8b2a67 --- /dev/null +++ b/src/test/ui/dyn-star/dispatch-on-pin-mut.rs @@ -0,0 +1,52 @@ +// run-pass +// edition:2021 +// check-run-results + +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +use std::future::Future; + +async fn foo(f: dyn* Future<Output = i32>) { + println!("value: {}", f.await); +} + +async fn async_main() { + foo(Box::pin(async { 1 })).await +} + +// ------------------------------------------------------------------------- // +// Implementation Details Below... + +use std::pin::Pin; +use std::task::*; + +pub fn noop_waker() -> Waker { + let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE); + + // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld + unsafe { Waker::from_raw(raw) } +} + +const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop); + +unsafe fn noop_clone(_p: *const ()) -> RawWaker { + RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE) +} + +unsafe fn noop(_p: *const ()) {} + +fn main() { + let mut fut = async_main(); + + // Poll loop, just to test the future... + let waker = noop_waker(); + let ctx = &mut Context::from_waker(&waker); + + loop { + match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } { + Poll::Pending => {} + Poll::Ready(()) => break, + } + } +} diff --git a/src/test/ui/dyn-star/dispatch-on-pin-mut.run.stdout b/src/test/ui/dyn-star/dispatch-on-pin-mut.run.stdout new file mode 100644 index 00000000000..96c5ca6985f --- /dev/null +++ b/src/test/ui/dyn-star/dispatch-on-pin-mut.run.stdout @@ -0,0 +1 @@ +value: 1 diff --git a/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr b/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr new file mode 100644 index 00000000000..fdf74aa7efe --- /dev/null +++ b/src/test/ui/dyn-star/dispatch-on-pin-mut.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/dispatch-on-pin-mut.rs:5:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs index b4ff8a22286..c12b16f1605 100644 --- a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs +++ b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.rs @@ -1,7 +1,8 @@ -// check-pass +// run-pass +// check-run-results #![feature(dyn_star)] -#![allow(incomplete_features)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes trait AddOne { fn add1(&mut self) -> usize; diff --git a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout new file mode 100644 index 00000000000..b4db3ed707d --- /dev/null +++ b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.run.stdout @@ -0,0 +1,2 @@ +43 +44 diff --git a/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr new file mode 100644 index 00000000000..933c133831a --- /dev/null +++ b/src/test/ui/dyn-star/dont-unsize-coerce-dyn-star.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/dont-unsize-coerce-dyn-star.rs:4:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs new file mode 100644 index 00000000000..a4eb669e321 --- /dev/null +++ b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.rs @@ -0,0 +1,13 @@ +#![feature(dyn_star, trait_upcasting)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +trait A: B {} +trait B {} +impl A for usize {} +impl B for usize {} + +fn main() { + let x: Box<dyn* A> = Box::new(1usize as dyn* A); + let y: Box<dyn* B> = x; + //~^ ERROR mismatched types +} diff --git a/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr new file mode 100644 index 00000000000..2fc751b3b4a --- /dev/null +++ b/src/test/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr @@ -0,0 +1,23 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/no-unsize-coerce-dyn-trait.rs:1:12 + | +LL | #![feature(dyn_star, trait_upcasting)] + | ^^^^^^^^ + | + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/no-unsize-coerce-dyn-trait.rs:11:26 + | +LL | let y: Box<dyn* B> = x; + | ----------- ^ expected trait `B`, found trait `A` + | | + | expected due to this + | + = note: expected struct `Box<dyn* B>` + found struct `Box<dyn* A>` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/dyn-star/upcast.rs b/src/test/ui/dyn-star/upcast.rs index cee76ada7df..c667ac143a3 100644 --- a/src/test/ui/dyn-star/upcast.rs +++ b/src/test/ui/dyn-star/upcast.rs @@ -1,7 +1,6 @@ -// run-pass +// known-bug: #104800 #![feature(dyn_star, trait_upcasting)] -#![allow(incomplete_features)] trait Foo: Bar { fn hello(&self); diff --git a/src/test/ui/dyn-star/upcast.stderr b/src/test/ui/dyn-star/upcast.stderr new file mode 100644 index 00000000000..6a95f7754e6 --- /dev/null +++ b/src/test/ui/dyn-star/upcast.stderr @@ -0,0 +1,20 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/upcast.rs:3:12 + | +LL | #![feature(dyn_star, trait_upcasting)] + | ^^^^^^^^ + | + = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: `dyn* Foo` needs to be a pointer-sized type + --> $DIR/upcast.rs:30:23 + | +LL | let w: dyn* Bar = w; + | ^ `dyn* Foo` needs to be a pointer-sized type + | + = help: the trait `PointerSized` is not implemented for `dyn* Foo` + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-23122-2.rs b/src/test/ui/issues/issue-23122-2.rs index 95e1f60d8b0..338789c2e87 100644 --- a/src/test/ui/issues/issue-23122-2.rs +++ b/src/test/ui/issues/issue-23122-2.rs @@ -1,3 +1,4 @@ +// normalize-stderr-test: "long-type-\d+" -> "long-type-hash" trait Next { type Next: Next; } diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr index f6cda3de5c7..5828e027b59 100644 --- a/src/test/ui/issues/issue-23122-2.stderr +++ b/src/test/ui/issues/issue-23122-2.stderr @@ -1,10 +1,16 @@ -error[E0275]: overflow evaluating the requirement `<T as Next>::Next` - --> $DIR/issue-23122-2.rs:10:17 +error[E0275]: overflow evaluating the requirement `<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized` + --> $DIR/issue-23122-2.rs:11:17 | LL | type Next = <GetNext<T::Next> as Next>::Next; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`) +note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next` + --> $DIR/issue-23122-2.rs:10:15 + | +LL | impl<T: Next> Next for GetNext<T> { + | ^^^^ ^^^^^^^^^^ + = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-23122-2/issue-23122-2.long-type-hash.txt' error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29723.stderr b/src/test/ui/issues/issue-29723.stderr index e39ddfc81c9..92ee5cf22b7 100644 --- a/src/test/ui/issues/issue-29723.stderr +++ b/src/test/ui/issues/issue-29723.stderr @@ -9,6 +9,11 @@ LL | 0 if { drop(s); false } => String::from("oops"), ... LL | s | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | 0 if { drop(s.clone()); false } => String::from("oops"), + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-42796.stderr b/src/test/ui/issues/issue-42796.stderr index f3e0e7b20a1..f2971df5db2 100644 --- a/src/test/ui/issues/issue-42796.stderr +++ b/src/test/ui/issues/issue-42796.stderr @@ -10,6 +10,10 @@ LL | println!("{}", s); | ^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | let mut s_copy = s.clone(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index bfabe2d12f7..20d4c418e87 100644 --- a/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/src/test/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -370,23 +370,23 @@ error: layout_of(NicheFirst) = Layout { pref: $PREF_ALIGN, }, abi: ScalarPair( - Initialized { + Union { value: Int( I8, false, ), - valid_range: 0..=4, }, - Union { + Initialized { value: Int( I8, false, ), + valid_range: 0..=4, }, ), fields: Arbitrary { offsets: [ - Size(0 bytes), + Size(1 bytes), ], memory_index: [ 0, @@ -394,7 +394,7 @@ error: layout_of(NicheFirst) = Layout { }, largest_niche: Some( Niche { - offset: Size(0 bytes), + offset: Size(1 bytes), value: Int( I8, false, @@ -429,29 +429,29 @@ error: layout_of(NicheFirst) = Layout { I8, false, ), - valid_range: 0..=2, + valid_range: 0..=255, }, Initialized { value: Int( I8, false, ), - valid_range: 0..=255, + valid_range: 0..=2, }, ), fields: Arbitrary { offsets: [ - Size(0 bytes), Size(1 bytes), + Size(0 bytes), ], memory_index: [ - 0, 1, + 0, ], }, largest_niche: Some( Niche { - offset: Size(0 bytes), + offset: Size(1 bytes), value: Int( I8, false, diff --git a/src/test/ui/liveness/liveness-move-call-arg.stderr b/src/test/ui/liveness/liveness-move-call-arg.stderr index 7c0e916eddc..d14cd6cb4e0 100644 --- a/src/test/ui/liveness/liveness-move-call-arg.stderr +++ b/src/test/ui/liveness/liveness-move-call-arg.stderr @@ -3,9 +3,23 @@ error[E0382]: use of moved value: `x` | LL | let x: Box<isize> = Box::new(25); | - move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait -... +LL | +LL | loop { + | ---- inside of this loop LL | take(x); | ^ value moved here, in previous iteration of loop + | +note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary + --> $DIR/liveness-move-call-arg.rs:1:13 + | +LL | fn take(_x: Box<isize>) {} + | ---- ^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | take(x.clone()); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-move-in-loop.stderr b/src/test/ui/liveness/liveness-move-in-loop.stderr index 832d4f8fa03..a060914f178 100644 --- a/src/test/ui/liveness/liveness-move-in-loop.stderr +++ b/src/test/ui/liveness/liveness-move-in-loop.stderr @@ -4,8 +4,22 @@ error[E0382]: use of moved value: `y` LL | let y: Box<isize> = 42.into(); | - move occurs because `y` has type `Box<isize>`, which does not implement the `Copy` trait ... +LL | loop { + | ---- inside of this loop +LL | println!("{}", y); +LL | loop { + | ---- inside of this loop +LL | loop { + | ---- inside of this loop +LL | loop { + | ---- inside of this loop LL | x = y; | ^ value moved here, in previous iteration of loop + | +help: consider cloning the value if the performance cost is acceptable + | +LL | x = y.clone(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-move-in-while.stderr b/src/test/ui/liveness/liveness-move-in-while.stderr index b04a05fe409..4dff7447dd7 100644 --- a/src/test/ui/liveness/liveness-move-in-while.stderr +++ b/src/test/ui/liveness/liveness-move-in-while.stderr @@ -24,12 +24,22 @@ error[E0382]: borrow of moved value: `y` LL | let y: Box<isize> = 42.into(); | - move occurs because `y` has type `Box<isize>`, which does not implement the `Copy` trait ... +LL | loop { + | ---- inside of this loop LL | println!("{}", y); | ^ value borrowed here after move LL | while true { while true { while true { x = y; x.clone(); } } } - | - value moved here, in previous iteration of loop + | ---------- ---------- ---------- - value moved here, in previous iteration of loop + | | | | + | | | inside of this loop + | | inside of this loop + | inside of this loop | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | while true { while true { while true { x = y.clone(); x.clone(); } } } + | ++++++++ error: aborting due to previous error; 3 warnings emitted diff --git a/src/test/ui/liveness/liveness-use-after-move.stderr b/src/test/ui/liveness/liveness-use-after-move.stderr index 218b93c8e4f..3accba197a1 100644 --- a/src/test/ui/liveness/liveness-use-after-move.stderr +++ b/src/test/ui/liveness/liveness-use-after-move.stderr @@ -10,6 +10,10 @@ LL | println!("{}", *x); | ^^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | let y = x.clone(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-use-after-send.stderr b/src/test/ui/liveness/liveness-use-after-send.stderr index 8edc0463fe5..65d55ca8f70 100644 --- a/src/test/ui/liveness/liveness-use-after-send.stderr +++ b/src/test/ui/liveness/liveness-use-after-send.stderr @@ -8,7 +8,16 @@ LL | send(ch, message); LL | println!("{}", message); | ^^^^^^^ value borrowed here after move | +note: consider changing this parameter type in function `send` to borrow instead if owning the value isn't necessary + --> $DIR/liveness-use-after-send.rs:3:54 + | +LL | fn send<T:Send + std::fmt::Debug>(ch: Chan<T>, data: T) { + | ---- in this function ^ this parameter takes ownership of the value = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | send(ch, message.clone()); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/borrow-closures-instead-of-move.stderr b/src/test/ui/moves/borrow-closures-instead-of-move.stderr index 3146b695900..9a84ddef7e6 100644 --- a/src/test/ui/moves/borrow-closures-instead-of-move.stderr +++ b/src/test/ui/moves/borrow-closures-instead-of-move.stderr @@ -4,9 +4,17 @@ error[E0382]: use of moved value: `f` LL | fn takes_fn(f: impl Fn()) { | - move occurs because `f` has type `impl Fn()`, which does not implement the `Copy` trait LL | loop { + | ---- inside of this loop LL | takes_fnonce(f); | ^ value moved here, in previous iteration of loop | +note: consider changing this parameter type in function `takes_fnonce` to borrow instead if owning the value isn't necessary + --> $DIR/borrow-closures-instead-of-move.rs:34:20 + | +LL | fn takes_fnonce(_: impl FnOnce()) {} + | ------------ ^^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function help: consider borrowing `f` | LL | takes_fnonce(&f); @@ -24,6 +32,13 @@ LL | takes_fnonce(m); LL | takes_fnonce(m); | ^ value used here after move | +note: consider changing this parameter type in function `takes_fnonce` to borrow instead if owning the value isn't necessary + --> $DIR/borrow-closures-instead-of-move.rs:34:20 + | +LL | fn takes_fnonce(_: impl FnOnce()) {} + | ------------ ^^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this function help: consider mutably borrowing `m` | LL | takes_fnonce(&mut m); diff --git a/src/test/ui/moves/issue-46099-move-in-macro.stderr b/src/test/ui/moves/issue-46099-move-in-macro.stderr index baa87e3e9fd..94bc9e6f454 100644 --- a/src/test/ui/moves/issue-46099-move-in-macro.stderr +++ b/src/test/ui/moves/issue-46099-move-in-macro.stderr @@ -5,6 +5,11 @@ LL | let b = Box::new(true); | - move occurs because `b` has type `Box<bool>`, which does not implement the `Copy` trait LL | test!({b}); | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | test!({b.clone()}); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.rs b/src/test/ui/moves/issue-72649-uninit-in-loop.rs index d76b69ecdc8..56c225bab8c 100644 --- a/src/test/ui/moves/issue-72649-uninit-in-loop.rs +++ b/src/test/ui/moves/issue-72649-uninit-in-loop.rs @@ -25,7 +25,7 @@ fn moved_here_1() { fn moved_here_2() { let value = NonCopy{}; //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait - loop { + loop { //~ NOTE inside of this loop let _used = value; //~^ NOTE value moved here loop { @@ -38,7 +38,7 @@ fn moved_here_2() { fn moved_loop_1() { let value = NonCopy{}; //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait - loop { + loop { //~ NOTE inside of this loop let _used = value; //~ ERROR use of moved value: `value` //~^ NOTE value moved here, in previous iteration of loop } @@ -49,7 +49,7 @@ fn moved_loop_2() { //~^ NOTE move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait let _used = value; value = NonCopy{}; - loop { + loop { //~ NOTE inside of this loop let _used2 = value; //~ ERROR use of moved value: `value` //~^ NOTE value moved here, in previous iteration of loop } diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr index 974994223a3..7e119fe8cda 100644 --- a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr @@ -15,7 +15,9 @@ error[E0382]: use of moved value: `value` | LL | let value = NonCopy{}; | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait -... +LL | +LL | loop { + | ---- inside of this loop LL | let _used = value; | ----- value moved here ... @@ -27,7 +29,9 @@ error[E0382]: use of moved value: `value` | LL | let value = NonCopy{}; | ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait -... +LL | +LL | loop { + | ---- inside of this loop LL | let _used = value; | ^^^^^ value moved here, in previous iteration of loop @@ -37,6 +41,8 @@ error[E0382]: use of moved value: `value` LL | let mut value = NonCopy{}; | --------- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait ... +LL | loop { + | ---- inside of this loop LL | let _used2 = value; | ^^^^^ value moved here, in previous iteration of loop diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr index 3a686121a92..c13dc58826e 100644 --- a/src/test/ui/moves/move-fn-self-receiver.stderr +++ b/src/test/ui/moves/move-fn-self-receiver.stderr @@ -96,6 +96,10 @@ note: this function takes ownership of the receiver `self`, which moves `rc_foo` | LL | fn use_rc_self(self: Rc<Self>) {} | ^^^^ +help: consider cloning the value if the performance cost is acceptable + | +LL | rc_foo.clone().use_rc_self(); + | ++++++++ error[E0382]: use of moved value: `foo_add` --> $DIR/move-fn-self-receiver.rs:59:5 @@ -137,6 +141,11 @@ LL | for _val in explicit_into_iter.into_iter() {} | ----------- `explicit_into_iter` moved due to this method call LL | explicit_into_iter; | ^^^^^^^^^^^^^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | for _val in explicit_into_iter.clone().into_iter() {} + | ++++++++ error[E0382]: use of moved value: `container` --> $DIR/move-fn-self-receiver.rs:71:5 @@ -160,6 +169,7 @@ error[E0382]: use of moved value: `foo2` LL | let foo2 = Foo; | ---- move occurs because `foo2` has type `Foo`, which does not implement the `Copy` trait LL | loop { + | ---- inside of this loop LL | foo2.use_self(); | ^^^^ ---------- `foo2` moved due to this method call, in previous iteration of loop diff --git a/src/test/ui/moves/move-guard-same-consts.stderr b/src/test/ui/moves/move-guard-same-consts.stderr index 2048fefefa3..86e5f65248b 100644 --- a/src/test/ui/moves/move-guard-same-consts.stderr +++ b/src/test/ui/moves/move-guard-same-consts.stderr @@ -8,6 +8,18 @@ LL | (1, 2) if take(x) => (), | - value moved here LL | (1, 2) if take(x) => (), | ^ value used here after move + | +note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary + --> $DIR/move-guard-same-consts.rs:25:15 + | +LL | fn take<T>(_: T) -> bool { false } + | ---- ^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | (1, 2) if take(x.clone()) => (), + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/move-in-guard-1.stderr b/src/test/ui/moves/move-in-guard-1.stderr index 5e9aa66b90d..f04cb34d7c4 100644 --- a/src/test/ui/moves/move-in-guard-1.stderr +++ b/src/test/ui/moves/move-in-guard-1.stderr @@ -8,6 +8,18 @@ LL | (1, _) if take(x) => (), | - value moved here LL | (_, 2) if take(x) => (), | ^ value used here after move + | +note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary + --> $DIR/move-in-guard-1.rs:15:15 + | +LL | fn take<T>(_: T) -> bool { false } + | ---- ^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | (1, _) if take(x.clone()) => (), + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/move-in-guard-2.stderr b/src/test/ui/moves/move-in-guard-2.stderr index 8d636c11b78..26047861f55 100644 --- a/src/test/ui/moves/move-in-guard-2.stderr +++ b/src/test/ui/moves/move-in-guard-2.stderr @@ -6,6 +6,18 @@ LL | let x: Box<_> = Box::new(1); ... LL | (_, 2) if take(x) => (), | ^ value used here after move + | +note: consider changing this parameter type in function `take` to borrow instead if owning the value isn't necessary + --> $DIR/move-in-guard-2.rs:13:15 + | +LL | fn take<T>(_: T) -> bool { false } + | ---- ^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | (_, 2) if take(x.clone()) => (), + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr index 3cc8ca29144..a49ee31b466 100644 --- a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr +++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr @@ -13,6 +13,10 @@ note: this function takes ownership of the receiver `self`, which moves `x` | LL | fn into_iter(self) -> Self::IntoIter; | ^^^^ +help: consider cloning the value if the performance cost is acceptable + | +LL | consume(x.clone().into_iter().next().unwrap()); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr index a315bbaab33..db4382b58fc 100644 --- a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr +++ b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr @@ -8,7 +8,7 @@ LL | consume(node) + r | ^^^^ value used here after partial move | = note: partial move occurs because value has type `Box<List>`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `node.next.0` +help: borrow this binding in the pattern to avoid moving the value | LL | Some(ref right) => consume(right), | +++ diff --git a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr index ee7971691a4..0930df14805 100644 --- a/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr +++ b/src/test/ui/moves/moves-based-on-type-distribute-copy-over-paren.stderr @@ -9,6 +9,11 @@ LL | let _y = Foo { f:x }; LL | LL | touch(&x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = Foo { f:x.clone() }; + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-distribute-copy-over-paren.rs:21:11 @@ -21,6 +26,11 @@ LL | let _y = Foo { f:(((x))) }; LL | LL | touch(&x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = Foo { f:(((x))).clone() }; + | ++++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr index 9bcec36740d..838b1282cb4 100644 --- a/src/test/ui/moves/moves-based-on-type-exprs.stderr +++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr @@ -7,6 +7,11 @@ LL | let _y = Foo { f:x }; | - value moved here LL | touch(&x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = Foo { f:x.clone() }; + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:18:11 @@ -17,6 +22,11 @@ LL | let _y = (x, 3); | - value moved here LL | touch(&x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = (x.clone(), 3); + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:35:11 @@ -29,6 +39,11 @@ LL | x ... LL | touch(&x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | x.clone() + | ++++++++ error[E0382]: borrow of moved value: `y` --> $DIR/moves-based-on-type-exprs.rs:36:11 @@ -41,6 +56,11 @@ LL | y ... LL | touch(&y); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | y.clone() + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:46:11 @@ -53,6 +73,11 @@ LL | true => x, ... LL | touch(&x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | true => x.clone(), + | ++++++++ error[E0382]: borrow of moved value: `y` --> $DIR/moves-based-on-type-exprs.rs:47:11 @@ -65,6 +90,11 @@ LL | false => y ... LL | touch(&y); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | false => y.clone() + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:58:11 @@ -77,6 +107,18 @@ LL | _ if guard(x) => 10, ... LL | touch(&x); | ^^ value borrowed here after move + | +note: consider changing this parameter type in function `guard` to borrow instead if owning the value isn't necessary + --> $DIR/moves-based-on-type-exprs.rs:6:14 + | +LL | fn guard(_s: String) -> bool {panic!()} + | ----- ^^^^^^ this parameter takes ownership of the value + | | + | in this function +help: consider cloning the value if the performance cost is acceptable + | +LL | _ if guard(x.clone()) => 10, + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:65:11 @@ -87,6 +129,11 @@ LL | let _y = [x]; | - value moved here LL | touch(&x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = [x.clone()]; + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:71:11 @@ -97,6 +144,11 @@ LL | let _y = vec![x]; | - value moved here LL | touch(&x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = vec![x.clone()]; + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:77:11 @@ -113,6 +165,10 @@ note: this function takes ownership of the receiver `self`, which moves `x` | LL | fn into_iter(self) -> Self::IntoIter; | ^^^^ +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = x.clone().into_iter().next().unwrap(); + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/moves-based-on-type-exprs.rs:83:11 @@ -129,6 +185,10 @@ note: this function takes ownership of the receiver `self`, which moves `x` | LL | fn into_iter(self) -> Self::IntoIter; | ^^^^ +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = [x.clone().into_iter().next().unwrap(); 1]; + | ++++++++ error: aborting due to 11 previous errors diff --git a/src/test/ui/moves/moves-based-on-type-match-bindings.stderr b/src/test/ui/moves/moves-based-on-type-match-bindings.stderr index ad1a2db8b52..225935532ea 100644 --- a/src/test/ui/moves/moves-based-on-type-match-bindings.stderr +++ b/src/test/ui/moves/moves-based-on-type-match-bindings.stderr @@ -8,6 +8,10 @@ LL | touch(&x); | ^^ value borrowed here after partial move | = note: partial move occurs because `x.f` has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | Foo {ref f} => {} + | +++ error: aborting due to previous error diff --git a/src/test/ui/moves/moves-based-on-type-tuple.stderr b/src/test/ui/moves/moves-based-on-type-tuple.stderr index eef8ce61fa9..0bcce301263 100644 --- a/src/test/ui/moves/moves-based-on-type-tuple.stderr +++ b/src/test/ui/moves/moves-based-on-type-tuple.stderr @@ -8,6 +8,11 @@ LL | Box::new((x, x)) | - ^ value used here after move | | | value moved here + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Box::new((x.clone(), x)) + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr b/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr index c25981e6f80..22e7951dbe3 100644 --- a/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr +++ b/src/test/ui/moves/use_of_moved_value_clone_suggestions.stderr @@ -7,6 +7,11 @@ LL | (t, t) | - ^ value used here after move | | | value moved here + | +help: consider cloning the value if the performance cost is acceptable + | +LL | (t.clone(), t) + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr index e9d7ca953d6..0a09353b8ec 100644 --- a/src/test/ui/nll/closure-access-spans.stderr +++ b/src/test/ui/nll/closure-access-spans.stderr @@ -67,6 +67,11 @@ LL | || x.len(); | ^^ - borrow occurs due to use in closure | | | value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let r = x.clone(); + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/closure-access-spans.rs:40:5 @@ -79,6 +84,11 @@ LL | || x = String::new(); | ^^ - borrow occurs due to use in closure | | | value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let r = x.clone(); + | ++++++++ error[E0382]: borrow of moved value: `x` --> $DIR/closure-access-spans.rs:45:5 diff --git a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr index 947c9e29b45..97ed414b1ec 100644 --- a/src/test/ui/nll/issue-21232-partial-init-and-use.stderr +++ b/src/test/ui/nll/issue-21232-partial-init-and-use.stderr @@ -37,6 +37,11 @@ LL | let mut t: T = (0, Box::new(0)); drop(t); | move occurs because `t` has type `(u32, Box<u32>)`, which does not implement the `Copy` trait LL | t.0 = 10; t.1 = Box::new(20); | ^^^^^^^^ value partially assigned here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let mut t: T = (0, Box::new(0)); drop(t.clone()); + | ++++++++ error[E0381]: partially assigned binding `s` isn't fully initialized --> $DIR/issue-21232-partial-init-and-use.rs:123:5 @@ -77,6 +82,11 @@ LL | let mut t: T = (0, Box::new(0)); drop(t); | move occurs because `t` has type `(u32, Box<u32>)`, which does not implement the `Copy` trait LL | t.0 = 10; | ^^^^^^^^ value partially assigned here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let mut t: T = (0, Box::new(0)); drop(t.clone()); + | ++++++++ error[E0381]: partially assigned binding `s` isn't fully initialized --> $DIR/issue-21232-partial-init-and-use.rs:149:5 @@ -208,6 +218,11 @@ LL | c2 => { | -- value moved here LL | c.0 = 2; | ^^^^^^^ value partially assigned here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref c2 => { + | +++ error[E0382]: assign to part of moved value: `c` --> $DIR/issue-21232-partial-init-and-use.rs:255:13 @@ -219,6 +234,11 @@ LL | c2 => { | -- value moved here LL | (c.1).0 = 2; | ^^^^^^^^^^^ value partially assigned here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref c2 => { + | +++ error[E0382]: assign to part of moved value: `c.1` --> $DIR/issue-21232-partial-init-and-use.rs:263:13 @@ -229,6 +249,10 @@ LL | ((c.1).1).0 = 3; | ^^^^^^^^^^^^^^^ value partially assigned here after move | = note: move occurs because `c.1` has type `(i32, (i32, String))`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref c2 => { + | +++ error: aborting due to 23 previous errors diff --git a/src/test/ui/nll/issue-51512.stderr b/src/test/ui/nll/issue-51512.stderr index e591ca08290..072e96788b1 100644 --- a/src/test/ui/nll/issue-51512.stderr +++ b/src/test/ui/nll/issue-51512.stderr @@ -7,6 +7,11 @@ LL | let r = range; | ----- value moved here LL | let x = range.start; | ^^^^^^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let r = range.clone(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/nll/issue-53807.stderr b/src/test/ui/nll/issue-53807.stderr index 574a114340f..d8f58b59131 100644 --- a/src/test/ui/nll/issue-53807.stderr +++ b/src/test/ui/nll/issue-53807.stderr @@ -5,7 +5,7 @@ LL | if let Some(thing) = maybe { | ^^^^^ value moved here, in previous iteration of loop | = note: move occurs because value has type `Vec<bool>`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `maybe.0` +help: borrow this binding in the pattern to avoid moving the value | LL | if let Some(ref thing) = maybe { | +++ diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index 2d48a914218..f72ed3af718 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -26,6 +26,11 @@ LL | false if { drop(x); true } => 1, LL | true => { LL | x; | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | false if { drop(x.clone()); true } => 1, + | ++++++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/ref-suggestion.stderr b/src/test/ui/nll/ref-suggestion.stderr index a973c583a9d..b1f5117cb02 100644 --- a/src/test/ui/nll/ref-suggestion.stderr +++ b/src/test/ui/nll/ref-suggestion.stderr @@ -7,6 +7,11 @@ LL | let y = x; | - value moved here LL | x; | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let y = x.clone(); + | ++++++++ error[E0382]: use of moved value: `x` --> $DIR/ref-suggestion.rs:8:5 @@ -17,6 +22,11 @@ LL | let mut y = x; | - value moved here LL | x; | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | let mut y = x.clone(); + | ++++++++ error[E0382]: use of partially moved value: `x` --> $DIR/ref-suggestion.rs:16:5 @@ -28,7 +38,7 @@ LL | x; | ^ value used here after partial move | = note: partial move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `x.0.0` +help: borrow this binding in the pattern to avoid moving the value | LL | (Some(ref y), ()) => {}, | +++ diff --git a/src/test/ui/parser/issue-104620.rs b/src/test/ui/parser/issue-104620.rs new file mode 100644 index 00000000000..f49476c4408 --- /dev/null +++ b/src/test/ui/parser/issue-104620.rs @@ -0,0 +1,4 @@ +#![feature(rustc_attrs)] + +#![rustc_dummy=5z] //~ ERROR unexpected expression: `5z` +fn main() {} diff --git a/src/test/ui/parser/issue-104620.stderr b/src/test/ui/parser/issue-104620.stderr new file mode 100644 index 00000000000..d06a6b2554b --- /dev/null +++ b/src/test/ui/parser/issue-104620.stderr @@ -0,0 +1,8 @@ +error: unexpected expression: `5z` + --> $DIR/issue-104620.rs:3:16 + | +LL | #![rustc_dummy=5z] + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr index fad84dda0e1..c8b45fd24d9 100644 --- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr +++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr @@ -16,6 +16,11 @@ LL | Some(_z @ ref _y) => {} | | value borrowed here after move | value moved into `_z` here | move occurs because `_z` has type `X` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref _z @ ref _y) => {} + | +++ error: cannot move out of value because it is borrowed --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14 @@ -35,6 +40,11 @@ LL | Some(_z @ ref mut _y) => {} | | value borrowed here after move | value moved into `_z` here | move occurs because `_z` has type `X` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Some(ref _z @ ref mut _y) => {} + | +++ error[E0382]: borrow of moved value --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14 @@ -45,7 +55,7 @@ LL | Some(ref _y @ _z) => {} | value borrowed here after move | = note: move occurs because value has type `X`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `x.0` +help: borrow this binding in the pattern to avoid moving the value | LL | Some(ref _y @ ref _z) => {} | +++ @@ -59,7 +69,7 @@ LL | Some(ref mut _y @ _z) => {} | value borrowed here after move | = note: move occurs because value has type `X`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving `x.0` +help: borrow this binding in the pattern to avoid moving the value | LL | Some(ref mut _y @ ref _z) => {} | +++ diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr index a227cc583d6..32489715112 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr @@ -6,6 +6,11 @@ LL | let a @ b = U; | | | | | value moved here | value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ +++ error[E0382]: use of partially moved value --> $DIR/borrowck-move-and-move.rs:13:9 @@ -16,6 +21,10 @@ LL | let a @ (b, c) = (U, U); | value used here after partial move | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, ref c) = (U, U); + | +++ +++ error[E0382]: use of partially moved value --> $DIR/borrowck-move-and-move.rs:15:9 @@ -26,6 +35,10 @@ LL | let a @ (b, c) = (u(), u()); | value used here after partial move | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, ref c) = (u(), u()); + | +++ +++ error[E0382]: use of moved value --> $DIR/borrowck-move-and-move.rs:18:16 @@ -36,6 +49,11 @@ LL | a @ Ok(b) | a @ Err(b) => {} | - ^ value used here after move | | | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Ok(b) | a @ Err(b) => {} + | +++ error[E0382]: use of moved value --> $DIR/borrowck-move-and-move.rs:18:29 @@ -46,6 +64,11 @@ LL | a @ Ok(b) | a @ Err(b) => {} | - ^ value used here after move | | | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Ok(b) | ref a @ Err(b) => {} + | +++ error[E0382]: use of partially moved value --> $DIR/borrowck-move-and-move.rs:25:9 @@ -56,6 +79,10 @@ LL | xs @ [a, .., b] => {} | value used here after partial move | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref xs @ [a, .., ref b] => {} + | +++ +++ error[E0382]: use of partially moved value --> $DIR/borrowck-move-and-move.rs:29:9 @@ -66,6 +93,10 @@ LL | xs @ [_, ys @ .., _] => {} | value used here after partial move | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref xs @ [_, ref ys @ .., _] => {} + | +++ +++ error[E0382]: use of moved value --> $DIR/borrowck-move-and-move.rs:22:12 diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr index 002c7609f61..f27df32ccfa 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr @@ -79,6 +79,10 @@ LL | let ref a @ box b = Box::new(NC); | value borrowed here after move | = note: move occurs because value has type `NC`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ box ref b = Box::new(NC); + | +++ error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:38:9 diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr index be4e81c61aa..d6474f1b49f 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr @@ -7,6 +7,11 @@ LL | let a @ ref b = U; | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ error: aborting due to previous error diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr index a9e66de0842..389e86e6464 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -7,6 +7,11 @@ LL | let a @ ref b = U; | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = U; + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9 @@ -18,6 +23,11 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:14 @@ -28,6 +38,11 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); | | value borrowed here after move | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (ref mut b @ ref mut c, d @ ref e) = (U, U); + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:33 @@ -38,6 +53,11 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); | | value borrowed here after move | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (mut b @ ref mut c, ref d @ ref e) = (U, U); + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9 @@ -49,6 +69,11 @@ LL | let a @ [ref mut b, ref c] = [U, U]; | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ [ref mut b, ref c] = [U, U]; + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9 @@ -59,6 +84,11 @@ LL | let a @ ref b = u(); | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = u(); + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9 @@ -70,6 +100,11 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:14 @@ -80,6 +115,11 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); | | value borrowed here after move | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (ref mut b @ ref mut c, d @ ref e) = (u(), u()); + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:33 @@ -90,6 +130,11 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); | | value borrowed here after move | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9 @@ -101,6 +146,11 @@ LL | let a @ [ref mut b, ref c] = [u(), u()]; | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ [ref mut b, ref c] = [u(), u()]; + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:42:9 @@ -111,6 +161,11 @@ LL | a @ Some(ref b) => {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9 @@ -122,6 +177,11 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:19 @@ -132,6 +192,11 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | value borrowed here after move | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 @@ -142,6 +207,11 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | value borrowed here after move | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9 @@ -153,6 +223,11 @@ LL | mut a @ Some([ref b, ref mut c]) => {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([ref b, ref mut c]) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 @@ -163,6 +238,11 @@ LL | a @ Some(ref b) => {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9 @@ -174,6 +254,11 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19 @@ -184,6 +269,11 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | value borrowed here after move | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 @@ -194,6 +284,11 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | value borrowed here after move | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9 @@ -205,6 +300,11 @@ LL | mut a @ Some([ref b, ref mut c]) => {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([ref b, ref mut c]) => {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11 @@ -215,6 +315,11 @@ LL | fn f1(a @ ref b: U) {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f1(ref a @ ref b: U) {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11 @@ -226,6 +331,11 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(ref mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20 @@ -236,6 +346,11 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} | | value borrowed here after move | value moved into `b` here | move occurs because `b` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(mut a @ (ref b @ ref c, mut d @ ref e): (U, U)) {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31 @@ -246,6 +361,11 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} | | value borrowed here after move | value moved into `d` here | move occurs because `d` has type `U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f2(mut a @ (b @ ref c, ref mut d @ ref e): (U, U)) {} + | +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11 @@ -257,6 +377,11 @@ LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {} | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {} + | +++ error[E0382]: use of partially moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9 @@ -267,6 +392,10 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); | value used here after partial move | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (U, U); + | +++ +++ error[E0382]: use of partially moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9 @@ -277,6 +406,10 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); | value used here after partial move | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); + | +++ +++ error[E0382]: use of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 @@ -285,6 +418,11 @@ LL | match Some((U, U)) { | ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | - value moved here ^ value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30 @@ -305,6 +443,11 @@ LL | a @ Some(ref b) => {} | - ^^^^^ value borrowed here after move | | | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ error[E0382]: use of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 @@ -313,6 +456,11 @@ LL | match Some((u(), u())) { | ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | - value moved here ^ value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | +++ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30 diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr index b2f22fe8638..770bb89530c 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr @@ -242,6 +242,10 @@ LL | let ref mut a @ [b, mut c] = [U, U]; | value borrowed here after partial move | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ [b, ref mut c] = [U, U]; + | +++ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9 @@ -251,6 +255,11 @@ LL | let ref a @ b = u(); | | | | | value moved here | value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ ref b = u(); + | +++ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18 @@ -261,6 +270,10 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); | value borrowed here after move | = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref b @ ref mut c, ref d @ e) = (u(), u()); + | +++ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33 @@ -271,6 +284,10 @@ LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); | value borrowed here after move | = note: move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref b @ mut c, ref d @ ref e) = (u(), u()); + | +++ error[E0382]: borrow of partially moved value --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9 @@ -281,6 +298,10 @@ LL | let ref mut a @ [b, mut c] = [u(), u()]; | value borrowed here after partial move | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ [b, ref mut c] = [u(), u()]; + | +++ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 @@ -291,7 +312,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value borrowed here after move | = note: move occurs because value has type `U`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving the value +help: borrow this binding in the pattern to avoid moving the value | LL | ref a @ Some((ref b @ ref mut c, ref d @ e)) => {} | +++ @@ -305,7 +326,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value borrowed here after move | = note: move occurs because value has type `U`, which does not implement the `Copy` trait -help: borrow this field in the pattern to avoid moving the value +help: borrow this binding in the pattern to avoid moving the value | LL | ref a @ Some((ref b @ mut c, ref d @ ref e)) => {} | +++ diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index 384a57b2ee0..ad4ce7952ca 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -97,6 +97,11 @@ LL | let a @ (ref mut b, ref mut c) = (U, U); | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (ref mut b, ref mut c) = (U, U); + | +++ error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9 @@ -109,6 +114,11 @@ LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `&mut (U, [U; 2])` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ (b, [c, d]) = &mut val; // Same as ^-- + | +++ error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9 @@ -119,6 +129,11 @@ LL | let a @ &mut ref mut b = &mut U; | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `&mut U` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ &mut ref mut b = &mut U; + | +++ error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:72:9 @@ -130,6 +145,11 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | | value borrowed here after move | value moved into `a` here | move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ &mut (ref mut b, ref mut c) = &mut (U, U); + | +++ error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:76:9 diff --git a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr index cd3234952fa..e0e623fa544 100644 --- a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr +++ b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr @@ -7,6 +7,10 @@ LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); | value used here after partial move | = note: partial move occurs because value has type `NC<C, C>`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref a @ NC(b, ref c @ NC(d, e)) = NC(C, NC(C, C)); + | +++ +++ error: aborting due to previous error diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr index 840a513d6c6..638bdd6db76 100644 --- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr +++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr @@ -34,6 +34,11 @@ LL | Ok(ref a @ b) | Err(b @ ref a) => { | | value borrowed here after move | value moved into `b` here | move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | Ok(ref a @ b) | Err(ref b @ ref a) => { + | +++ error: cannot move out of value because it is borrowed --> $DIR/default-binding-modes-both-sides-independent.rs:42:9 @@ -52,6 +57,11 @@ LL | let ref mut a @ b = NotCopy; | | | | | value moved here | value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref mut a @ ref b = NotCopy; + | +++ error: aborting due to 6 previous errors diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr index bac2db6ce82..bb7b818368b 100644 --- a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr @@ -129,6 +129,10 @@ LL | drop(tup.1); | ^^^^^ value used here after move | = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let (ref _x0, ref _x1, ref _x2, ..) = tup; + | +++ error[E0382]: borrow of moved value: `tup.1` --> $DIR/borrowck-move-ref-pattern.rs:29:20 diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr index a67bfd018a2..4d00a708313 100644 --- a/src/test/ui/recursion/issue-83150.stderr +++ b/src/test/ui/recursion/issue-83150.stderr @@ -9,11 +9,9 @@ LL | func(&mut iter.map(|x| x + 1)) = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0275]: overflow evaluating the requirement `<std::ops::Range<u8> as Iterator>::Item` +error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) - = note: required for `Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:12:24: 12:27]>` to implement `Iterator` - = note: 64 redundant requirements hidden = note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator` = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt' diff --git a/src/test/ui/recursion/issue-95134.rs b/src/test/ui/recursion/issue-95134.rs index adc9c6ee2d9..fdc4d536981 100644 --- a/src/test/ui/recursion/issue-95134.rs +++ b/src/test/ui/recursion/issue-95134.rs @@ -1,6 +1,8 @@ // build-fail +// known-bug: #95134 // compile-flags: -Copt-level=0 -//~^^ ERROR overflow evaluating the requirement +// failure-status: 101 +// dont-check-compiler-stderr pub fn encode_num<Writer: ExampleWriter>(n: u32, mut writer: Writer) -> Result<(), Writer::Error> { if n > 15 { diff --git a/src/test/ui/recursion/issue-95134.stderr b/src/test/ui/recursion/issue-95134.stderr deleted file mode 100644 index 57a498694b7..00000000000 --- a/src/test/ui/recursion/issue-95134.stderr +++ /dev/null @@ -1,7 +0,0 @@ -error[E0275]: overflow evaluating the requirement `<EmptyWriter as ExampleWriter>::Error` - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_95134`) - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr index 5611b5f4ece..06699b947be 100644 --- a/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr +++ b/src/test/ui/rfc-2361-dbg-macro/dbg-macro-move-semantics.stderr @@ -7,6 +7,12 @@ LL | let _ = dbg!(a); | ------- value moved here LL | let _ = dbg!(a); | ^ value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + --> $SRC_DIR/std/src/macros.rs:LL:COL + | +LL | ref tmp => { + | +++ error: aborting due to previous error diff --git a/src/test/ui/stats/hir-stats.rs b/src/test/ui/stats/hir-stats.rs index a24b3ada57e..0b89d0b160b 100644 --- a/src/test/ui/stats/hir-stats.rs +++ b/src/test/ui/stats/hir-stats.rs @@ -1,6 +1,7 @@ // check-pass // compile-flags: -Zhir-stats // only-x86_64 +// ignore-stage1 FIXME: remove after next bootstrap bump // The aim here is to include at least one of every different type of top-level // AST/HIR node reported by `-Zhir-stats`. diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr index 297245f0198..012bc848d4b 100644 --- a/src/test/ui/stats/hir-stats.stderr +++ b/src/test/ui/stats/hir-stats.stderr @@ -2,12 +2,12 @@ ast-stats-1 PRE EXPANSION AST STATS ast-stats-1 Name Accumulated Size Count Item Size ast-stats-1 ---------------------------------------------------------------- ast-stats-1 ExprField 48 ( 0.6%) 1 48 +ast-stats-1 GenericArgs 56 ( 0.8%) 1 56 +ast-stats-1 - AngleBracketed 56 ( 0.8%) 1 ast-stats-1 Crate 56 ( 0.8%) 1 56 ast-stats-1 Attribute 64 ( 0.9%) 2 32 ast-stats-1 - Normal 32 ( 0.4%) 1 ast-stats-1 - DocComment 32 ( 0.4%) 1 -ast-stats-1 GenericArgs 64 ( 0.9%) 1 64 -ast-stats-1 - AngleBracketed 64 ( 0.9%) 1 ast-stats-1 Local 72 ( 1.0%) 1 72 ast-stats-1 WherePredicate 72 ( 1.0%) 1 72 ast-stats-1 - BoundPredicate 72 ( 1.0%) 1 @@ -53,15 +53,15 @@ ast-stats-1 - Impl 184 ( 2.5%) 1 ast-stats-1 - Fn 368 ( 5.0%) 2 ast-stats-1 - Use 552 ( 7.4%) 3 ast-stats-1 ---------------------------------------------------------------- -ast-stats-1 Total 7_424 +ast-stats-1 Total 7_416 ast-stats-1 ast-stats-2 POST EXPANSION AST STATS ast-stats-2 Name Accumulated Size Count Item Size ast-stats-2 ---------------------------------------------------------------- ast-stats-2 ExprField 48 ( 0.6%) 1 48 +ast-stats-2 GenericArgs 56 ( 0.7%) 1 56 +ast-stats-2 - AngleBracketed 56 ( 0.7%) 1 ast-stats-2 Crate 56 ( 0.7%) 1 56 -ast-stats-2 GenericArgs 64 ( 0.8%) 1 64 -ast-stats-2 - AngleBracketed 64 ( 0.8%) 1 ast-stats-2 Local 72 ( 0.9%) 1 72 ast-stats-2 WherePredicate 72 ( 0.9%) 1 72 ast-stats-2 - BoundPredicate 72 ( 0.9%) 1 @@ -80,9 +80,9 @@ ast-stats-2 - Expr 96 ( 1.2%) 3 ast-stats-2 Param 160 ( 2.0%) 4 40 ast-stats-2 FnDecl 200 ( 2.5%) 5 40 ast-stats-2 Variant 240 ( 3.0%) 2 120 -ast-stats-2 GenericBound 288 ( 3.5%) 4 72 -ast-stats-2 - Trait 288 ( 3.5%) 4 -ast-stats-2 Block 288 ( 3.5%) 6 48 +ast-stats-2 GenericBound 288 ( 3.6%) 4 72 +ast-stats-2 - Trait 288 ( 3.6%) 4 +ast-stats-2 Block 288 ( 3.6%) 6 48 ast-stats-2 AssocItem 416 ( 5.1%) 4 104 ast-stats-2 - Type 208 ( 2.6%) 2 ast-stats-2 - Fn 208 ( 2.6%) 2 @@ -104,7 +104,7 @@ ast-stats-2 - Rptr 64 ( 0.8%) 1 ast-stats-2 - Ptr 64 ( 0.8%) 1 ast-stats-2 - ImplicitSelf 128 ( 1.6%) 2 ast-stats-2 - Path 640 ( 7.9%) 10 -ast-stats-2 Item 2_024 (24.9%) 11 184 +ast-stats-2 Item 2_024 (25.0%) 11 184 ast-stats-2 - Trait 184 ( 2.3%) 1 ast-stats-2 - Enum 184 ( 2.3%) 1 ast-stats-2 - ExternCrate 184 ( 2.3%) 1 @@ -113,7 +113,7 @@ ast-stats-2 - Impl 184 ( 2.3%) 1 ast-stats-2 - Fn 368 ( 4.5%) 2 ast-stats-2 - Use 736 ( 9.1%) 4 ast-stats-2 ---------------------------------------------------------------- -ast-stats-2 Total 8_120 +ast-stats-2 Total 8_112 ast-stats-2 hir-stats HIR STATS hir-stats Name Accumulated Size Count Item Size diff --git a/src/test/ui/structs-enums/type-sizes.rs b/src/test/ui/structs-enums/type-sizes.rs index 7a23f13630a..63e2f3150c0 100644 --- a/src/test/ui/structs-enums/type-sizes.rs +++ b/src/test/ui/structs-enums/type-sizes.rs @@ -3,6 +3,7 @@ #![allow(non_camel_case_types)] #![allow(dead_code)] #![feature(never_type)] +#![feature(pointer_is_aligned)] use std::mem::size_of; use std::num::NonZeroU8; @@ -168,6 +169,18 @@ pub enum EnumManyVariant<X> { _F0, _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _FA, _FB, _FC, _FD, _FE, _FF, } +struct Reorder4 { + a: u32, + b: u8, + ary: [u8; 4], +} + +struct Reorder2 { + a: u16, + b: u8, + ary: [u8; 6], +} + pub fn main() { assert_eq!(size_of::<u8>(), 1 as usize); assert_eq!(size_of::<u32>(), 4 as usize); @@ -249,4 +262,12 @@ pub fn main() { assert_eq!(size_of::<EnumManyVariant<Option<NicheU16>>>(), 4); assert_eq!(size_of::<EnumManyVariant<Option2<NicheU16,u8>>>(), 6); assert_eq!(size_of::<EnumManyVariant<Option<(NicheU16,u8)>>>(), 6); + + + let v = Reorder4 {a: 0, b: 0, ary: [0; 4]}; + assert_eq!(size_of::<Reorder4>(), 12); + assert!((&v.ary).as_ptr().is_aligned_to(4), "[u8; 4] should group with align-4 fields"); + let v = Reorder2 {a: 0, b: 0, ary: [0; 6]}; + assert_eq!(size_of::<Reorder2>(), 10); + assert!((&v.ary).as_ptr().is_aligned_to(2), "[u8; 6] should group with align-2 fields"); } diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr index 1059e3d1525..0cc8994fe1f 100644 --- a/src/test/ui/suggestions/borrow-for-loop-head.stderr +++ b/src/test/ui/suggestions/borrow-for-loop-head.stderr @@ -12,6 +12,7 @@ error[E0382]: use of moved value: `a` LL | let a = vec![1, 2, 3]; | - move occurs because `a` has type `Vec<i32>`, which does not implement the `Copy` trait LL | for i in &a { + | ----------- inside of this loop LL | for j in a { | ^ `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop | diff --git a/src/test/ui/suggestions/ref-pattern-binding.fixed b/src/test/ui/suggestions/ref-pattern-binding.fixed new file mode 100644 index 00000000000..c36040eeca3 --- /dev/null +++ b/src/test/ui/suggestions/ref-pattern-binding.fixed @@ -0,0 +1,19 @@ +// run-rustfix +#![allow(unused)] + +struct S { + f: String, +} + +fn main() { + let ref _moved @ ref _from = String::from("foo"); //~ ERROR + let ref _moved @ ref _from = String::from("foo"); //~ ERROR + let ref _moved @ ref _from = String::from("foo"); //~ ERROR + //~^ ERROR + let ref _moved @ ref _from = String::from("foo"); // ok + let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR + let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR + //~^ ERROR + let ref _moved @ S { ref f } = S { f: String::from("foo") }; // ok + let ref _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR +} diff --git a/src/test/ui/suggestions/ref-pattern-binding.rs b/src/test/ui/suggestions/ref-pattern-binding.rs new file mode 100644 index 00000000000..c0d4feb0330 --- /dev/null +++ b/src/test/ui/suggestions/ref-pattern-binding.rs @@ -0,0 +1,19 @@ +// run-rustfix +#![allow(unused)] + +struct S { + f: String, +} + +fn main() { + let _moved @ _from = String::from("foo"); //~ ERROR + let _moved @ ref _from = String::from("foo"); //~ ERROR + let ref _moved @ _from = String::from("foo"); //~ ERROR + //~^ ERROR + let ref _moved @ ref _from = String::from("foo"); // ok + let _moved @ S { f } = S { f: String::from("foo") }; //~ ERROR + let ref _moved @ S { f } = S { f: String::from("foo") }; //~ ERROR + //~^ ERROR + let ref _moved @ S { ref f } = S { f: String::from("foo") }; // ok + let _moved @ S { ref f } = S { f: String::from("foo") }; //~ ERROR +} diff --git a/src/test/ui/suggestions/ref-pattern-binding.stderr b/src/test/ui/suggestions/ref-pattern-binding.stderr new file mode 100644 index 00000000000..10447ba7089 --- /dev/null +++ b/src/test/ui/suggestions/ref-pattern-binding.stderr @@ -0,0 +1,107 @@ +error: borrow of moved value + --> $DIR/ref-pattern-binding.rs:10:9 + | +LL | let _moved @ ref _from = String::from("foo"); + | ------^^^--------- + | | | + | | value borrowed here after move + | value moved into `_moved` here + | move occurs because `_moved` has type `String` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ ref _from = String::from("foo"); + | +++ + +error: cannot move out of value because it is borrowed + --> $DIR/ref-pattern-binding.rs:11:9 + | +LL | let ref _moved @ _from = String::from("foo"); + | ----------^^^----- + | | | + | | value moved into `_from` here + | value borrowed, by `_moved`, here + +error: cannot move out of value because it is borrowed + --> $DIR/ref-pattern-binding.rs:15:9 + | +LL | let ref _moved @ S { f } = S { f: String::from("foo") }; + | ----------^^^^^^^-^^ + | | | + | | value moved into `f` here + | value borrowed, by `_moved`, here + +error: borrow of moved value + --> $DIR/ref-pattern-binding.rs:18:9 + | +LL | let _moved @ S { ref f } = S { f: String::from("foo") }; + | ------^^^^^^^-----^^ + | | | + | | value borrowed here after move + | value moved into `_moved` here + | move occurs because `_moved` has type `S` which does not implement the `Copy` trait + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ S { ref f } = S { f: String::from("foo") }; + | +++ + +error[E0382]: use of moved value + --> $DIR/ref-pattern-binding.rs:9:9 + | +LL | let _moved @ _from = String::from("foo"); + | ^^^^^^ ----- ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait + | | | + | | value moved here + | value used here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ ref _from = String::from("foo"); + | +++ +++ + +error[E0382]: borrow of moved value + --> $DIR/ref-pattern-binding.rs:11:9 + | +LL | let ref _moved @ _from = String::from("foo"); + | ^^^^^^^^^^ ----- ------------------- move occurs because value has type `String`, which does not implement the `Copy` trait + | | | + | | value moved here + | value borrowed here after move + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ ref _from = String::from("foo"); + | +++ + +error[E0382]: use of partially moved value + --> $DIR/ref-pattern-binding.rs:14:9 + | +LL | let _moved @ S { f } = S { f: String::from("foo") }; + | ^^^^^^ - value partially moved here + | | + | value used here after partial move + | + = note: partial move occurs because value has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ S { ref f } = S { f: String::from("foo") }; + | +++ +++ + +error[E0382]: borrow of partially moved value + --> $DIR/ref-pattern-binding.rs:15:9 + | +LL | let ref _moved @ S { f } = S { f: String::from("foo") }; + | ^^^^^^^^^^ - value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `String`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ S { ref f } = S { f: String::from("foo") }; + | +++ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/track-diagnostics/track2.stderr b/src/test/ui/track-diagnostics/track2.stderr index 38a621da816..fe13e5ef3f5 100644 --- a/src/test/ui/track-diagnostics/track2.stderr +++ b/src/test/ui/track-diagnostics/track2.stderr @@ -7,6 +7,11 @@ LL | let _moved @ _from = String::from("foo"); | | value moved here | value used here after move -Ztrack-diagnostics: created at compiler/rustc_borrowck/src/borrowck_errors.rs:LL:CC + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | let ref _moved @ ref _from = String::from("foo"); + | +++ +++ error: aborting due to previous error diff --git a/src/test/ui/traits/predicate_can_apply-hang.rs b/src/test/ui/traits/predicate_can_apply-hang.rs new file mode 100644 index 00000000000..5f01645da52 --- /dev/null +++ b/src/test/ui/traits/predicate_can_apply-hang.rs @@ -0,0 +1,6 @@ +fn f<B>(x: Vec<[[[B; 1]; 1]; 1]>) -> impl PartialEq<B> { + //~^ ERROR can't compare `Vec<[[[B; 1]; 1]; 1]>` with `B` + x +} + +fn main() {} diff --git a/src/test/ui/traits/predicate_can_apply-hang.stderr b/src/test/ui/traits/predicate_can_apply-hang.stderr new file mode 100644 index 00000000000..49fe63b412a --- /dev/null +++ b/src/test/ui/traits/predicate_can_apply-hang.stderr @@ -0,0 +1,21 @@ +error[E0277]: can't compare `Vec<[[[B; 1]; 1]; 1]>` with `B` + --> $DIR/predicate_can_apply-hang.rs:1:38 + | +LL | fn f<B>(x: Vec<[[[B; 1]; 1]; 1]>) -> impl PartialEq<B> { + | ^^^^^^^^^^^^^^^^^ no implementation for `Vec<[[[B; 1]; 1]; 1]> == B` +LL | +LL | x + | - return type was inferred to be `Vec<[[[B; 1]; 1]; 1]>` here + | + = help: the trait `PartialEq<B>` is not implemented for `Vec<[[[B; 1]; 1]; 1]>` + = help: the following other types implement trait `PartialEq<Rhs>`: + <Vec<T, A1> as PartialEq<Vec<U, A2>>> + <Vec<T, A> as PartialEq<&[U; N]>> + <Vec<T, A> as PartialEq<&[U]>> + <Vec<T, A> as PartialEq<&mut [U]>> + <Vec<T, A> as PartialEq<[U; N]>> + <Vec<T, A> as PartialEq<[U]>> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs index 5f5a2574bab..d624187561e 100644 --- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs +++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.rs @@ -7,7 +7,11 @@ use core::ops::Deref; // issue 89190 trait A {} trait B: A {} + impl<'a> Deref for dyn 'a + B { + //~^ ERROR `(dyn B + 'a)` implements `Deref` with supertrait `A` as target + //~| WARN this was previously accepted by the compiler but is being phased out; + type Target = dyn A; fn deref(&self) -> &Self::Target { todo!() @@ -18,8 +22,6 @@ fn take_a(_: &dyn A) {} fn whoops(b: &dyn B) { take_a(b) - //~^ ERROR `dyn B` implements `Deref` with supertrait `A` as output - //~^^ WARN this was previously accepted by the compiler but is being phased out; } fn main() {} diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr index 41381a3ffd1..4533b116342 100644 --- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr +++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr @@ -1,8 +1,11 @@ -error: `dyn B` implements `Deref` with supertrait `A` as output - --> $DIR/migrate-lint-deny.rs:20:12 +error: `(dyn B + 'a)` implements `Deref` with supertrait `A` as target + --> $DIR/migrate-lint-deny.rs:11:1 | -LL | take_a(b) - | ^ +LL | impl<'a> Deref for dyn 'a + B { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | type Target = dyn A; + | -------------------- target type is set here | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460> diff --git a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr index c9f2a3ed9f4..f738b03eed6 100644 --- a/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr +++ b/src/test/ui/try-block/try-block-maybe-bad-lifetime.stderr @@ -23,6 +23,10 @@ LL | println!("{}", x); | ^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | ::std::mem::drop(x.clone()); + | ++++++++ error[E0506]: cannot assign to `i` because it is borrowed --> $DIR/try-block-maybe-bad-lifetime.rs:40:9 diff --git a/src/test/ui/typeck/hang-in-overflow.rs b/src/test/ui/typeck/hang-in-overflow.rs new file mode 100644 index 00000000000..a8330c9b65c --- /dev/null +++ b/src/test/ui/typeck/hang-in-overflow.rs @@ -0,0 +1,19 @@ +// normalize-stderr-test "the requirement `.*`" -> "the requirement `...`" +// normalize-stderr-test "required for `.*` to implement `.*`" -> "required for `...` to implement `...`" +// normalize-stderr-test: ".*the full type name has been written to.*\n" -> "" + +// Currently this fatally aborts instead of hanging. +// Make sure at least that this doesn't turn into a hang. + +fn f() { + foo::<_>(); + //~^ ERROR overflow evaluating the requirement +} + +fn foo<B>() +where + Vec<[[[B; 1]; 1]; 1]>: PartialEq<B>, +{ +} + +fn main() {} diff --git a/src/test/ui/typeck/hang-in-overflow.stderr b/src/test/ui/typeck/hang-in-overflow.stderr new file mode 100644 index 00000000000..7a7b85b19b4 --- /dev/null +++ b/src/test/ui/typeck/hang-in-overflow.stderr @@ -0,0 +1,22 @@ +error[E0275]: overflow evaluating the requirement `...` + --> $DIR/hang-in-overflow.rs:9:5 + | +LL | foo::<_>(); + | ^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hang_in_overflow`) + = note: required for `...` to implement `...` + = note: 127 redundant requirements hidden + = note: required for `...` to implement `...` +note: required by a bound in `foo` + --> $DIR/hang-in-overflow.rs:15:28 + | +LL | fn foo<B>() + | --- required by a bound in this +LL | where +LL | Vec<[[[B; 1]; 1]; 1]>: PartialEq<B>, + | ^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/union/union-move.mirunsafeck.stderr b/src/test/ui/union/union-move.mirunsafeck.stderr index 53050cf539e..6381ae874ba 100644 --- a/src/test/ui/union/union-move.mirunsafeck.stderr +++ b/src/test/ui/union/union-move.mirunsafeck.stderr @@ -8,6 +8,14 @@ LL | move_out(x.f1_nocopy); | ----------- value moved here LL | move_out(x.f2_nocopy); | ^^^^^^^^^^^ value used here after move + | +note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary + --> $DIR/union-move.rs:10:19 + | +LL | fn move_out<T>(x: T) {} + | -------- ^ this parameter takes ownership of the value + | | + | in this function error[E0382]: use of moved value: `x` --> $DIR/union-move.rs:45:18 @@ -19,6 +27,14 @@ LL | move_out(x.f2_nocopy); | ----------- value moved here LL | move_out(x.f3_copy); | ^^^^^^^^^ value used here after move + | +note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary + --> $DIR/union-move.rs:10:19 + | +LL | fn move_out<T>(x: T) {} + | -------- ^ this parameter takes ownership of the value + | | + | in this function error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait --> $DIR/union-move.rs:52:18 diff --git a/src/test/ui/union/union-move.thirunsafeck.stderr b/src/test/ui/union/union-move.thirunsafeck.stderr index 53050cf539e..6381ae874ba 100644 --- a/src/test/ui/union/union-move.thirunsafeck.stderr +++ b/src/test/ui/union/union-move.thirunsafeck.stderr @@ -8,6 +8,14 @@ LL | move_out(x.f1_nocopy); | ----------- value moved here LL | move_out(x.f2_nocopy); | ^^^^^^^^^^^ value used here after move + | +note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary + --> $DIR/union-move.rs:10:19 + | +LL | fn move_out<T>(x: T) {} + | -------- ^ this parameter takes ownership of the value + | | + | in this function error[E0382]: use of moved value: `x` --> $DIR/union-move.rs:45:18 @@ -19,6 +27,14 @@ LL | move_out(x.f2_nocopy); | ----------- value moved here LL | move_out(x.f3_copy); | ^^^^^^^^^ value used here after move + | +note: consider changing this parameter type in function `move_out` to borrow instead if owning the value isn't necessary + --> $DIR/union-move.rs:10:19 + | +LL | fn move_out<T>(x: T) {} + | -------- ^ this parameter takes ownership of the value + | | + | in this function error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait --> $DIR/union-move.rs:52:18 diff --git a/src/test/ui/unop-move-semantics.stderr b/src/test/ui/unop-move-semantics.stderr index 65d866c716e..d52a92b8888 100644 --- a/src/test/ui/unop-move-semantics.stderr +++ b/src/test/ui/unop-move-semantics.stderr @@ -14,6 +14,10 @@ note: calling this operator moves the left-hand side | LL | fn not(self) -> Self::Output; | ^^^^ +help: consider cloning the value if the performance cost is acceptable + | +LL | !x.clone(); + | ++++++++ help: consider further restricting this bound | LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) { diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr index 28ae1c0688c..d8bffd4f9cf 100644 --- a/src/test/ui/unsized-locals/borrow-after-move.stderr +++ b/src/test/ui/unsized-locals/borrow-after-move.stderr @@ -28,6 +28,14 @@ LL | drop_unsized(y); ... LL | println!("{}", &y); | ^^ value borrowed here after move + | +note: consider changing this parameter type in function `drop_unsized` to borrow instead if owning the value isn't necessary + --> $DIR/borrow-after-move.rs:14:31 + | +LL | fn drop_unsized<T: ?Sized>(_: T) {} + | ------------ ^ this parameter takes ownership of the value + | | + | in this function error[E0382]: borrow of moved value: `x` --> $DIR/borrow-after-move.rs:31:24 @@ -66,6 +74,11 @@ LL | x.foo(); | - value moved here LL | println!("{}", &x); | ^^ value borrowed here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | x.clone().foo(); + | ++++++++ error: aborting due to 5 previous errors; 1 warning emitted diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr index dfae6cc75d9..71534818141 100644 --- a/src/test/ui/unsized-locals/double-move.stderr +++ b/src/test/ui/unsized-locals/double-move.stderr @@ -16,6 +16,14 @@ LL | drop_unsized(y); | - value moved here LL | drop_unsized(y); | ^ value used here after move + | +note: consider changing this parameter type in function `drop_unsized` to borrow instead if owning the value isn't necessary + --> $DIR/double-move.rs:14:31 + | +LL | fn drop_unsized<T: ?Sized>(_: T) {} + | ------------ ^ this parameter takes ownership of the value + | | + | in this function error[E0382]: use of moved value: `x` --> $DIR/double-move.rs:27:22 diff --git a/src/test/ui/use/use-after-move-based-on-type.stderr b/src/test/ui/use/use-after-move-based-on-type.stderr index 445f14d65e3..7b4d2454994 100644 --- a/src/test/ui/use/use-after-move-based-on-type.stderr +++ b/src/test/ui/use/use-after-move-based-on-type.stderr @@ -9,6 +9,10 @@ LL | println!("{}", x); | ^ value borrowed here after move | = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider cloning the value if the performance cost is acceptable + | +LL | let _y = x.clone(); + | ++++++++ error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-implicity-coerced-object.stderr b/src/test/ui/use/use-after-move-implicity-coerced-object.stderr index 26804216d9d..dfa0c04836e 100644 --- a/src/test/ui/use/use-after-move-implicity-coerced-object.stderr +++ b/src/test/ui/use/use-after-move-implicity-coerced-object.stderr @@ -9,6 +9,14 @@ LL | l.push(n); LL | LL | let x = n.to_string(); | ^^^^^^^^^^^^^ value borrowed here after move + | +note: consider changing this parameter type in method `push` to borrow instead if owning the value isn't necessary + --> $DIR/use-after-move-implicity-coerced-object.rs:17:27 + | +LL | fn push(&mut self, n: Box<dyn ToString + 'static>) { + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this parameter takes ownership of the value + | | + | in this method error: aborting due to previous error diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs index 06a39c5997e..b4210d87510 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_overeager_cloned.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::{get_associated_type, implements_trait, is_copy}; +use clippy_utils::ty::{implements_trait, is_copy}; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; @@ -25,7 +25,7 @@ pub(super) fn check<'tcx>( && let Some(method_id) = typeck.type_dependent_def_id(cloned_call.hir_id) && cx.tcx.trait_of_item(method_id) == Some(iter_id) && let cloned_recv_ty = typeck.expr_ty_adjusted(cloned_recv) - && let Some(iter_assoc_ty) = get_associated_type(cx, cloned_recv_ty, iter_id, "Item") + && let Some(iter_assoc_ty) = cx.get_associated_type(cloned_recv_ty, iter_id, "Item") && matches!(*iter_assoc_ty.kind(), ty::Ref(_, ty, _) if !is_copy(cx, ty)) { if needs_into_iter diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs index 4eb579af7a1..52a4ff7d1ae 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs @@ -2,7 +2,7 @@ use super::utils::clone_or_copy_needed; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait}; +use clippy_utils::ty::{get_iterator_item_ty, implements_trait}; use clippy_utils::{fn_def_id, get_parent_expr}; use rustc_errors::Applicability; use rustc_hir::{def_id::DefId, Expr, ExprKind}; @@ -54,7 +54,7 @@ pub fn check_for_loop_iter( if let Some(into_iterator_trait_id) = cx.tcx.get_diagnostic_item(sym::IntoIterator); let collection_ty = cx.typeck_results().expr_ty(collection); if implements_trait(cx, collection_ty, into_iterator_trait_id, &[]); - if let Some(into_iter_item_ty) = get_associated_type(cx, collection_ty, into_iterator_trait_id, "Item"); + if let Some(into_iter_item_ty) = cx.get_associated_type(collection_ty, into_iterator_trait_id, "Item"); if iter_item_ty == into_iter_item_ty; if let Some(collection_snippet) = snippet_opt(cx, collection.span); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 375ebc903b4..8b000cd754c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -2,9 +2,11 @@ use super::implicit_clone::is_clone_like; use super::unnecessary_iter_cloned::{self, is_into_iter}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_opt; -use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs}; +use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs}; use clippy_utils::visitors::find_all_ret_expressions; -use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty}; +use clippy_utils::{ + fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty, +}; use clippy_utils::{meets_msrv, msrvs}; use rustc_errors::Applicability; use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node}; @@ -18,7 +20,9 @@ use rustc_middle::ty::EarlyBinder; use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty}; use rustc_semver::RustcVersion; use rustc_span::{sym, Symbol}; -use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; +use rustc_trait_selection::traits::{ + query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause, +}; use std::cmp::max; use super::UNNECESSARY_TO_OWNED; @@ -146,7 +150,7 @@ fn check_addr_of_expr( if_chain! { if let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref); if implements_trait(cx, receiver_ty, deref_trait_id, &[]); - if get_associated_type(cx, receiver_ty, deref_trait_id, "Target") == Some(target_ty); + if cx.get_associated_type(receiver_ty, deref_trait_id, "Target") == Some(target_ty); then { if n_receiver_refs > 0 { span_lint_and_sugg( @@ -341,13 +345,13 @@ fn get_input_traits_and_projections<'tcx>( if trait_predicate.trait_ref.self_ty() == input { trait_predicates.push(trait_predicate); } - }, + } PredicateKind::Projection(projection_predicate) => { if projection_predicate.projection_ty.self_ty() == input { projection_predicates.push(projection_predicate); } - }, - _ => {}, + } + _ => {} } } (trait_predicates, projection_predicates) @@ -462,7 +466,12 @@ fn is_cloned_or_copied(cx: &LateContext<'_>, method_name: Symbol, method_def_id: /// Returns true if the named method can be used to convert the receiver to its "owned" /// representation. -fn is_to_owned_like<'a>(cx: &LateContext<'a>, call_expr: &Expr<'a>, method_name: Symbol, method_def_id: DefId) -> bool { +fn is_to_owned_like<'a>( + cx: &LateContext<'a>, + call_expr: &Expr<'a>, + method_name: Symbol, + method_def_id: DefId, +) -> bool { is_clone_like(cx, method_name.as_str(), method_def_id) || is_cow_into_owned(cx, method_name, method_def_id) || is_to_string_on_string_like(cx, call_expr, method_name, method_def_id) @@ -490,7 +499,7 @@ fn is_to_string_on_string_like<'a>( && let GenericArgKind::Type(ty) = generic_arg.unpack() && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef) - && (get_associated_type(cx, ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) || + && (cx.get_associated_type(ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) || implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()])) { true } else { diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs index 78e83880e1a..e111c7d2291 100644 --- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs +++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs @@ -582,7 +582,7 @@ fn ident_difference_expr_with_base_location( | (Block(_, _), Block(_, _)) | (Closure(_), Closure(_)) | (Match(_, _), Match(_, _)) - | (Loop(_, _), Loop(_, _)) + | (Loop(_, _, _), Loop(_, _, _)) | (ForLoop(_, _, _, _), ForLoop(_, _, _, _)) | (While(_, _, _), While(_, _, _)) | (If(_, _, _), If(_, _, _)) diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 5c595f74eff..6bcf0bbd7eb 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -171,7 +171,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => { eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt) }, - (Loop(lt, ll), Loop(rt, rl)) => eq_label(ll, rl) && eq_block(lt, rt), + (Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll, rl) && eq_block(lt, rt), (Block(lb, ll), Block(rb, rl)) => eq_label(ll, rl) && eq_block(lb, rb), (TryBlock(l), TryBlock(r)) => eq_block(l, r), (Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l, r), diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 1b65b701409..8284dc5c28c 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -117,24 +117,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' pub fn get_iterator_item_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { cx.tcx .get_diagnostic_item(sym::Iterator) - .and_then(|iter_did| get_associated_type(cx, ty, iter_did, "Item")) -} - -/// Returns the associated type `name` for `ty` as an implementation of `trait_id`. -/// Do not invoke without first verifying that the type implements the trait. -pub fn get_associated_type<'tcx>( - cx: &LateContext<'tcx>, - ty: Ty<'tcx>, - trait_id: DefId, - name: &str, -) -> Option<Ty<'tcx>> { - cx.tcx - .associated_items(trait_id) - .find_by_name_and_kind(cx.tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) - .and_then(|assoc| { - let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, [])); - cx.tcx.try_normalize_erasing_regions(cx.param_env, proj).ok() - }) + .and_then(|iter_did| cx.get_associated_type(ty, iter_did, "Item")) } /// Get the diagnostic name of a type, e.g. `sym::HashMap`. To check if a type diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index d5611082f01..414e767690b 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -660,7 +660,7 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option<ControlFlow< ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => { Some(ControlFlow::new_for(pat, cond, block, label, expr.span)) } - ast::ExprKind::Loop(ref block, label) => { + ast::ExprKind::Loop(ref block, label, _) => { Some(ControlFlow::new_loop(block, label, expr.span)) } ast::ExprKind::While(ref cond, ref block, label) => { |
