diff --git a/Cargo.lock b/Cargo.lock index b98c4fd0642..e5025a1ba4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3270,6 +3270,7 @@ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ "rustc_ast", + "rustc_ast_pretty", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 44bb44cb728..a09aa9ee665 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -23,7 +23,7 @@ use crate::ast::*; use crate::ptr::P; use crate::token::{self, Token}; use crate::tokenstream::*; -use crate::visit::{AssocCtxt, BoundKind}; +use crate::visit::{AssocCtxt, BoundKind, FnCtxt}; pub trait ExpectOne { fn expect_one(self, err: &'static str) -> A::Item; @@ -37,7 +37,16 @@ impl ExpectOne for SmallVec { } pub trait WalkItemKind { - fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor); + type Ctxt; + fn walk( + &mut self, + span: Span, + id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + ctxt: Self::Ctxt, + visitor: &mut impl MutVisitor, + ); } pub trait MutVisitor: Sized { @@ -114,9 +123,9 @@ pub trait MutVisitor: Sized { fn flat_map_assoc_item( &mut self, i: P, - _ctxt: AssocCtxt, + ctxt: AssocCtxt, ) -> SmallVec<[P; 1]> { - walk_flat_map_item(self, i) + walk_flat_map_assoc_item(self, i, ctxt) } fn visit_fn_decl(&mut self, d: &mut P) { @@ -880,7 +889,7 @@ fn walk_coroutine_kind(vis: &mut T, coroutine_kind: &mut Coroutin fn walk_fn(vis: &mut T, kind: FnKind<'_>) { match kind { - FnKind::Fn(FnSig { header, decl, span }, generics, body) => { + FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span }, _visibility, generics, body) => { // Identifier and visibility are visited as a part of the item. vis.visit_fn_header(header); vis.visit_generics(generics); @@ -890,8 +899,9 @@ fn walk_fn(vis: &mut T, kind: FnKind<'_>) { } vis.visit_span(span); } - FnKind::Closure(binder, decl, body) => { + FnKind::Closure(binder, coroutine_kind, decl, body) => { vis.visit_closure_binder(binder); + coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind)); vis.visit_fn_decl(decl); vis.visit_expr(body); } @@ -1079,17 +1089,29 @@ pub fn walk_block(vis: &mut T, block: &mut P) { vis.visit_span(span); } -pub fn walk_item_kind( - kind: &mut impl WalkItemKind, +pub fn walk_item_kind( + kind: &mut K, span: Span, id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + ctxt: K::Ctxt, vis: &mut impl MutVisitor, ) { - kind.walk(span, id, vis) + kind.walk(span, id, ident, visibility, ctxt, vis) } impl WalkItemKind for ItemKind { - fn walk(&mut self, span: Span, id: NodeId, vis: &mut impl MutVisitor) { + type Ctxt = (); + fn walk( + &mut self, + span: Span, + id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + _ctxt: Self::Ctxt, + vis: &mut impl MutVisitor, + ) { match self { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), @@ -1102,7 +1124,11 @@ impl WalkItemKind for ItemKind { } ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(vis, defaultness); - vis.visit_fn(FnKind::Fn(sig, generics, body), span, id); + vis.visit_fn( + FnKind::Fn(FnCtxt::Free, ident, sig, visibility, generics, body), + span, + id, + ); } ItemKind::Mod(safety, mod_kind) => { visit_safety(vis, safety); @@ -1201,14 +1227,27 @@ impl WalkItemKind for ItemKind { } impl WalkItemKind for AssocItemKind { - fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) { + type Ctxt = AssocCtxt; + fn walk( + &mut self, + span: Span, + id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + ctxt: Self::Ctxt, + visitor: &mut impl MutVisitor, + ) { match self { AssocItemKind::Const(item) => { visit_const_item(item, visitor); } AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(visitor, defaultness); - visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id); + visitor.visit_fn( + FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, visibility, generics, body), + span, + id, + ); } AssocItemKind::Type(box TyAlias { defaultness, @@ -1288,24 +1327,40 @@ pub fn walk_crate(vis: &mut T, krate: &mut Crate) { vis.visit_span(inject_use_span); } -/// Mutates one item, returning the item again. -pub fn walk_flat_map_item( +pub fn walk_flat_map_item>( + visitor: &mut impl MutVisitor, + item: P>, +) -> SmallVec<[P>; 1]> { + walk_flat_map_assoc_item(visitor, item, ()) +} + +pub fn walk_flat_map_assoc_item( visitor: &mut impl MutVisitor, mut item: P>, + ctxt: K::Ctxt, ) -> SmallVec<[P>; 1]> { let Item { ident, attrs, id, kind, vis, span, tokens } = item.deref_mut(); visitor.visit_id(id); visit_attrs(visitor, attrs); visitor.visit_vis(vis); visitor.visit_ident(ident); - kind.walk(*span, *id, visitor); + kind.walk(*span, *id, ident, vis, ctxt, visitor); visit_lazy_tts(visitor, tokens); visitor.visit_span(span); smallvec![item] } impl WalkItemKind for ForeignItemKind { - fn walk(&mut self, span: Span, id: NodeId, visitor: &mut impl MutVisitor) { + type Ctxt = (); + fn walk( + &mut self, + span: Span, + id: NodeId, + ident: &mut Ident, + visibility: &mut Visibility, + _ctxt: Self::Ctxt, + visitor: &mut impl MutVisitor, + ) { match self { ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { visitor.visit_ty(ty); @@ -1313,7 +1368,11 @@ impl WalkItemKind for ForeignItemKind { } ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => { visit_defaultness(visitor, defaultness); - visitor.visit_fn(FnKind::Fn(sig, generics, body), span, id); + visitor.visit_fn( + FnKind::Fn(FnCtxt::Foreign, ident, sig, visibility, generics, body), + span, + id, + ); } ForeignItemKind::TyAlias(box TyAlias { defaultness, @@ -1522,9 +1581,8 @@ pub fn walk_expr(vis: &mut T, Expr { kind, id, span, attrs, token fn_arg_span, }) => { visit_constness(vis, constness); - coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind)); vis.visit_capture_by(capture_clause); - vis.visit_fn(FnKind::Closure(binder, fn_decl, body), *span, *id); + vis.visit_fn(FnKind::Closure(binder, coroutine_kind, fn_decl, body), *span, *id); vis.visit_span(fn_decl_span); vis.visit_span(fn_arg_span); } @@ -1785,8 +1843,20 @@ impl DummyAstNode for crate::ast_traits::AstNo #[derive(Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(&'a mut FnSig, &'a mut Generics, &'a mut Option>), + Fn( + FnCtxt, + &'a mut Ident, + &'a mut FnSig, + &'a mut Visibility, + &'a mut Generics, + &'a mut Option>, + ), /// E.g., `|x, y| body`. - Closure(&'a mut ClosureBinder, &'a mut P, &'a mut P), + Closure( + &'a mut ClosureBinder, + &'a mut Option, + &'a mut P, + &'a mut P, + ), } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 58497d70a24..3500c215376 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -66,7 +66,7 @@ impl BoundKind { #[derive(Copy, Clone, Debug)] pub enum FnKind<'a> { /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`. - Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, &'a Generics, Option<&'a Block>), + Fn(FnCtxt, &'a Ident, &'a FnSig, &'a Visibility, &'a Generics, &'a Option>), /// E.g., `|x, y| body`. Closure(&'a ClosureBinder, &'a Option, &'a FnDecl, &'a Expr), @@ -112,11 +112,15 @@ pub enum LifetimeCtxt { GenericArg, } -pub trait WalkItemKind: Sized { +pub trait WalkItemKind { + type Ctxt; fn walk<'a, V: Visitor<'a>>( &'a self, - item: &'a Item, - ctxt: AssocCtxt, + span: Span, + id: NodeId, + ident: &'a Ident, + visibility: &'a Visibility, + ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result; } @@ -268,8 +272,8 @@ pub trait Visitor<'ast>: Sized { fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) -> Self::Result { walk_fn_ret_ty(self, ret_ty) } - fn visit_fn_header(&mut self, _header: &'ast FnHeader) -> Self::Result { - Self::Result::output() + fn visit_fn_header(&mut self, header: &'ast FnHeader) -> Self::Result { + walk_fn_header(self, header) } fn visit_expr_field(&mut self, f: &'ast ExprField) -> Self::Result { walk_expr_field(self, f) @@ -292,6 +296,9 @@ pub trait Visitor<'ast>: Sized { fn visit_capture_by(&mut self, _capture_by: &'ast CaptureBy) -> Self::Result { Self::Result::output() } + fn visit_coroutine_kind(&mut self, _coroutine_kind: &'ast CoroutineKind) -> Self::Result { + Self::Result::output() + } } pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result { @@ -337,16 +344,19 @@ pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitR } impl WalkItemKind for ItemKind { + type Ctxt = (); fn walk<'a, V: Visitor<'a>>( &'a self, - item: &'a Item, - _ctxt: AssocCtxt, + span: Span, + id: NodeId, + ident: &'a Ident, + vis: &'a Visibility, + _ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { - let Item { id, span, vis, ident, .. } = item; match self { ItemKind::ExternCrate(_rename) => {} - ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, *id, false)), + ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, id, false)), ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); @@ -357,8 +367,8 @@ impl WalkItemKind for ItemKind { visit_opt!(visitor, visit_expr, expr); } ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = FnKind::Fn(FnCtxt::Free, *ident, sig, vis, generics, body.as_deref()); - try_visit!(visitor.visit_fn(kind, *span, *id)); + let kind = FnKind::Fn(FnCtxt::Free, ident, sig, vis, generics, body); + try_visit!(visitor.visit_fn(kind, span, id)); } ItemKind::Mod(_unsafety, mod_kind) => match mod_kind { ModKind::Loaded(items, _inline, _inner_span) => { @@ -415,7 +425,7 @@ impl WalkItemKind for ItemKind { walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); } ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), - ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, *id)), + ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, id)), ItemKind::Delegation(box Delegation { id, qself, @@ -431,7 +441,7 @@ impl WalkItemKind for ItemKind { } ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { try_visit!(walk_qself(visitor, qself)); - try_visit!(visitor.visit_path(prefix, *id)); + try_visit!(visitor.visit_path(prefix, id)); if let Some(suffixes) = suffixes { for (ident, rename) in suffixes { visitor.visit_ident(ident); @@ -449,9 +459,9 @@ impl WalkItemKind for ItemKind { pub fn walk_item<'a, V: Visitor<'a>>( visitor: &mut V, - item: &'a Item, + item: &'a Item>, ) -> V::Result { - walk_assoc_item(visitor, item, AssocCtxt::Trait /*ignored*/) + walk_assoc_item(visitor, item, ()) } pub fn walk_enum_def<'a, V: Visitor<'a>>( @@ -681,20 +691,23 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res } impl WalkItemKind for ForeignItemKind { + type Ctxt = (); fn walk<'a, V: Visitor<'a>>( &'a self, - item: &'a Item, - _ctxt: AssocCtxt, + span: Span, + id: NodeId, + ident: &'a Ident, + vis: &'a Visibility, + _ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { - let &Item { id, span, ident, ref vis, .. } = item; match self { ForeignItemKind::Static(box StaticItem { ty, mutability: _, expr, safety: _ }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref()); + let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body); try_visit!(visitor.visit_fn(kind, span, id)); } ForeignItemKind::TyAlias(box TyAlias { @@ -813,6 +826,12 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) V::Result::output() } +pub fn walk_fn_header<'a, V: Visitor<'a>>(visitor: &mut V, fn_header: &'a FnHeader) -> V::Result { + let FnHeader { safety: _, coroutine_kind, constness: _, ext: _ } = fn_header; + visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref()); + V::Result::output() +} + pub fn walk_fn_decl<'a, V: Visitor<'a>>( visitor: &mut V, FnDecl { inputs, output }: &'a FnDecl, @@ -830,8 +849,9 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu try_visit!(walk_fn_decl(visitor, decl)); visit_opt!(visitor, visit_block, body); } - FnKind::Closure(binder, _coroutine_kind, decl, body) => { + FnKind::Closure(binder, coroutine_kind, decl, body) => { try_visit!(visitor.visit_closure_binder(binder)); + visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref()); try_visit!(walk_fn_decl(visitor, decl)); try_visit!(visitor.visit_expr(body)); } @@ -840,13 +860,16 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu } impl WalkItemKind for AssocItemKind { + type Ctxt = AssocCtxt; fn walk<'a, V: Visitor<'a>>( &'a self, - item: &'a Item, - ctxt: AssocCtxt, + span: Span, + id: NodeId, + ident: &'a Ident, + vis: &'a Visibility, + ctxt: Self::Ctxt, visitor: &mut V, ) -> V::Result { - let &Item { id, span, ident, ref vis, .. } = item; match self { AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => { try_visit!(visitor.visit_generics(generics)); @@ -854,8 +877,7 @@ impl WalkItemKind for AssocItemKind { visit_opt!(visitor, visit_expr, expr); } AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => { - let kind = - FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref()); + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body); try_visit!(visitor.visit_fn(kind, span, id)); } AssocItemKind::Type(box TyAlias { @@ -903,16 +925,16 @@ impl WalkItemKind for AssocItemKind { } } -pub fn walk_assoc_item<'a, V: Visitor<'a>>( +pub fn walk_assoc_item<'a, V: Visitor<'a>, K: WalkItemKind>( visitor: &mut V, - item: &'a Item, - ctxt: AssocCtxt, + item: &'a Item, + ctxt: K::Ctxt, ) -> V::Result { - let Item { id: _, span: _, ident, vis, attrs, kind, tokens: _ } = item; + let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item; walk_list!(visitor, visit_attribute, attrs); try_visit!(visitor.visit_vis(vis)); try_visit!(visitor.visit_ident(ident)); - try_visit!(kind.walk(item, ctxt, visitor)); + try_visit!(kind.walk(*span, *id, ident, vis, ctxt, visitor)); V::Result::output() } diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index c47c12b4fd1..8cc4521e0a7 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -9,6 +9,7 @@ doctest = false [dependencies] # tidy-alphabetical-start rustc_ast = { path = "../rustc_ast" } +rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index a5ee6713be8..f704320c71d 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -103,6 +103,12 @@ ast_lowering_invalid_asm_template_modifier_reg_class = ast_lowering_invalid_asm_template_modifier_sym = asm template modifiers are not allowed for `sym` arguments +ast_lowering_invalid_legacy_const_generic_arg = + invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items + +ast_lowering_invalid_legacy_const_generic_arg_suggestion = + try using a const generic argument instead + ast_lowering_invalid_register = invalid register `{$reg}`: {$error} diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 6b39c2d3955..e6a3f939f2d 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -451,3 +451,26 @@ pub(crate) struct YieldInClosure { #[suggestion(code = "#[coroutine] ", applicability = "maybe-incorrect", style = "verbose")] pub suggestion: Option, } + +#[derive(Diagnostic)] +#[diag(ast_lowering_invalid_legacy_const_generic_arg)] +pub(crate) struct InvalidLegacyConstGenericArg { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub suggestion: UseConstGenericArg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + ast_lowering_invalid_legacy_const_generic_arg_suggestion, + applicability = "maybe-incorrect" +)] +pub(crate) struct UseConstGenericArg { + #[suggestion_part(code = "::<{const_args}>")] + pub end_of_fn: Span, + pub const_args: String, + pub other_args: String, + #[suggestion_part(code = "{other_args}")] + pub call_args: Span, +} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b7cf2d252dc..3af29838b72 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,18 +1,22 @@ use std::assert_matches::assert_matches; +use std::ops::ControlFlow; use rustc_ast::ptr::P as AstP; use rustc_ast::*; +use rustc_ast_pretty::pprust::expr_to_string; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_middle::span_bug; +use rustc_middle::ty::TyCtxt; use rustc_session::errors::report_lit_error; use rustc_span::source_map::{Spanned, respan}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; use thin_vec::{ThinVec, thin_vec}; +use visit::{Visitor, walk_expr}; use super::errors::{ AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot, @@ -23,9 +27,32 @@ use super::errors::{ use super::{ GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, }; -use crate::errors::YieldInClosure; +use crate::errors::{InvalidLegacyConstGenericArg, UseConstGenericArg, YieldInClosure}; use crate::{AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition, fluent_generated}; +struct WillCreateDefIdsVisitor {} + +impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor { + type Result = ControlFlow; + + fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { + ControlFlow::Break(c.value.span) + } + + fn visit_item(&mut self, item: &'v Item) -> Self::Result { + ControlFlow::Break(item.span) + } + + fn visit_expr(&mut self, ex: &'v Expr) -> Self::Result { + match ex.kind { + ExprKind::Gen(..) | ExprKind::ConstBlock(..) | ExprKind::Closure(..) => { + ControlFlow::Break(ex.span) + } + _ => walk_expr(self, ex), + } + } +} + impl<'hir> LoweringContext<'_, 'hir> { fn lower_exprs(&mut self, exprs: &[AstP]) -> &'hir [hir::Expr<'hir>] { self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x))) @@ -396,10 +423,34 @@ impl<'hir> LoweringContext<'_, 'hir> { unreachable!(); }; + let mut error = None; + let mut invalid_expr_error = |tcx: TyCtxt<'_>, span| { + // Avoid emitting the error multiple times. + if error.is_none() { + let mut const_args = vec![]; + let mut other_args = vec![]; + for (idx, arg) in args.iter().enumerate() { + if legacy_args_idx.contains(&idx) { + const_args.push(format!("{{ {} }}", expr_to_string(arg))); + } else { + other_args.push(expr_to_string(arg)); + } + } + let suggestion = UseConstGenericArg { + end_of_fn: f.span.shrink_to_hi(), + const_args: const_args.join(", "), + other_args: other_args.join(", "), + call_args: args[0].span.to(args.last().unwrap().span), + }; + error = Some(tcx.dcx().emit_err(InvalidLegacyConstGenericArg { span, suggestion })); + } + error.unwrap() + }; + // Split the arguments into const generics and normal arguments let mut real_args = vec![]; let mut generic_args = ThinVec::new(); - for (idx, arg) in args.into_iter().enumerate() { + for (idx, arg) in args.iter().cloned().enumerate() { if legacy_args_idx.contains(&idx) { let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); @@ -410,7 +461,20 @@ impl<'hir> LoweringContext<'_, 'hir> { self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); } - let anon_const = AnonConst { id: node_id, value: arg }; + let mut visitor = WillCreateDefIdsVisitor {}; + let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) { + AstP(Expr { + id: self.next_node_id(), + kind: ExprKind::Err(invalid_expr_error(self.tcx, span)), + span: f.span, + attrs: [].into(), + tokens: None, + }) + } else { + arg + }; + + let anon_const = AnonConst { id: node_id, value: const_value }; generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); } else { real_args.push(arg); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5a0e9e8aec0..d53280751fc 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -738,7 +738,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { allow_internal_unstable: Option>, ) -> Span { self.tcx.with_stable_hashing_context(|hcx| { - span.mark_with_reason(allow_internal_unstable, reason, self.tcx.sess.edition(), hcx) + span.mark_with_reason(allow_internal_unstable, reason, span.edition(), hcx) }) } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index dee48586f34..07a6f4e5ee7 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -946,8 +946,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.visit_vis(&item.vis); self.visit_ident(&item.ident); - let kind = - FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref()); + let kind = FnKind::Fn(FnCtxt::Free, &item.ident, sig, &item.vis, generics, body); self.visit_fn(kind, item.span, item.id); walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. @@ -1476,14 +1475,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { { self.visit_vis(&item.vis); self.visit_ident(&item.ident); - let kind = FnKind::Fn( - FnCtxt::Assoc(ctxt), - item.ident, - sig, - &item.vis, - generics, - body.as_deref(), - ); + let kind = + FnKind::Fn(FnCtxt::Assoc(ctxt), &item.ident, sig, &item.vis, generics, body); walk_list!(self, visit_attribute, &item.attrs); self.visit_fn(kind, item.span, item.id); } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index d832decc170..7adc7a8863e 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -1,93 +1,171 @@ +use std::fmt; + use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph; use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{self, BasicBlock, Body, Location, Place, TerminatorEdges}; +use rustc_middle::mir::{ + self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges, +}; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; -use rustc_mir_dataflow::{Analysis, Forward, GenKill, Results, ResultsVisitable}; +use rustc_mir_dataflow::{Analysis, GenKill, JoinSemiLattice, SwitchIntEdgeEffects}; use tracing::debug; use crate::{BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, places_conflict}; -/// The results of the dataflow analyses used by the borrow checker. -pub(crate) struct BorrowckResults<'a, 'tcx> { - pub(crate) borrows: Results<'tcx, Borrows<'a, 'tcx>>, - pub(crate) uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>, - pub(crate) ever_inits: Results<'tcx, EverInitializedPlaces<'a, 'tcx>>, +// This analysis is different to most others. Its results aren't computed with +// `iterate_to_fixpoint`, but are instead composed from the results of three sub-analyses that are +// computed individually with `iterate_to_fixpoint`. +pub(crate) struct Borrowck<'a, 'tcx> { + pub(crate) borrows: Borrows<'a, 'tcx>, + pub(crate) uninits: MaybeUninitializedPlaces<'a, 'tcx>, + pub(crate) ever_inits: EverInitializedPlaces<'a, 'tcx>, +} + +impl<'a, 'tcx> Analysis<'tcx> for Borrowck<'a, 'tcx> { + type Domain = BorrowckDomain<'a, 'tcx>; + + const NAME: &'static str = "borrowck"; + + fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { + BorrowckDomain { + borrows: self.borrows.bottom_value(body), + uninits: self.uninits.bottom_value(body), + ever_inits: self.ever_inits.bottom_value(body), + } + } + + fn initialize_start_block(&self, _body: &mir::Body<'tcx>, _state: &mut Self::Domain) { + // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. + unreachable!(); + } + + fn apply_before_statement_effect( + &mut self, + state: &mut Self::Domain, + stmt: &mir::Statement<'tcx>, + loc: Location, + ) { + self.borrows.apply_before_statement_effect(&mut state.borrows, stmt, loc); + self.uninits.apply_before_statement_effect(&mut state.uninits, stmt, loc); + self.ever_inits.apply_before_statement_effect(&mut state.ever_inits, stmt, loc); + } + + fn apply_statement_effect( + &mut self, + state: &mut Self::Domain, + stmt: &mir::Statement<'tcx>, + loc: Location, + ) { + self.borrows.apply_statement_effect(&mut state.borrows, stmt, loc); + self.uninits.apply_statement_effect(&mut state.uninits, stmt, loc); + self.ever_inits.apply_statement_effect(&mut state.ever_inits, stmt, loc); + } + + fn apply_before_terminator_effect( + &mut self, + state: &mut Self::Domain, + term: &mir::Terminator<'tcx>, + loc: Location, + ) { + self.borrows.apply_before_terminator_effect(&mut state.borrows, term, loc); + self.uninits.apply_before_terminator_effect(&mut state.uninits, term, loc); + self.ever_inits.apply_before_terminator_effect(&mut state.ever_inits, term, loc); + } + + fn apply_terminator_effect<'mir>( + &mut self, + state: &mut Self::Domain, + term: &'mir mir::Terminator<'tcx>, + loc: Location, + ) -> TerminatorEdges<'mir, 'tcx> { + self.borrows.apply_terminator_effect(&mut state.borrows, term, loc); + self.uninits.apply_terminator_effect(&mut state.uninits, term, loc); + self.ever_inits.apply_terminator_effect(&mut state.ever_inits, term, loc); + + // This return value doesn't matter. It's only used by `iterate_to_fixpoint`, which this + // analysis doesn't use. + TerminatorEdges::None + } + + fn apply_call_return_effect( + &mut self, + _state: &mut Self::Domain, + _block: BasicBlock, + _return_places: CallReturnPlaces<'_, 'tcx>, + ) { + // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. + unreachable!(); + } + + fn apply_switch_int_edge_effects( + &mut self, + _block: BasicBlock, + _discr: &mir::Operand<'tcx>, + _apply_edge_effects: &mut impl SwitchIntEdgeEffects, + ) { + // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. + unreachable!(); + } +} + +impl JoinSemiLattice for BorrowckDomain<'_, '_> { + fn join(&mut self, _other: &Self) -> bool { + // This is only reachable from `iterate_to_fixpoint`, which this analysis doesn't use. + unreachable!(); + } +} + +impl<'tcx, C> DebugWithContext for BorrowckDomain<'_, 'tcx> +where + C: rustc_mir_dataflow::move_paths::HasMoveData<'tcx>, +{ + fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("borrows: ")?; + self.borrows.fmt_with(ctxt, f)?; + f.write_str(" uninits: ")?; + self.uninits.fmt_with(ctxt, f)?; + f.write_str(" ever_inits: ")?; + self.ever_inits.fmt_with(ctxt, f)?; + Ok(()) + } + + fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self == old { + return Ok(()); + } + + if self.borrows != old.borrows { + f.write_str("borrows: ")?; + self.borrows.fmt_diff_with(&old.borrows, ctxt, f)?; + f.write_str("\n")?; + } + + if self.uninits != old.uninits { + f.write_str("uninits: ")?; + self.uninits.fmt_diff_with(&old.uninits, ctxt, f)?; + f.write_str("\n")?; + } + + if self.ever_inits != old.ever_inits { + f.write_str("ever_inits: ")?; + self.ever_inits.fmt_diff_with(&old.ever_inits, ctxt, f)?; + f.write_str("\n")?; + } + + Ok(()) + } } /// The transient state of the dataflow analyses used by the borrow checker. -#[derive(Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub(crate) struct BorrowckDomain<'a, 'tcx> { pub(crate) borrows: as Analysis<'tcx>>::Domain, pub(crate) uninits: as Analysis<'tcx>>::Domain, pub(crate) ever_inits: as Analysis<'tcx>>::Domain, } -impl<'a, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'a, 'tcx> { - type Direction = Forward; - type Domain = BorrowckDomain<'a, 'tcx>; - - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { - BorrowckDomain { - borrows: self.borrows.analysis.bottom_value(body), - uninits: self.uninits.analysis.bottom_value(body), - ever_inits: self.ever_inits.analysis.bottom_value(body), - } - } - - fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) { - state.borrows.clone_from(self.borrows.entry_set_for_block(block)); - state.uninits.clone_from(self.uninits.entry_set_for_block(block)); - state.ever_inits.clone_from(self.ever_inits.entry_set_for_block(block)); - } - - fn reconstruct_before_statement_effect( - &mut self, - state: &mut Self::Domain, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - self.borrows.analysis.apply_before_statement_effect(&mut state.borrows, stmt, loc); - self.uninits.analysis.apply_before_statement_effect(&mut state.uninits, stmt, loc); - self.ever_inits.analysis.apply_before_statement_effect(&mut state.ever_inits, stmt, loc); - } - - fn reconstruct_statement_effect( - &mut self, - state: &mut Self::Domain, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - self.borrows.analysis.apply_statement_effect(&mut state.borrows, stmt, loc); - self.uninits.analysis.apply_statement_effect(&mut state.uninits, stmt, loc); - self.ever_inits.analysis.apply_statement_effect(&mut state.ever_inits, stmt, loc); - } - - fn reconstruct_before_terminator_effect( - &mut self, - state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - self.borrows.analysis.apply_before_terminator_effect(&mut state.borrows, term, loc); - self.uninits.analysis.apply_before_terminator_effect(&mut state.uninits, term, loc); - self.ever_inits.analysis.apply_before_terminator_effect(&mut state.ever_inits, term, loc); - } - - fn reconstruct_terminator_effect( - &mut self, - state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - self.borrows.analysis.apply_terminator_effect(&mut state.borrows, term, loc); - self.uninits.analysis.apply_terminator_effect(&mut state.uninits, term, loc); - self.ever_inits.analysis.apply_terminator_effect(&mut state.ever_inits, term, loc); - } -} - rustc_index::newtype_index! { #[orderable] #[debug_format = "bw{}"] diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 657e6e0907c..7eaf265d410 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -36,13 +36,13 @@ use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; -use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::{ EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, }; use rustc_mir_dataflow::move_paths::{ InitIndex, InitLocation, LookupResult, MoveData, MoveOutIndex, MovePathIndex, }; +use rustc_mir_dataflow::{Analysis, EntrySets, Results, ResultsVisitor, visit_results}; use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use smallvec::SmallVec; @@ -50,7 +50,7 @@ use tracing::{debug, instrument}; use crate::borrow_set::{BorrowData, BorrowSet}; use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions}; -use crate::dataflow::{BorrowIndex, BorrowckDomain, BorrowckResults, Borrows}; +use crate::dataflow::{BorrowIndex, Borrowck, BorrowckDomain, Borrows}; use crate::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName}; use crate::location::LocationTable; use crate::nll::PoloniusOutput; @@ -221,6 +221,10 @@ fn do_mir_borrowck<'tcx>( consumer_options, ); + // `flow_inits` is large, so we drop it as soon as possible. This reduces + // peak memory usage significantly on some benchmarks. + drop(flow_inits); + // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. nll::dump_nll_mir(&infcx, body, ®ioncx, &opt_closure_req, &borrow_set); @@ -229,27 +233,6 @@ fn do_mir_borrowck<'tcx>( // information. nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, &opaque_type_values, diags); - // The various `flow_*` structures can be large. We drop `flow_inits` here - // so it doesn't overlap with the others below. This reduces peak memory - // usage significantly on some benchmarks. - drop(flow_inits); - - let flow_borrows = Borrows::new(tcx, body, ®ioncx, &borrow_set).iterate_to_fixpoint( - tcx, - body, - Some("borrowck"), - ); - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data).iterate_to_fixpoint( - tcx, - body, - Some("borrowck"), - ); - let flow_ever_inits = EverInitializedPlaces::new(body, &move_data).iterate_to_fixpoint( - tcx, - body, - Some("borrowck"), - ); - let movable_coroutine = // The first argument is the coroutine type passed by value if let Some(local) = body.local_decls.raw.get(1) @@ -334,16 +317,11 @@ fn do_mir_borrowck<'tcx>( // Compute and report region errors, if any. mbcx.report_region_errors(nll_errors); - let mut results = BorrowckResults { - ever_inits: flow_ever_inits, - uninits: flow_uninits, - borrows: flow_borrows, - }; - - rustc_mir_dataflow::visit_results( + let mut flow_results = get_flow_results(tcx, body, &move_data, &borrow_set, ®ioncx); + visit_results( body, traversal::reverse_postorder(body).map(|(bb, _)| bb), - &mut results, + &mut flow_results, &mut mbcx, ); @@ -426,6 +404,47 @@ fn do_mir_borrowck<'tcx>( (result, body_with_facts) } +fn get_flow_results<'a, 'tcx>( + tcx: TyCtxt<'tcx>, + body: &'a Body<'tcx>, + move_data: &'a MoveData<'tcx>, + borrow_set: &'a BorrowSet<'tcx>, + regioncx: &RegionInferenceContext<'tcx>, +) -> Results<'tcx, Borrowck<'a, 'tcx>> { + // We compute these three analyses individually, but them combine them into + // a single results so that `mbcx` can visit them all together. + let borrows = Borrows::new(tcx, body, regioncx, borrow_set).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); + let uninits = MaybeUninitializedPlaces::new(tcx, body, move_data).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); + let ever_inits = EverInitializedPlaces::new(body, move_data).iterate_to_fixpoint( + tcx, + body, + Some("borrowck"), + ); + + let analysis = Borrowck { + borrows: borrows.analysis, + uninits: uninits.analysis, + ever_inits: ever_inits.analysis, + }; + + assert_eq!(borrows.entry_sets.len(), uninits.entry_sets.len()); + assert_eq!(borrows.entry_sets.len(), ever_inits.entry_sets.len()); + let entry_sets: EntrySets<'_, Borrowck<'_, '_>> = + itertools::izip!(borrows.entry_sets, uninits.entry_sets, ever_inits.entry_sets) + .map(|(borrows, uninits, ever_inits)| BorrowckDomain { borrows, uninits, ever_inits }) + .collect(); + + Results { analysis, entry_sets } +} + pub(crate) struct BorrowckInferCtxt<'tcx> { pub(crate) infcx: InferCtxt<'tcx>, pub(crate) reg_var_to_origin: RefCell>, @@ -588,14 +607,10 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> { // 2. loans made in overlapping scopes do not conflict // 3. assignments do not affect things loaned out as immutable // 4. moves do not affect things loaned out in any way -impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> - for MirBorrowckCtxt<'a, '_, 'tcx> -{ - type Domain = BorrowckDomain<'a, 'tcx>; - +impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, '_, 'tcx> { fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, stmt: &'a Statement<'tcx>, location: Location, @@ -667,7 +682,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, term: &'a Terminator<'tcx>, loc: Location, @@ -780,7 +795,7 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, + _results: &mut Results<'tcx, Borrowck<'a, 'tcx>>, state: &BorrowckDomain<'a, 'tcx>, term: &'a Terminator<'tcx>, loc: Location, diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index f419c1e776b..e7ee6b43e27 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -204,10 +204,10 @@ impl MutVisitor for CfgEval<'_> { fn flat_map_assoc_item( &mut self, item: P, - _ctxt: AssocCtxt, + ctxt: AssocCtxt, ) -> SmallVec<[P; 1]> { let item = configure!(self, item); - mut_visit::walk_flat_map_item(self, item) + mut_visit::walk_flat_map_assoc_item(self, item, ctxt) } fn flat_map_foreign_item( diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 95348453308..ba5d34359aa 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -144,7 +144,15 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { item.kind { let prev_tests = mem::take(&mut self.tests); - walk_item_kind(&mut item.kind, item.span, item.id, self); + walk_item_kind( + &mut item.kind, + item.span, + item.id, + &mut item.ident, + &mut item.vis, + (), + self, + ); self.add_test_cases(item.id, span, prev_tests); } else { // But in those cases, we emit a lint to warn the user of these missing tests. diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 1e2e41b3122..b92885cc1a7 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -453,11 +453,6 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return Ok(()); } - sym::likely | sym::unlikely => { - intrinsic_args!(fx, args => (a); intrinsic); - - ret.write_cvalue(fx, a); - } sym::breakpoint => { intrinsic_args!(fx, args => (); intrinsic); @@ -1267,6 +1262,10 @@ fn codegen_regular_intrinsic_call<'tcx>( ); } + sym::cold_path => { + // This is a no-op. The intrinsic is just a hint to the optimizer. + } + // Unimplemented intrinsics must have a fallback body. The fallback body is obtained // by converting the `InstanceKind::Intrinsic` to an `InstanceKind::Item`. _ => { diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index b0298a35cb0..225f294e1e4 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -139,8 +139,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc &args.iter().map(|arg| arg.immediate()).collect::>(), ) } - sym::likely => self.expect(args[0].immediate(), true), - sym::unlikely => self.expect(args[0].immediate(), false), sym::is_val_statically_known => { let a = args[0].immediate(); let builtin = self.context.get_builtin_function("__builtin_constant_p"); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index e9c687d75e3..b56f464975d 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -192,7 +192,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { Some(instance), ) } - sym::likely => self.expect(args[0].immediate(), true), sym::is_val_statically_known => { let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx); let kind = self.type_kind(intrinsic_type); @@ -213,7 +212,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { self.const_bool(false) } } - sym::unlikely => self.expect(args[0].immediate(), false), sym::select_unpredictable => { let cond = args[0].immediate(); assert_eq!(args[1].layout, args[2].layout); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 027d80350e4..097d37bb70c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -377,20 +377,32 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // If there are two targets (one conditional, one fallback), emit `br` instead of // `switch`. let (test_value, target) = target_iter.next().unwrap(); - let lltrue = helper.llbb_with_cleanup(self, target); - let llfalse = helper.llbb_with_cleanup(self, targets.otherwise()); + let otherwise = targets.otherwise(); + let lltarget = helper.llbb_with_cleanup(self, target); + let llotherwise = helper.llbb_with_cleanup(self, otherwise); + let target_cold = self.cold_blocks[target]; + let otherwise_cold = self.cold_blocks[otherwise]; + // If `target_cold == otherwise_cold`, the branches have the same weight + // so there is no expectation. If they differ, the `target` branch is expected + // when the `otherwise` branch is cold. + let expect = if target_cold == otherwise_cold { None } else { Some(otherwise_cold) }; if switch_ty == bx.tcx().types.bool { // Don't generate trivial icmps when switching on bool. match test_value { - 0 => bx.cond_br(discr_value, llfalse, lltrue), - 1 => bx.cond_br(discr_value, lltrue, llfalse), + 0 => { + let expect = expect.map(|e| !e); + bx.cond_br_with_expect(discr_value, llotherwise, lltarget, expect); + } + 1 => { + bx.cond_br_with_expect(discr_value, lltarget, llotherwise, expect); + } _ => bug!(), } } else { let switch_llty = bx.immediate_backend_type(bx.layout_of(switch_ty)); let llval = bx.const_uint_big(switch_llty, test_value); let cmp = bx.icmp(IntPredicate::IntEQ, discr_value, llval); - bx.cond_br(cmp, lltrue, llfalse); + bx.cond_br_with_expect(cmp, lltarget, llotherwise, expect); } } else if self.cx.sess().opts.optimize == OptLevel::No && target_iter.len() == 2 diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index c9e38bb80c2..2a1b9e28c1e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -498,6 +498,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + sym::cold_path => { + // This is a no-op. The intrinsic is just a hint to the optimizer. + return Ok(()); + } + _ => { // Need to use backend-specific things in the implementation. return bx.codegen_intrinsic_call(instance, fn_abi, args, llresult, span); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 20fd08923ec..f19e3b72141 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -91,6 +91,10 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Cached terminate upon unwinding block and its reason terminate_block: Option<(Bx::BasicBlock, UnwindTerminateReason)>, + /// A bool flag for each basic block indicating whether it is a cold block. + /// A cold block is a block that is unlikely to be executed at runtime. + cold_blocks: IndexVec, + /// The location where each MIR arg/var/tmp/ret is stored. This is /// usually an `PlaceRef` representing an alloca, but not always: /// sometimes we can skip the alloca and just store the value @@ -207,6 +211,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cleanup_kinds, landing_pads: IndexVec::from_elem(None, &mir.basic_blocks), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()), + cold_blocks: find_cold_blocks(cx.tcx(), mir), locals: locals::Locals::empty(), debug_context, per_local_var_debug_info: None, @@ -477,3 +482,39 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( args } + +fn find_cold_blocks<'tcx>( + tcx: TyCtxt<'tcx>, + mir: &mir::Body<'tcx>, +) -> IndexVec { + let local_decls = &mir.local_decls; + + let mut cold_blocks: IndexVec = + IndexVec::from_elem(false, &mir.basic_blocks); + + // Traverse all basic blocks from end of the function to the start. + for (bb, bb_data) in traversal::postorder(mir) { + let terminator = bb_data.terminator(); + + // If a BB ends with a call to a cold function, mark it as cold. + if let mir::TerminatorKind::Call { ref func, .. } = terminator.kind + && let ty::FnDef(def_id, ..) = *func.ty(local_decls, tcx).kind() + && let attrs = tcx.codegen_fn_attrs(def_id) + && attrs.flags.contains(CodegenFnAttrFlags::COLD) + { + cold_blocks[bb] = true; + continue; + } + + // If all successors of a BB are cold and there's at least one of them, mark this BB as cold + let mut succ = terminator.successors(); + if let Some(first) = succ.next() + && cold_blocks[first] + && succ.all(|s| cold_blocks[s]) + { + cold_blocks[bb] = true; + } + } + + cold_blocks +} diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 74cd522a30f..b0138ac8bfe 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -84,6 +84,26 @@ pub trait BuilderMethods<'a, 'tcx>: then_llbb: Self::BasicBlock, else_llbb: Self::BasicBlock, ); + + // Conditional with expectation. + // + // This function is opt-in for back ends. + // + // The default implementation calls `self.expect()` before emiting the branch + // by calling `self.cond_br()` + fn cond_br_with_expect( + &mut self, + mut cond: Self::Value, + then_llbb: Self::BasicBlock, + else_llbb: Self::BasicBlock, + expect: Option, + ) { + if let Some(expect) = expect { + cond = self.expect(cond, expect); + } + self.cond_br(cond, then_llbb, else_llbb) + } + fn switch( &mut self, v: Self::Value, diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 6686413bf02..1271d9d2d0d 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -152,13 +152,20 @@ where let span = span.substitute_dummy(our_span); let err = mk(span, frames); let mut err = tcx.dcx().create_err(err); + let can_be_spurious = matches!(error, InterpErrorKind::ResourceExhaustion(_)); let msg = error.diagnostic_message(); error.add_args(&mut err); // Use *our* span to label the interp error err.span_label(our_span, msg); - ErrorHandled::Reported(err.emit().into(), span) + let g = err.emit(); + let reported = if can_be_spurious { + ReportedErrorInfo::spurious(g) + } else { + ReportedErrorInfo::from(g) + }; + ErrorHandled::Reported(reported, span) } } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 62115aef4a7..f12320cb851 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -263,6 +263,12 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { } /// See documentation on the `ptr_guaranteed_cmp` intrinsic. + /// Returns `2` if the result is unknown. + /// Returns `1` if the pointers are guaranteed equal. + /// Returns `0` if the pointers are guaranteed inequal. + /// + /// Note that this intrinsic is exposed on stable for comparison with null. In other words, any + /// change to this function that affects comparison with null is insta-stable! fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> { interp_ok(match (a, b) { // Comparisons between integers are always known. diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index ff6d5b28b3b..eb574bd5f77 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -596,6 +596,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // const-eval will return "tainted" errors if e.g. the layout cannot // be computed as the type references non-existing names. // See . + } else if reported.can_be_spurious() { + // These errors can just sometimes happen, even when the expression + // is nominally "infallible", e.g. when running out of memory. } else { // Looks like the const is not captured by `required_consts`, that's bad. span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts"); diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c7a56a80e81..d89d73824aa 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -417,6 +417,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // These just return their argument self.copy_op(&args[0], dest)?; } + sym::cold_path => { + // This is a no-op. The intrinsic is just a hint to the optimizer. + } sym::raw_eq => { let result = self.raw_eq_intrinsic(&args[0], &args[1])?; self.write_scalar(result, dest)?; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 04ac7891023..91786462b40 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1303,7 +1303,7 @@ impl InvocationCollectorNode for AstNodeWrapper, TraitItemTag> fragment.make_trait_items() } fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_item(visitor, self.wrapped) + walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Trait) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) @@ -1344,7 +1344,7 @@ impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag> fragment.make_impl_items() } fn walk_flat_map(self, visitor: &mut V) -> Self::OutputTy { - walk_flat_map_item(visitor, self.wrapped) + walk_flat_map_assoc_item(visitor, self.wrapped, AssocCtxt::Impl) } fn is_mac_call(&self) -> bool { matches!(self.wrapped.kind, AssocItemKind::MacCall(..)) diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 610c69e9d21..90206b19bd5 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -286,7 +286,7 @@ impl MutVisitor for PlaceholderExpander { AssocCtxt::Impl => it.make_impl_items(), } } - _ => walk_flat_map_item(self, item), + _ => walk_flat_map_assoc_item(self, item, ctxt), } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index cb954b0adcb..3e33120901f 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -109,9 +109,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::three_way_compare | sym::discriminant_value | sym::type_id - | sym::likely - | sym::unlikely | sym::select_unpredictable + | sym::cold_path | sym::ptr_guaranteed_cmp | sym::minnumf16 | sym::minnumf32 @@ -489,9 +488,8 @@ pub fn check_intrinsic_type( sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)), sym::assume => (0, 0, vec![tcx.types.bool], tcx.types.unit), - sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool), - sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool), sym::select_unpredictable => (1, 0, vec![tcx.types.bool, param(0), param(0)], param(0)), + sym::cold_path => (0, 0, vec![], tcx.types.unit), sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)), sym::write_via_move => { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index cc55f57c46c..b4b3ef31f97 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -177,6 +177,7 @@ enum Scope<'a> { LateBoundary { s: ScopeRef<'a>, what: &'static str, + deny_late_regions: bool, }, Root { @@ -234,9 +235,11 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("s", &"..") .finish(), Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), - Scope::LateBoundary { s: _, what } => { - f.debug_struct("LateBoundary").field("what", what).finish() - } + Scope::LateBoundary { s: _, what, deny_late_regions } => f + .debug_struct("LateBoundary") + .field("what", what) + .field("deny_late_regions", deny_late_regions) + .finish(), Scope::Root { opt_parent_item } => { f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish() } @@ -573,17 +576,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // give, we will reverse the IndexMap after early captures. let mut late_depth = 0; let mut scope = self.scope; - let mut crossed_late_boundary = None; let mut opaque_capture_scopes = vec![(opaque.def_id, &captures)]; loop { match *scope { Scope::Binder { ref bound_vars, scope_type, s, .. } => { for (&original_lifetime, &def) in bound_vars.iter().rev() { - if let ResolvedArg::LateBound(..) = def - && crossed_late_boundary.is_some() - { - continue; - } if let DefKind::LifetimeParam = self.tcx.def_kind(original_lifetime) { let def = def.shifted(late_depth); let ident = lifetime_ident(original_lifetime); @@ -624,12 +621,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } - | Scope::TraitRefBoundary { s, .. } => { - scope = s; - } - - Scope::LateBoundary { s, what, .. } => { - crossed_late_boundary = Some(what); + | Scope::TraitRefBoundary { s, .. } + | Scope::LateBoundary { s, .. } => { scope = s; } } @@ -640,7 +633,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let scope = Scope::Opaque { captures: &captures, def_id: opaque.def_id, s: self.scope }; self.with(scope, |this| { let scope = Scope::TraitRefBoundary { s: this.scope }; - this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque)) + this.with(scope, |this| { + let scope = Scope::LateBoundary { + s: this.scope, + what: "nested `impl Trait`", + // We can capture late-bound regions; we just don't duplicate + // lifetime or const params, so we can't allow those. + deny_late_regions: false, + }; + this.with(scope, |this| intravisit::walk_opaque_ty(this, opaque)) + }) }); let captures = captures.into_inner().into_iter().collect(); @@ -997,9 +999,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { - self.with(Scope::LateBoundary { s: self.scope, what: "constant" }, |this| { - intravisit::walk_anon_const(this, c); - }); + self.with( + Scope::LateBoundary { s: self.scope, what: "constant", deny_late_regions: true }, + |this| { + intravisit::walk_anon_const(this, c); + }, + ); } fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) { @@ -1291,8 +1296,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { scope = s; } - Scope::LateBoundary { s, what } => { - crossed_late_boundary = Some(what); + Scope::LateBoundary { s, what, deny_late_regions } => { + if deny_late_regions { + crossed_late_boundary = Some(what); + } scope = s; } } @@ -1508,7 +1515,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { scope = s; } - Scope::LateBoundary { s, what } => { + Scope::LateBoundary { s, what, deny_late_regions: _ } => { crossed_late_boundary = Some(what); scope = s; } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index acccff77a10..ef9b3dbd13b 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -68,6 +68,10 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { } impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> { + fn visit_coroutine_kind(&mut self, coroutine_kind: &'a ast::CoroutineKind) -> Self::Result { + self.check_id(coroutine_kind.closure_id()); + } + fn visit_param(&mut self, param: &'a ast::Param) { self.with_lint_attrs(param.id, ¶m.attrs, |cx| { lint_callback!(cx, check_param, param); @@ -111,17 +115,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> self.with_lint_attrs(e.id, &e.attrs, |cx| { lint_callback!(cx, check_expr, e); ast_visit::walk_expr(cx, e); - // Explicitly check for lints associated with 'closure_id', since - // it does not have a corresponding AST node - match e.kind { - ast::ExprKind::Closure(box ast::Closure { - coroutine_kind: Some(coroutine_kind), - .. - }) => { - cx.check_id(coroutine_kind.closure_id()); - } - _ => {} - } lint_callback!(cx, check_expr_post, e); }) } @@ -156,14 +149,6 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> lint_callback!(self, check_fn, fk, span, id); self.check_id(id); ast_visit::walk_fn(self, fk); - - // Explicitly check for lints associated with 'closure_id', since - // it does not have a corresponding AST node - if let ast_visit::FnKind::Fn(_, _, sig, _, _, _) = fk { - if let Some(coroutine_kind) = sig.header.coroutine_kind { - self.check_id(coroutine_kind.closure_id()); - } - } } fn visit_variant_data(&mut self, s: &'a ast::VariantData) { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index b50a95e7d2b..6c13127b04e 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -584,6 +584,7 @@ enum UnusedDelimsCtx { MatchScrutineeExpr, ReturnValue, BlockRetValue, + BreakValue, LetScrutineeExpr, ArrayLenExpr, AnonConst, @@ -605,6 +606,7 @@ impl From for &'static str { UnusedDelimsCtx::MatchScrutineeExpr => "`match` scrutinee expression", UnusedDelimsCtx::ReturnValue => "`return` value", UnusedDelimsCtx::BlockRetValue => "block return value", + UnusedDelimsCtx::BreakValue => "`break` value", UnusedDelimsCtx::LetScrutineeExpr => "`let` scrutinee expression", UnusedDelimsCtx::ArrayLenExpr | UnusedDelimsCtx::AnonConst => "const expression", UnusedDelimsCtx::MatchArmExpr => "match arm expression", @@ -913,6 +915,10 @@ trait UnusedDelimLint { (value, UnusedDelimsCtx::ReturnValue, false, Some(left), None, true) } + Break(_, Some(ref value)) => { + (value, UnusedDelimsCtx::BreakValue, false, None, None, true) + } + Index(_, ref value, _) => (value, UnusedDelimsCtx::IndexExpr, false, None, None, false), Assign(_, ref value, _) | AssignOp(.., ref value) => { @@ -1063,6 +1069,9 @@ impl UnusedDelimLint for UnusedParens { _, _, ) if node.is_lazy())) + && !((ctx == UnusedDelimsCtx::ReturnValue + || ctx == UnusedDelimsCtx::BreakValue) + && matches!(inner.kind, ast::ExprKind::Assign(_, _, _))) { self.emit_unused_delims_expr(cx, value, ctx, left_pos, right_pos, is_kw) } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 51146cfd2e9..efdb4b077e9 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4185,7 +4185,7 @@ declare_lint! { Warn, "never type fallback affecting unsafe function calls", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange, + reason: FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(Edition::Edition2024), reference: "issue #123748 ", }; @edition Edition2024 => Deny; @@ -4239,7 +4239,7 @@ declare_lint! { Warn, "never type fallback affecting unsafe function calls", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::EditionAndFutureReleaseError(Edition::Edition2024), reference: "issue #123748 ", }; report_in_external_macro diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 0caf6ef3a6d..eac4afee050 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -381,6 +381,8 @@ pub enum FutureIncompatibilityReason { /// hard errors (and the lint removed). Preferably when there is some /// confidence that the number of impacted projects is very small (few /// should have a broken dependency in their dependency tree). + /// + /// [`EditionAndFutureReleaseError`]: FutureIncompatibilityReason::EditionAndFutureReleaseError FutureReleaseErrorReportInDeps, /// Code that changes meaning in some way in a /// future release. @@ -419,6 +421,28 @@ pub enum FutureIncompatibilityReason { /// slightly changes the text of the diagnostic, but is otherwise the /// same. EditionSemanticsChange(Edition), + /// This will be an error in the provided edition *and* in a future + /// release. + /// + /// This variant a combination of [`FutureReleaseErrorDontReportInDeps`] + /// and [`EditionError`]. This is useful in rare cases when we + /// want to have "preview" of a breaking change in an edition, but do a + /// breaking change later on all editions anyway. + /// + /// [`EditionError`]: FutureIncompatibilityReason::EditionError + /// [`FutureReleaseErrorDontReportInDeps`]: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps + EditionAndFutureReleaseError(Edition), + /// This will change meaning in the provided edition *and* in a future + /// release. + /// + /// This variant a combination of [`FutureReleaseSemanticsChange`] + /// and [`EditionSemanticsChange`]. This is useful in rare cases when we + /// want to have "preview" of a breaking change in an edition, but do a + /// breaking change later on all editions anyway. + /// + /// [`EditionSemanticsChange`]: FutureIncompatibilityReason::EditionSemanticsChange + /// [`FutureReleaseSemanticsChange`]: FutureIncompatibilityReason::FutureReleaseSemanticsChange + EditionAndFutureReleaseSemanticsChange(Edition), /// A custom reason. /// /// Choose this variant if the built-in text of the diagnostic of the @@ -431,9 +455,15 @@ pub enum FutureIncompatibilityReason { impl FutureIncompatibilityReason { pub fn edition(self) -> Option { match self { - Self::EditionError(e) => Some(e), - Self::EditionSemanticsChange(e) => Some(e), - _ => None, + Self::EditionError(e) + | Self::EditionSemanticsChange(e) + | Self::EditionAndFutureReleaseError(e) + | Self::EditionAndFutureReleaseSemanticsChange(e) => Some(e), + + FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps + | FutureIncompatibilityReason::FutureReleaseErrorReportInDeps + | FutureIncompatibilityReason::FutureReleaseSemanticsChange + | FutureIncompatibilityReason::Custom(_) => None, } } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index b5862565e8e..92ba6ceee93 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -382,6 +382,17 @@ pub fn lint_level( FutureIncompatibilityReason::EditionSemanticsChange(edition) => { format!("this changes meaning in Rust {edition}") } + FutureIncompatibilityReason::EditionAndFutureReleaseError(edition) => { + format!( + "this was previously accepted by the compiler but is being phased out; \ + it will become a hard error in Rust {edition} and in a future release in all editions!" + ) + } + FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(edition) => { + format!( + "this changes meaning in Rust {edition} and in a future release in all editions!" + ) + } FutureIncompatibilityReason::Custom(reason) => reason.to_owned(), }; diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 8ec7e1851a5..08afa33c6b4 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -59,22 +59,33 @@ impl ErrorHandled { pub struct ReportedErrorInfo { error: ErrorGuaranteed, is_tainted_by_errors: bool, + /// Whether this is the kind of error that can sometimes occur, and sometimes not. + /// Used for resource exhaustion errors. + can_be_spurious: bool, } impl ReportedErrorInfo { #[inline] pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo { - ReportedErrorInfo { is_tainted_by_errors: true, error } + ReportedErrorInfo { is_tainted_by_errors: true, can_be_spurious: false, error } } + #[inline] + pub fn spurious(error: ErrorGuaranteed) -> ReportedErrorInfo { + ReportedErrorInfo { can_be_spurious: true, is_tainted_by_errors: false, error } + } + pub fn is_tainted_by_errors(&self) -> bool { self.is_tainted_by_errors } + pub fn can_be_spurious(&self) -> bool { + self.can_be_spurious + } } impl From for ReportedErrorInfo { #[inline] fn from(error: ErrorGuaranteed) -> ReportedErrorInfo { - ReportedErrorInfo { is_tainted_by_errors: false, error } + ReportedErrorInfo { is_tainted_by_errors: false, can_be_spurious: false, error } } } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index d8d99deeb2c..244d22d082f 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -46,7 +46,7 @@ pub enum InstantiationMode { LocalCopy, } -#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash, HashStable)] +#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash, HashStable, TyEncodable, TyDecodable)] pub enum MonoItem<'tcx> { Fn(Instance<'tcx>), Static(DefId), @@ -66,20 +66,7 @@ impl<'tcx> MonoItem<'tcx> { // change NON_INCR_MIN_CGU_SIZE as well. pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize { match *self { - MonoItem::Fn(instance) => { - match instance.def { - // "Normal" functions size estimate: the number of - // statements, plus one for the terminator. - InstanceKind::Item(..) - | InstanceKind::DropGlue(..) - | InstanceKind::AsyncDropGlueCtorShim(..) => { - let mir = tcx.instance_mir(instance.def); - mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum() - } - // Other compiler-generated shims size estimate: 1 - _ => 1, - } - } + MonoItem::Fn(instance) => tcx.size_estimate(instance), // Conservatively estimate the size of a static declaration or // assembly item to be 1. MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1, @@ -556,3 +543,21 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> { Symbol::intern(&cgu_name) } } + +/// See module-level docs of `rustc_monomorphize::collector` on some context for "mentioned" items. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub enum CollectionMode { + /// Collect items that are used, i.e., actually needed for codegen. + /// + /// Which items are used can depend on optimization levels, as MIR optimizations can remove + /// uses. + UsedItems, + /// Collect items that are mentioned. The goal of this mode is that it is independent of + /// optimizations: the set of "mentioned" items is computed before optimizations are run. + /// + /// The exact contents of this set are *not* a stable guarantee. (For instance, it is currently + /// computed after drop-elaboration. If we ever do some optimizations even in debug builds, we + /// might decide to run them before computing mentioned items.) The key property of this set is + /// that it is optimization-independent. + MentionedItems, +} diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 1d4c36e28bd..013847f0b2d 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -216,6 +216,10 @@ impl EraseType for (&'_ T0, &'_ [T1]) { type Result = [u8; size_of::<(&'static (), &'static [()])>()]; } +impl EraseType for (&'_ [T0], &'_ [T1]) { + type Result = [u8; size_of::<(&'static [()], &'static [()])>()]; +} + impl EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) { type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()]; } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index fe28ef0f70c..c5def5fc65b 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -7,6 +7,7 @@ use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{DUMMY_SP, Span}; use crate::infer::canonical::CanonicalQueryInput; +use crate::mir::mono::CollectionMode; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::{TyAndLayout, ValidityRequirement}; use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt}; @@ -590,3 +591,11 @@ impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) { } } } + +impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) { + type Cache = DefaultCache; + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.0.default_span(tcx) + } +} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4e3668822ec..4068d06f6df 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -40,6 +40,7 @@ use rustc_session::cstore::{ }; use rustc_session::lint::LintExpectationId; use rustc_span::def_id::LOCAL_CRATE; +use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; use rustc_span::{DUMMY_SP, Span}; use rustc_target::spec::PanicStrategy; @@ -59,7 +60,7 @@ use crate::mir::interpret::{ EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId, LitToConstError, LitToConstInput, }; -use crate::mir::mono::CodegenUnit; +use crate::mir::mono::{CodegenUnit, CollectionMode, MonoItem}; use crate::query::erase::{Erase, erase, restore}; use crate::query::plumbing::{ CyclePlaceholder, DynamicQuery, query_ensure, query_ensure_error_guaranteed, query_get_at, @@ -2339,6 +2340,16 @@ rustc_queries! { arena_cache desc { "functions to skip for move-size check" } } + + query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> (&'tcx [Spanned>], &'tcx [Spanned>]) { + desc { "collecting items used by `{}`", key.0 } + cache_on_disk_if { true } + } + + query size_estimate(key: ty::Instance<'tcx>) -> usize { + desc { "estimating codegen size of `{}`", key } + cache_on_disk_if { true } + } } rustc_query_append! { define_callbacks! } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 8b77a4a81ca..3849cb72668 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -12,6 +12,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_macros::{Decodable, Encodable}; use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; +use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::{self, interpret}; use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -22,7 +23,7 @@ use rustc_session::Session; use rustc_span::hygiene::{ ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, }; -use rustc_span::source_map::SourceMap; +use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::{ BytePos, CachingSourceMapView, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span, SpanDecoder, SpanEncoder, StableSourceFileId, Symbol, @@ -773,6 +774,13 @@ impl<'a, 'tcx> Decodable> for &'tcx [rustc_ast::InlineAsm } } +impl<'a, 'tcx> Decodable> for &'tcx [Spanned>] { + #[inline] + fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { + RefDecodable::decode(d) + } +} + impl<'a, 'tcx> Decodable> for &'tcx crate::traits::specialization_graph::Graph { diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index b5358f0ca35..47a84d4b258 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -13,9 +13,11 @@ use std::marker::DiscriminantKind; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; +use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::TyCtxt; use rustc_serialize::{Decodable, Encodable}; use rustc_span::Span; +use rustc_span::source_map::Spanned; pub use rustc_type_ir::{TyDecoder, TyEncoder}; use crate::arena::ArenaAllocatable; @@ -397,6 +399,15 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> } } +impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [Spanned>] { + fn decode(decoder: &mut D) -> &'tcx Self { + decoder + .interner() + .arena + .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder))) + } +} + impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List { diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 3e01f0512c4..9a5cf9d4e84 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -4,8 +4,8 @@ use rustc_middle::mir::{ self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, }; -use super::visitor::{ResultsVisitable, ResultsVisitor}; -use super::{Analysis, Effect, EffectIndex, SwitchIntTarget}; +use super::visitor::ResultsVisitor; +use super::{Analysis, Effect, EffectIndex, Results, SwitchIntTarget}; pub trait Direction { const IS_FORWARD: bool; @@ -33,14 +33,14 @@ pub trait Direction { where A: Analysis<'tcx>; - fn visit_results_in_block<'mir, 'tcx, D, R>( - state: &mut D, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>; + A: Analysis<'tcx>; fn join_state_into_successors_of<'tcx, A>( analysis: &mut A, @@ -53,7 +53,7 @@ pub trait Direction { A: Analysis<'tcx>; } -/// Dataflow that runs from the exit of a block (the terminator), to its entry (the first statement). +/// Dataflow that runs from the exit of a block (terminator), to its entry (the first statement). pub struct Backward; impl Direction for Backward { @@ -157,32 +157,32 @@ impl Direction for Backward { analysis.apply_statement_effect(state, statement, location); } - fn visit_results_in_block<'mir, 'tcx, D, R>( - state: &mut D, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>, + A: Analysis<'tcx>, { - results.reset_to_block_entry(state, block); + state.clone_from(results.entry_set_for_block(block)); vis.visit_block_end(state); // Terminator let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.reconstruct_before_terminator_effect(state, term, loc); + results.analysis.apply_before_terminator_effect(state, term, loc); vis.visit_terminator_before_primary_effect(results, state, term, loc); - results.reconstruct_terminator_effect(state, term, loc); + results.analysis.apply_terminator_effect(state, term, loc); vis.visit_terminator_after_primary_effect(results, state, term, loc); for (statement_index, stmt) in block_data.statements.iter().enumerate().rev() { let loc = Location { block, statement_index }; - results.reconstruct_before_statement_effect(state, stmt, loc); + results.analysis.apply_before_statement_effect(state, stmt, loc); vis.visit_statement_before_primary_effect(results, state, stmt, loc); - results.reconstruct_statement_effect(state, stmt, loc); + results.analysis.apply_statement_effect(state, stmt, loc); vis.visit_statement_after_primary_effect(results, state, stmt, loc); } @@ -389,32 +389,32 @@ impl Direction for Forward { } } - fn visit_results_in_block<'mir, 'tcx, F, R>( - state: &mut F, + fn visit_results_in_block<'mir, 'tcx, A>( + state: &mut A::Domain, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = F>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = F>, + A: Analysis<'tcx>, { - results.reset_to_block_entry(state, block); + state.clone_from(results.entry_set_for_block(block)); vis.visit_block_start(state); for (statement_index, stmt) in block_data.statements.iter().enumerate() { let loc = Location { block, statement_index }; - results.reconstruct_before_statement_effect(state, stmt, loc); + results.analysis.apply_before_statement_effect(state, stmt, loc); vis.visit_statement_before_primary_effect(results, state, stmt, loc); - results.reconstruct_statement_effect(state, stmt, loc); + results.analysis.apply_statement_effect(state, stmt, loc); vis.visit_statement_after_primary_effect(results, state, stmt, loc); } let loc = Location { block, statement_index: block_data.statements.len() }; let term = block_data.terminator(); - results.reconstruct_before_terminator_effect(state, term, loc); + results.analysis.apply_before_terminator_effect(state, term, loc); vis.visit_terminator_before_primary_effect(results, state, term, loc); - results.reconstruct_terminator_effect(state, term, loc); + results.analysis.apply_terminator_effect(state, term, loc); vis.visit_terminator_after_primary_effect(results, state, term, loc); vis.visit_block_end(state); diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index bac75b972f9..98a4f58cb5d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -544,20 +544,18 @@ impl StateDiffCollector { } } -impl<'tcx, A> ResultsVisitor<'_, 'tcx, Results<'tcx, A>> for StateDiffCollector +impl<'tcx, A> ResultsVisitor<'_, 'tcx, A> for StateDiffCollector where A: Analysis<'tcx>, A::Domain: DebugWithContext, { - type Domain = A::Domain; - - fn visit_block_start(&mut self, state: &Self::Domain) { + fn visit_block_start(&mut self, state: &A::Domain) { if A::Direction::IS_FORWARD { self.prev_state.clone_from(state); } } - fn visit_block_end(&mut self, state: &Self::Domain) { + fn visit_block_end(&mut self, state: &A::Domain) { if A::Direction::IS_BACKWARD { self.prev_state.clone_from(state); } @@ -566,7 +564,7 @@ where fn visit_statement_before_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { @@ -579,7 +577,7 @@ where fn visit_statement_after_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _statement: &mir::Statement<'tcx>, _location: Location, ) { @@ -590,7 +588,7 @@ where fn visit_terminator_before_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { @@ -603,7 +601,7 @@ where fn visit_terminator_after_primary_effect( &mut self, results: &mut Results<'tcx, A>, - state: &Self::Domain, + state: &A::Domain, _terminator: &mir::Terminator<'tcx>, _location: Location, ) { diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index 8f81da8bb04..244dfe26ad3 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -55,8 +55,8 @@ mod visitor; pub use self::cursor::ResultsCursor; pub use self::direction::{Backward, Direction, Forward}; pub use self::lattice::{JoinSemiLattice, MaybeReachable}; -pub use self::results::Results; -pub use self::visitor::{ResultsVisitable, ResultsVisitor, visit_results}; +pub use self::results::{EntrySets, Results}; +pub use self::visitor::{ResultsVisitor, visit_results}; /// Analysis domains are all bitsets of various kinds. This trait holds /// operations needed by all of them. diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs index 366fcbf33ba..ff6cafbfbae 100644 --- a/compiler/rustc_mir_dataflow/src/framework/results.rs +++ b/compiler/rustc_mir_dataflow/src/framework/results.rs @@ -18,7 +18,7 @@ use crate::errors::{ DuplicateValuesFor, PathMustEndInFilename, RequiresAnArgument, UnknownFormatter, }; -type EntrySets<'tcx, A> = IndexVec>::Domain>; +pub type EntrySets<'tcx, A> = IndexVec>::Domain>; /// A dataflow analysis that has converged to fixpoint. #[derive(Clone)] @@ -27,7 +27,7 @@ where A: Analysis<'tcx>, { pub analysis: A, - pub(super) entry_sets: EntrySets<'tcx, A>, + pub entry_sets: EntrySets<'tcx, A>, } impl<'tcx, A> Results<'tcx, A> @@ -51,7 +51,7 @@ where &mut self, body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, - vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { visit_results(body, blocks, self, vis) } @@ -59,7 +59,7 @@ where pub fn visit_reachable_with<'mir>( &mut self, body: &'mir mir::Body<'tcx>, - vis: &mut impl ResultsVisitor<'mir, 'tcx, Self, Domain = A::Domain>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) { let blocks = traversal::reachable(body); visit_results(body, blocks.map(|(bb, _)| bb), self, vis) diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index 3d6b008a684..5c7539eed4d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -4,15 +4,15 @@ use super::{Analysis, Direction, Results}; /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the /// dataflow state at that location. -pub fn visit_results<'mir, 'tcx, D, R>( +pub fn visit_results<'mir, 'tcx, A>( body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, - results: &mut R, - vis: &mut impl ResultsVisitor<'mir, 'tcx, R, Domain = D>, + results: &mut Results<'tcx, A>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, A>, ) where - R: ResultsVisitable<'tcx, Domain = D>, + A: Analysis<'tcx>, { - let mut state = results.bottom_value(body); + let mut state = results.analysis.bottom_value(body); #[cfg(debug_assertions)] let reachable_blocks = mir::traversal::reachable_as_bitset(body); @@ -22,23 +22,23 @@ pub fn visit_results<'mir, 'tcx, D, R>( assert!(reachable_blocks.contains(block)); let block_data = &body[block]; - R::Direction::visit_results_in_block(&mut state, block, block_data, results, vis); + A::Direction::visit_results_in_block(&mut state, block, block_data, results, vis); } } -/// A visitor over the results of an `Analysis`. The type parameter `R` is the results type being -/// visited. -pub trait ResultsVisitor<'mir, 'tcx, R> { - type Domain; - - fn visit_block_start(&mut self, _state: &Self::Domain) {} +/// A visitor over the results of an `Analysis`. +pub trait ResultsVisitor<'mir, 'tcx, A> +where + A: Analysis<'tcx>, +{ + fn visit_block_start(&mut self, _state: &A::Domain) {} /// Called with the `before_statement_effect` of the given statement applied to `state` but not /// its `statement_effect`. fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, _location: Location, ) { @@ -48,19 +48,19 @@ pub trait ResultsVisitor<'mir, 'tcx, R> { /// statement applied to `state`. fn visit_statement_after_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, _location: Location, ) { } - /// Called with the `before_terminator_effect` of the given terminator applied to `state` but not - /// its `terminator_effect`. + /// Called with the `before_terminator_effect` of the given terminator applied to `state` but + /// not its `terminator_effect`. fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, _location: Location, ) { @@ -72,109 +72,12 @@ pub trait ResultsVisitor<'mir, 'tcx, R> { /// The `call_return_effect` (if one exists) will *not* be applied to `state`. fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, - _state: &Self::Domain, + _results: &mut Results<'tcx, A>, + _state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, _location: Location, ) { } - fn visit_block_end(&mut self, _state: &Self::Domain) {} -} - -/// Things that can be visited by a `ResultsVisitor`. -/// -/// This trait exists so that we can visit the results of one or more dataflow analyses -/// simultaneously. -pub trait ResultsVisitable<'tcx> { - type Direction: Direction; - type Domain; - - /// Creates an empty `Domain` to hold the transient state for these dataflow results. - /// - /// The value of the newly created `Domain` will be overwritten by `reset_to_block_entry` - /// before it can be observed by a `ResultsVisitor`. - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain; - - fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock); - - fn reconstruct_before_statement_effect( - &mut self, - state: &mut Self::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ); - - fn reconstruct_statement_effect( - &mut self, - state: &mut Self::Domain, - statement: &mir::Statement<'tcx>, - location: Location, - ); - - fn reconstruct_before_terminator_effect( - &mut self, - state: &mut Self::Domain, - terminator: &mir::Terminator<'tcx>, - location: Location, - ); - - fn reconstruct_terminator_effect( - &mut self, - state: &mut Self::Domain, - terminator: &mir::Terminator<'tcx>, - location: Location, - ); -} - -impl<'tcx, A> ResultsVisitable<'tcx> for Results<'tcx, A> -where - A: Analysis<'tcx>, -{ - type Domain = A::Domain; - type Direction = A::Direction; - - fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { - self.analysis.bottom_value(body) - } - - fn reset_to_block_entry(&self, state: &mut Self::Domain, block: BasicBlock) { - state.clone_from(self.entry_set_for_block(block)); - } - - fn reconstruct_before_statement_effect( - &mut self, - state: &mut Self::Domain, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - self.analysis.apply_before_statement_effect(state, stmt, loc); - } - - fn reconstruct_statement_effect( - &mut self, - state: &mut Self::Domain, - stmt: &mir::Statement<'tcx>, - loc: Location, - ) { - self.analysis.apply_statement_effect(state, stmt, loc); - } - - fn reconstruct_before_terminator_effect( - &mut self, - state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - self.analysis.apply_before_terminator_effect(state, term, loc); - } - - fn reconstruct_terminator_effect( - &mut self, - state: &mut Self::Domain, - term: &mir::Terminator<'tcx>, - loc: Location, - ) { - self.analysis.apply_terminator_effect(state, term, loc); - } + fn visit_block_end(&mut self, _state: &A::Domain) {} } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index b404e3bfb72..ab1453f1ed0 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -18,8 +18,8 @@ pub use self::drop_flag_effects::{ move_path_children_matching, on_all_children_bits, on_lookup_result_bits, }; pub use self::framework::{ - Analysis, Backward, Direction, Forward, GenKill, JoinSemiLattice, MaybeReachable, Results, - ResultsCursor, ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice, + Analysis, Backward, Direction, EntrySets, Forward, GenKill, JoinSemiLattice, MaybeReachable, + Results, ResultsCursor, ResultsVisitor, SwitchIntEdgeEffects, fmt, graphviz, lattice, visit_results, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_dataflow/src/points.rs b/compiler/rustc_mir_dataflow/src/points.rs index 73abb669a11..10f1e009855 100644 --- a/compiler/rustc_mir_dataflow/src/points.rs +++ b/compiler/rustc_mir_dataflow/src/points.rs @@ -3,7 +3,7 @@ use rustc_index::interval::SparseIntervalMatrix; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, BasicBlock, Body, Location}; -use crate::framework::{ResultsVisitable, ResultsVisitor, visit_results}; +use crate::framework::{Analysis, Results, ResultsVisitor, visit_results}; /// Maps between a `Location` and a `PointIndex` (and vice versa). pub struct DenseLocationMap { @@ -95,14 +95,14 @@ rustc_index::newtype_index! { } /// Add points depending on the result of the given dataflow analysis. -pub fn save_as_intervals<'tcx, N, R>( +pub fn save_as_intervals<'tcx, N, A>( elements: &DenseLocationMap, body: &mir::Body<'tcx>, - mut results: R, + mut results: Results<'tcx, A>, ) -> SparseIntervalMatrix where N: Idx, - R: ResultsVisitable<'tcx, Domain = BitSet>, + A: Analysis<'tcx, Domain = BitSet>, { let values = SparseIntervalMatrix::new(elements.num_points()); let mut visitor = Visitor { elements, values }; @@ -120,16 +120,15 @@ struct Visitor<'a, N: Idx> { values: SparseIntervalMatrix, } -impl<'mir, 'tcx, R, N> ResultsVisitor<'mir, 'tcx, R> for Visitor<'_, N> +impl<'mir, 'tcx, A, N> ResultsVisitor<'mir, 'tcx, A> for Visitor<'_, N> where + A: Analysis<'tcx, Domain = BitSet>, N: Idx, { - type Domain = BitSet; - fn visit_statement_after_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, A>, + state: &A::Domain, _statement: &'mir mir::Statement<'tcx>, location: Location, ) { @@ -142,8 +141,8 @@ where fn visit_terminator_after_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, A>, + state: &A::Domain, _terminator: &'mir mir::Terminator<'tcx>, location: Location, ) { diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 063f220501f..c2666caa1e8 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -68,11 +68,11 @@ use rustc_middle::ty::{ self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode, }; use rustc_middle::{bug, span_bug}; -use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, }; use rustc_mir_dataflow::storage::always_storage_live_locals; +use rustc_mir_dataflow::{Analysis, Results, ResultsVisitor}; use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::symbol::sym; @@ -817,9 +817,9 @@ impl ops::Deref for CoroutineSavedLocals { /// computation; see `CoroutineLayout` for more. fn compute_storage_conflicts<'mir, 'tcx>( body: &'mir Body<'tcx>, - saved_locals: &CoroutineSavedLocals, + saved_locals: &'mir CoroutineSavedLocals, always_live_locals: BitSet, - mut requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, + mut requires_storage: Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), saved_locals.domain_size()); @@ -877,15 +877,13 @@ struct StorageConflictVisitor<'a, 'tcx> { eligible_storage_live: BitSet, } -impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> +impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, MaybeRequiresStorage<'a, 'tcx>> for StorageConflictVisitor<'a, 'tcx> { - type Domain = BitSet; - fn visit_statement_before_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, + state: &BitSet, _statement: &'a Statement<'tcx>, loc: Location, ) { @@ -894,8 +892,8 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R> fn visit_terminator_before_primary_effect( &mut self, - _results: &mut R, - state: &Self::Domain, + _results: &mut Results<'tcx, MaybeRequiresStorage<'a, 'tcx>>, + state: &BitSet, _terminator: &'a Terminator<'tcx>, loc: Location, ) { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 7d073f1fa57..ab6460c490b 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -941,16 +941,12 @@ fn try_write_constant<'tcx>( interp_ok(()) } -impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx>>> - for Collector<'_, 'tcx> -{ - type Domain = State>; - +impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx> { #[instrument(level = "trace", skip(self, results, statement))] fn visit_statement_before_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, statement: &'mir Statement<'tcx>, location: Location, ) { @@ -972,7 +968,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx fn visit_statement_after_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, statement: &'mir Statement<'tcx>, location: Location, ) { @@ -997,7 +993,7 @@ impl<'mir, 'tcx> ResultsVisitor<'mir, 'tcx, Results<'tcx, ConstAnalysis<'_, 'tcx fn visit_terminator_before_primary_effect( &mut self, results: &mut Results<'tcx, ConstAnalysis<'_, 'tcx>>, - state: &Self::Domain, + state: &State>, terminator: &'mir Terminator<'tcx>, location: Location, ) { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 429e31b2c88..322deb539cd 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -207,6 +207,7 @@ use std::path::PathBuf; +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{LRef, MTLock, par_for_each_in}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; @@ -215,7 +216,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar}; -use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; +use rustc_middle::mir::mono::{CollectionMode, InstantiationMode, MonoItem}; use rustc_middle::mir::visit::Visitor as MirVisitor; use rustc_middle::mir::{self, Location, MentionedItem, traversal}; use rustc_middle::query::TyCtxtAt; @@ -243,16 +244,6 @@ pub(crate) enum MonoItemCollectionStrategy { Lazy, } -pub(crate) struct UsageMap<'tcx> { - // Maps every mono item to the mono items used by it. - used_map: UnordMap, Vec>>, - - // Maps every mono item to the mono items that use it. - user_map: UnordMap, Vec>>, -} - -type MonoItems<'tcx> = Vec>>; - /// The state that is shared across the concurrent threads that are doing collection. struct SharedState<'tcx> { /// Items that have been or are currently being recursively collected. @@ -264,22 +255,12 @@ struct SharedState<'tcx> { usage_map: MTLock>, } -/// See module-level docs on some contect for "mentioned" items. -#[derive(Copy, Clone, Debug, PartialEq)] -enum CollectionMode { - /// Collect items that are used, i.e., actually needed for codegen. - /// - /// Which items are used can depend on optimization levels, as MIR optimizations can remove - /// uses. - UsedItems, - /// Collect items that are mentioned. The goal of this mode is that it is independent of - /// optimizations: the set of "mentioned" items is computed before optimizations are run. - /// - /// The exact contents of this set are *not* a stable guarantee. (For instance, it is currently - /// computed after drop-elaboration. If we ever do some optimizations even in debug builds, we - /// might decide to run them before computing mentioned items.) The key property of this set is - /// that it is optimization-independent. - MentionedItems, +pub(crate) struct UsageMap<'tcx> { + // Maps every mono item to the mono items used by it. + used_map: UnordMap, Vec>>, + + // Maps every mono item to the mono items that use it. + user_map: UnordMap, Vec>>, } impl<'tcx> UsageMap<'tcx> { @@ -287,19 +268,15 @@ impl<'tcx> UsageMap<'tcx> { UsageMap { used_map: Default::default(), user_map: Default::default() } } - fn record_used<'a>( - &mut self, - user_item: MonoItem<'tcx>, - used_items: &'a [Spanned>], - ) where + fn record_used<'a>(&mut self, user_item: MonoItem<'tcx>, used_items: &'a MonoItems<'tcx>) + where 'tcx: 'a, { - let used_items: Vec<_> = used_items.iter().map(|item| item.node).collect(); - for &used_item in used_items.iter() { + for used_item in used_items.items() { self.user_map.entry(used_item).or_default().push(user_item); } - assert!(self.used_map.insert(user_item, used_items).is_none()); + assert!(self.used_map.insert(user_item, used_items.items().collect()).is_none()); } pub(crate) fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] { @@ -325,6 +302,52 @@ impl<'tcx> UsageMap<'tcx> { } } +struct MonoItems<'tcx> { + // We want a set of MonoItem + Span where trying to re-insert a MonoItem with a different Span + // is ignored. Map does that, but it looks odd. + items: FxIndexMap, Span>, +} + +impl<'tcx> MonoItems<'tcx> { + fn new() -> Self { + Self { items: FxIndexMap::default() } + } + + fn is_empty(&self) -> bool { + self.items.is_empty() + } + + fn push(&mut self, item: Spanned>) { + // Insert only if the entry does not exist. A normal insert would stomp the first span that + // got inserted. + self.items.entry(item.node).or_insert(item.span); + } + + fn items(&self) -> impl Iterator> + '_ { + self.items.keys().cloned() + } +} + +impl<'tcx> IntoIterator for MonoItems<'tcx> { + type Item = Spanned>; + type IntoIter = impl Iterator>>; + + fn into_iter(self) -> Self::IntoIter { + self.items.into_iter().map(|(item, span)| respan(span, item)) + } +} + +impl<'tcx> Extend>> for MonoItems<'tcx> { + fn extend(&mut self, iter: I) + where + I: IntoIterator>>, + { + for item in iter { + self.push(item) + } + } +} + /// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a /// post-monomorphization error is encountered during a collection step. /// @@ -443,13 +466,9 @@ fn collect_items_rec<'tcx>( )); rustc_data_structures::stack::ensure_sufficient_stack(|| { - collect_items_of_instance( - tcx, - instance, - &mut used_items, - &mut mentioned_items, - mode, - ) + let (used, mentioned) = tcx.items_of_instance((instance, mode)); + used_items.extend(used.into_iter().copied()); + mentioned_items.extend(mentioned.into_iter().copied()); }); } MonoItem::GlobalAsm(item_id) => { @@ -1171,14 +1190,12 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt /// Scans the MIR in order to find function calls, closures, and drop-glue. /// /// Anything that's found is added to `output`. Furthermore the "mentioned items" of the MIR are returned. -#[instrument(skip(tcx, used_items, mentioned_items), level = "debug")] +#[instrument(skip(tcx), level = "debug")] fn collect_items_of_instance<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, - used_items: &mut MonoItems<'tcx>, - mentioned_items: &mut MonoItems<'tcx>, mode: CollectionMode, -) { +) -> (MonoItems<'tcx>, MonoItems<'tcx>) { // This item is getting monomorphized, do mono-time checks. tcx.ensure().check_mono_item(instance); @@ -1193,11 +1210,13 @@ fn collect_items_of_instance<'tcx>( // mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already // added to `used_items` in a hash set, which can efficiently query in the // `body.mentioned_items` loop below without even having to monomorphize the item. + let mut used_items = MonoItems::new(); + let mut mentioned_items = MonoItems::new(); let mut used_mentioned_items = Default::default(); let mut collector = MirUsedCollector { tcx, body, - used_items, + used_items: &mut used_items, used_mentioned_items: &mut used_mentioned_items, instance, }; @@ -1212,7 +1231,7 @@ fn collect_items_of_instance<'tcx>( // them errors. for const_op in body.required_consts() { if let Some(val) = collector.eval_constant(const_op) { - collect_const_value(tcx, val, mentioned_items); + collect_const_value(tcx, val, &mut mentioned_items); } } @@ -1221,9 +1240,23 @@ fn collect_items_of_instance<'tcx>( for item in body.mentioned_items() { if !collector.used_mentioned_items.contains(&item.node) { let item_mono = collector.monomorphize(item.node); - visit_mentioned_item(tcx, &item_mono, item.span, mentioned_items); + visit_mentioned_item(tcx, &item_mono, item.span, &mut mentioned_items); } } + + (used_items, mentioned_items) +} + +fn items_of_instance<'tcx>( + tcx: TyCtxt<'tcx>, + (instance, mode): (Instance<'tcx>, CollectionMode), +) -> (&'tcx [Spanned>], &'tcx [Spanned>]) { + let (used_items, mentioned_items) = collect_items_of_instance(tcx, instance, mode); + + let used_items = tcx.arena.alloc_from_iter(used_items); + let mentioned_items = tcx.arena.alloc_from_iter(mentioned_items); + + (used_items, mentioned_items) } /// `item` must be already monomorphized. @@ -1304,7 +1337,7 @@ fn collect_const_value<'tcx>( #[instrument(skip(tcx, mode), level = "debug")] fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec> { debug!("collecting roots"); - let mut roots = Vec::new(); + let mut roots = MonoItems::new(); { let entry_fn = tcx.entry_fn(()); @@ -1596,4 +1629,5 @@ pub(crate) fn collect_crate_mono_items<'tcx>( pub(crate) fn provide(providers: &mut Providers) { providers.hooks.should_codegen_locally = should_codegen_locally; + providers.items_of_instance = items_of_instance; } diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 0cfc4371db5..eb576317678 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -2,6 +2,7 @@ #![feature(array_windows)] #![feature(file_buffered)] #![feature(if_let_guard)] +#![feature(impl_trait_in_assoc_type)] #![feature(let_chains)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index d53595929e7..02b361456e4 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -36,9 +36,7 @@ fn do_check_abi<'tcx>( target_feature_def: DefId, mut emit_err: impl FnMut(Option<&'static str>), ) { - let Some(feature_def) = tcx.sess.target.features_for_correct_vector_abi() else { - return; - }; + let feature_def = tcx.sess.target.features_for_correct_vector_abi(); let codegen_attrs = tcx.codegen_fn_attrs(target_feature_def); for arg_abi in abi.args.iter().chain(std::iter::once(&abi.ret)) { let size = arg_abi.layout.size; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index e2a6d392ca0..84e08ea881d 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -1319,5 +1319,20 @@ pub(crate) fn provide(providers: &mut Providers) { .unwrap_or_else(|| panic!("failed to find cgu with name {name:?}")) }; + providers.size_estimate = |tcx, instance| { + match instance.def { + // "Normal" functions size estimate: the number of + // statements, plus one for the terminator. + InstanceKind::Item(..) + | InstanceKind::DropGlue(..) + | InstanceKind::AsyncDropGlueCtorShim(..) => { + let mir = tcx.instance_mir(instance.def); + mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum() + } + // Other compiler-generated shims size estimate: 1 + _ => 1, + } + }; + collector::provide(providers); } diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 7ec4ad6dc35..37eb463cba6 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -650,8 +650,9 @@ pub(crate) struct LeftArrowOperator { #[diag(parse_remove_let)] pub(crate) struct RemoveLet { #[primary_span] - #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] pub span: Span, + #[suggestion(applicability = "machine-applicable", code = "", style = "verbose")] + pub suggestion: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0ac6133e828..0012db471ef 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2683,6 +2683,13 @@ impl<'a> Parser<'a> { // ^^ // } // + // We account for macro calls that were meant as conditions as well. + // + // if ... { + // } else if macro! { foo bar } { + // ^^ + // } + // // If $cond is "statement-like" such as ExprKind::While then we // want to suggest wrapping in braces. // @@ -2693,7 +2700,9 @@ impl<'a> Parser<'a> { // } // ^ if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) - && classify::expr_requires_semi_to_be_stmt(&cond) => + && (classify::expr_requires_semi_to_be_stmt(&cond) + || matches!(cond.kind, ExprKind::MacCall(..))) + => { self.dcx().emit_err(errors::ExpectedElseBlock { first_tok_span, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 3546e5b0f04..c4326427f67 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -685,7 +685,7 @@ impl<'a> Parser<'a> { self.bump(); // Trim extra space after the `let` let span = lo.with_hi(self.token.span.lo()); - self.dcx().emit_err(RemoveLet { span }); + self.dcx().emit_err(RemoveLet { span: lo, suggestion: span }); lo = self.token.span; } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index b7cdae3e3e1..190cd9ed061 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -475,6 +475,7 @@ impl<'a> Parser<'a> { } fn error_block_no_opening_brace_msg(&mut self, msg: Cow<'static, str>) -> Diag<'a> { + let prev = self.prev_token.span; let sp = self.token.span; let mut e = self.dcx().struct_span_err(sp, msg); let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon; @@ -514,14 +515,11 @@ impl<'a> Parser<'a> { } else { stmt.span }; - e.multipart_suggestion( - "try placing this code inside a block", - vec![ - (stmt_span.shrink_to_lo(), "{ ".to_string()), - (stmt_span.shrink_to_hi(), " }".to_string()), - ], - // Speculative; has been misleading in the past (#46836). - Applicability::MaybeIncorrect, + self.suggest_fixes_misparsed_for_loop_head( + &mut e, + prev.between(sp), + stmt_span, + &stmt.kind, ); } Err(e) => { @@ -534,6 +532,103 @@ impl<'a> Parser<'a> { e } + fn suggest_fixes_misparsed_for_loop_head( + &self, + e: &mut Diag<'_>, + between: Span, + stmt_span: Span, + stmt_kind: &StmtKind, + ) { + match (&self.token.kind, &stmt_kind) { + (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Call(..) = expr.kind => + { + // for _ in x y() {} + e.span_suggestion_verbose( + between, + "you might have meant to write a method call", + ".".to_string(), + Applicability::MaybeIncorrect, + ); + } + (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Field(..) = expr.kind => + { + // for _ in x y.z {} + e.span_suggestion_verbose( + between, + "you might have meant to write a field access", + ".".to_string(), + Applicability::MaybeIncorrect, + ); + } + (token::CloseDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Struct(expr) = &expr.kind + && let None = expr.qself + && expr.path.segments.len() == 1 => + { + // This is specific to "mistyped `if` condition followed by empty body" + // + // for _ in x y {} + e.span_suggestion_verbose( + between, + "you might have meant to write a field access", + ".".to_string(), + Applicability::MaybeIncorrect, + ); + } + (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Lit(lit) = expr.kind + && let None = lit.suffix + && let token::LitKind::Integer | token::LitKind::Float = lit.kind => + { + // for _ in x 0 {} + // for _ in x 0.0 {} + e.span_suggestion_verbose( + between, + format!("you might have meant to write a field access"), + ".".to_string(), + Applicability::MaybeIncorrect, + ); + } + (token::OpenDelim(Delimiter::Brace), StmtKind::Expr(expr)) + if let ExprKind::Loop(..) + | ExprKind::If(..) + | ExprKind::While(..) + | ExprKind::Match(..) + | ExprKind::ForLoop { .. } + | ExprKind::TryBlock(..) + | ExprKind::Ret(..) + | ExprKind::Closure(..) + | ExprKind::Struct(..) + | ExprKind::Try(..) = expr.kind => + { + // These are more likely to have been meant as a block body. + e.multipart_suggestion( + "you might have meant to write this as part of a block", + vec![ + (stmt_span.shrink_to_lo(), "{ ".to_string()), + (stmt_span.shrink_to_hi(), " }".to_string()), + ], + // Speculative; has been misleading in the past (#46836). + Applicability::MaybeIncorrect, + ); + } + (token::OpenDelim(Delimiter::Brace), _) => {} + (_, _) => { + e.multipart_suggestion( + "you might have meant to write this as part of a block", + vec![ + (stmt_span.shrink_to_lo(), "{ ".to_string()), + (stmt_span.shrink_to_hi(), " }".to_string()), + ], + // Speculative; has been misleading in the past (#46836). + Applicability::MaybeIncorrect, + ); + } + } + } + fn error_block_no_opening_brace(&mut self) -> PResult<'a, T> { let tok = super::token_descr(&self.token); let msg = format!("expected `{{`, found {tok}"); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index bdf940a04b5..293cee500bb 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1324,7 +1324,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // This way they can use `macro_rules` defined later. self.visit_vis(&item.vis); self.visit_ident(&item.ident); - item.kind.walk(item, AssocCtxt::Trait, self); + item.kind.walk(item.span, item.id, &item.ident, &item.vis, (), self); visit::walk_list!(self, visit_attribute, &item.attrs); } _ => visit::walk_item(self, item), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 42c6221dc57..5d4ba4be5b8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -589,6 +589,7 @@ symbols! { cmse_nonsecure_entry, coerce_unsized, cold, + cold_path, collapse_debuginfo, column, compare_bytes, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 88536926b11..112eb862663 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -598,7 +598,12 @@ const S390X_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[ const RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "zvl64b"), */ (128, "v")]; // Always warn on SPARC, as the necessary target features cannot be enabled in Rust at the moment. -const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(128, "vis")*/]; +const SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[/*(64, "vis")*/]; + +const HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = + &[/*(512, "hvx-length64b"),*/ (1024, "hvx-length128b")]; +const MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "msa")]; +const CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "vdspv1")]; impl super::spec::Target { pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] { @@ -620,20 +625,24 @@ impl super::spec::Target { } } - // Returns None if we do not support ABI checks on the given target yet. - pub fn features_for_correct_vector_abi(&self) -> Option<&'static [(u64, &'static str)]> { + pub fn features_for_correct_vector_abi(&self) -> &'static [(u64, &'static str)] { match &*self.arch { - "x86" | "x86_64" => Some(X86_FEATURES_FOR_CORRECT_VECTOR_ABI), - "aarch64" | "arm64ec" => Some(AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI), - "arm" => Some(ARM_FEATURES_FOR_CORRECT_VECTOR_ABI), - "powerpc" | "powerpc64" => Some(POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI), - "loongarch64" => Some(&[]), // on-stack ABI, so we complain about all by-val vectors - "riscv32" | "riscv64" => Some(RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI), - "wasm32" | "wasm64" => Some(WASM_FEATURES_FOR_CORRECT_VECTOR_ABI), - "s390x" => Some(S390X_FEATURES_FOR_CORRECT_VECTOR_ABI), - "sparc" | "sparc64" => Some(SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI), - // FIXME: add support for non-tier2 architectures - _ => None, + "x86" | "x86_64" => X86_FEATURES_FOR_CORRECT_VECTOR_ABI, + "aarch64" | "arm64ec" => AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI, + "arm" => ARM_FEATURES_FOR_CORRECT_VECTOR_ABI, + "powerpc" | "powerpc64" => POWERPC_FEATURES_FOR_CORRECT_VECTOR_ABI, + "loongarch64" => &[], // on-stack ABI, so we complain about all by-val vectors + "riscv32" | "riscv64" => RISCV_FEATURES_FOR_CORRECT_VECTOR_ABI, + "wasm32" | "wasm64" => WASM_FEATURES_FOR_CORRECT_VECTOR_ABI, + "s390x" => S390X_FEATURES_FOR_CORRECT_VECTOR_ABI, + "sparc" | "sparc64" => SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI, + "hexagon" => HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI, + "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI, + "bpf" => &[], // no vector ABI + "csky" => CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI, + // FIXME: for some tier3 targets, we are overly cautious and always give warnings + // when passing args in vector registers. + _ => &[], } } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index b042720933b..e0576c25515 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -116,7 +116,7 @@ use crate::vec::Vec; /// `String`s are always valid UTF-8. If you need a non-UTF-8 string, consider /// [`OsString`]. It is similar, but without the UTF-8 constraint. Because UTF-8 /// is a variable width encoding, `String`s are typically smaller than an array of -/// the same `chars`: +/// the same `char`s: /// /// ``` /// use std::mem; diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 72e34e5faf5..8a986337aa1 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1465,6 +1465,22 @@ pub const unsafe fn assume(b: bool) { } } +/// Hints to the compiler that current code path is cold. +/// +/// Note that, unlike most intrinsics, this is safe to call; +/// it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold +/// any safety invariants. +/// +/// This intrinsic does not have a stable counterpart. +#[unstable(feature = "core_intrinsics", issue = "none")] +#[cfg_attr(not(bootstrap), rustc_intrinsic)] +#[cfg(not(bootstrap))] +#[rustc_nounwind] +#[miri::intrinsic_fallback_is_spec] +#[cold] +pub const fn cold_path() {} + /// Hints to the compiler that branch condition is likely to be true. /// Returns the value passed to it. /// @@ -1480,13 +1496,21 @@ pub const unsafe fn assume(b: bool) { bootstrap, rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION") )] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_intrinsic] #[rustc_nounwind] -#[miri::intrinsic_fallback_is_spec] +#[inline(always)] pub const fn likely(b: bool) -> bool { - b + #[cfg(bootstrap)] + { + b + } + #[cfg(not(bootstrap))] + if b { + true + } else { + cold_path(); + false + } } /// Hints to the compiler that branch condition is likely to be false. @@ -1504,13 +1528,21 @@ pub const fn likely(b: bool) -> bool { bootstrap, rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION") )] -#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] #[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_intrinsic] #[rustc_nounwind] -#[miri::intrinsic_fallback_is_spec] +#[inline(always)] pub const fn unlikely(b: bool) -> bool { - b + #[cfg(bootstrap)] + { + b + } + #[cfg(not(bootstrap))] + if b { + cold_path(); + true + } else { + false + } } /// Returns either `true_val` or `false_val` depending on condition `b` with a @@ -3292,8 +3324,8 @@ pub const unsafe fn ptr_offset_from_unsigned(_ptr: *const T, _base: *const T) /// See documentation of `<*const T>::guaranteed_eq` for details. /// Returns `2` if the result is unknown. -/// Returns `1` if the pointers are guaranteed equal -/// Returns `0` if the pointers are guaranteed inequal +/// Returns `1` if the pointers are guaranteed equal. +/// Returns `0` if the pointers are guaranteed inequal. #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))] #[rustc_intrinsic] #[rustc_nounwind] @@ -3535,7 +3567,6 @@ pub(crate) macro const_eval_select { /// In other words, the following code has *Undefined Behavior*: /// /// ```no_run -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::hint::unreachable_unchecked; @@ -3548,7 +3579,6 @@ pub(crate) macro const_eval_select { /// may panic, or it may not: /// /// ```no_run -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::intrinsics::is_val_statically_known; @@ -3581,7 +3611,6 @@ pub(crate) macro const_eval_select { /// behave identically: /// /// ``` -/// #![feature(is_val_statically_known)] /// #![feature(core_intrinsics)] /// # #![allow(internal_features)] /// use std::intrinsics::is_val_statically_known; @@ -3598,7 +3627,11 @@ pub(crate) macro const_eval_select { /// # _ = foo(&5_i32); /// # _ = bar(&5_i32); /// ``` -#[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")] +#[cfg_attr( + bootstrap, + rustc_const_stable(feature = "const_is_val_statically_known", since = "CURRENT_RUSTC_VERSION") +)] +#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] @@ -4013,9 +4046,9 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us count: usize = count, ) => { let zero_size = count == 0 || size == 0; - ub_checks::is_aligned_and_not_null(src, align, zero_size) - && ub_checks::is_aligned_and_not_null(dst, align, zero_size) - && ub_checks::is_nonoverlapping(src, dst, size, count) + ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) + && ub_checks::maybe_is_nonoverlapping(src, dst, size, count) } ); @@ -4119,8 +4152,8 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { align: usize = align_of::(), zero_size: bool = T::IS_ZST || count == 0, ) => - ub_checks::is_aligned_and_not_null(src, align, zero_size) - && ub_checks::is_aligned_and_not_null(dst, align, zero_size) + ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size) ); copy(src, dst, count) } @@ -4201,7 +4234,7 @@ pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { addr: *const () = dst as *const (), align: usize = align_of::(), zero_size: bool = T::IS_ZST || count == 0, - ) => ub_checks::is_aligned_and_not_null(addr, align, zero_size) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, zero_size) ); write_bytes(dst, val, count) } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6f7ea769420..3b8ac20e527 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -109,6 +109,7 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(const_exact_div))] #![cfg_attr(bootstrap, feature(const_fmt_arguments_new))] +#![cfg_attr(bootstrap, feature(const_ub_checks))] #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(const_align_of_val)] @@ -121,7 +122,6 @@ #![feature(const_heap)] #![feature(const_nonnull_new)] #![feature(const_pin_2)] -#![feature(const_ptr_is_null)] #![feature(const_ptr_sub_ptr)] #![feature(const_raw_ptr_comparison)] #![feature(const_size_of_val)] @@ -132,14 +132,12 @@ #![feature(const_type_id)] #![feature(const_type_name)] #![feature(const_typed_swap)] -#![feature(const_ub_checks)] #![feature(core_intrinsics)] #![feature(coverage_attribute)] #![feature(do_not_recommend)] #![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] -#![feature(is_val_statically_known)] #![feature(lazy_get)] #![feature(link_cfg)] #![feature(non_null_from_ref)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 4d24b102096..318bb8ee4cd 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2242,7 +2242,6 @@ macro_rules! int_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn wrapping_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2808,7 +2807,6 @@ macro_rules! int_impl { without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0a5101884f7..0383c13fa08 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2251,7 +2251,6 @@ macro_rules! uint_impl { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn wrapping_pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; @@ -2791,7 +2790,6 @@ macro_rules! uint_impl { without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - #[rustc_allow_const_fn_unstable(is_val_statically_known)] pub const fn pow(self, mut exp: u32) -> Self { if exp == 0 { return 1; diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 2d7507e2d53..0dbe819acb1 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -29,16 +29,18 @@ impl *const T { /// assert!(!ptr.is_null()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_const_is_null"] #[inline] + #[rustc_allow_const_fn_unstable(const_eval_select)] pub const fn is_null(self) -> bool { // Compare via a cast to a thin pointer, so fat pointers are only // considering their "data" part for null-ness. let ptr = self as *const u8; const_eval_select!( @capture { ptr: *const u8 } -> bool: - if const #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] { + // This use of `const_raw_ptr_comparison` has been explicitly blessed by t-lang. + if const #[rustc_allow_const_fn_unstable(const_raw_ptr_comparison)] { match (ptr).guaranteed_eq(null_mut()) { Some(res) => res, // To remain maximally convervative, we stop execution when we don't @@ -280,7 +282,7 @@ impl *const T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 603e9044217..805edddfe63 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -1103,9 +1103,9 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { count: usize = count, ) => { let zero_size = size == 0 || count == 0; - ub_checks::is_aligned_and_not_null(x, align, zero_size) - && ub_checks::is_aligned_and_not_null(y, align, zero_size) - && ub_checks::is_nonoverlapping(x, y, size, count) + ub_checks::maybe_is_aligned_and_not_null(x, align, zero_size) + && ub_checks::maybe_is_aligned_and_not_null(y, align, zero_size) + && ub_checks::maybe_is_nonoverlapping(x, y, size, count) } ); @@ -1216,7 +1216,7 @@ pub const unsafe fn replace(dst: *mut T, src: T) -> T { addr: *const () = dst as *const (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); mem::replace(&mut *dst, src) } @@ -1369,7 +1369,7 @@ pub const unsafe fn read(src: *const T) -> T { addr: *const () = src as *const (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); crate::intrinsics::read_via_copy(src) } @@ -1573,7 +1573,7 @@ pub const unsafe fn write(dst: *mut T, src: T) { addr: *mut () = dst as *mut (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::write_via_move(dst, src) } @@ -1745,7 +1745,7 @@ pub unsafe fn read_volatile(src: *const T) -> T { addr: *const () = src as *const (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::volatile_load(src) } @@ -1825,7 +1825,7 @@ pub unsafe fn write_volatile(dst: *mut T, src: T) { addr: *mut () = dst as *mut (), align: usize = align_of::(), is_zst: bool = T::IS_ZST, - ) => ub_checks::is_aligned_and_not_null(addr, align, is_zst) + ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst) ); intrinsics::volatile_store(dst, src); } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 344ba46a50e..f0204bd0f77 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -29,7 +29,7 @@ impl *mut T { /// assert!(!ptr.is_null()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[rustc_diagnostic_item = "ptr_is_null"] #[inline] pub const fn is_null(self) -> bool { @@ -271,7 +271,7 @@ impl *mut T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid for a @@ -619,7 +619,7 @@ impl *mut T { /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] - #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] + #[rustc_const_stable(feature = "const_ptr_is_null", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { // SAFETY: the caller must guarantee that `self` is be valid for diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 89840881c4d..319b76899bf 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -132,7 +132,7 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] align: usize = align_of::(), len: usize = len, ) => - ub_checks::is_aligned_and_not_null(data, align, false) + ub_checks::maybe_is_aligned_and_not_null(data, align, false) && ub_checks::is_valid_allocation_size(size, len) ); &*ptr::slice_from_raw_parts(data, len) @@ -186,7 +186,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m align: usize = align_of::(), len: usize = len, ) => - ub_checks::is_aligned_and_not_null(data, align, false) + ub_checks::maybe_is_aligned_and_not_null(data, align, false) && ub_checks::is_valid_allocation_size(size, len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 93b4ad5c1c9..7f2a5424787 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -469,7 +469,7 @@ impl AtomicBool { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -1264,7 +1264,7 @@ impl AtomicPtr { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } @@ -2263,7 +2263,7 @@ macro_rules! atomic_int { /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses #[stable(feature = "atomic_from_ptr", since = "1.75.0")] - #[rustc_const_unstable(feature = "const_atomic_from_ptr", issue = "108652")] + #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { // SAFETY: guaranteed by the caller unsafe { &*ptr.cast() } diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs index 8fcbda141da..3e6110c9c88 100644 --- a/library/core/src/ub_checks.rs +++ b/library/core/src/ub_checks.rs @@ -64,8 +64,6 @@ macro_rules! assert_unsafe_precondition { #[rustc_no_mir_inline] #[inline] #[rustc_nounwind] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))] - #[rustc_allow_const_fn_unstable(const_ptr_is_null, const_ub_checks)] // only for UB checks const fn precondition_check($($name:$ty),*) { if !$e { ::core::panicking::panic_nounwind( @@ -116,12 +114,16 @@ pub(crate) const fn check_language_ub() -> bool { /// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the /// check is anyway not executed in `const`. #[inline] -#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] -pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool { +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn maybe_is_aligned_and_not_null( + ptr: *const (), + align: usize, + is_zst: bool, +) -> bool { // This is just for safety checks so we can const_eval_select. const_eval_select!( @capture { ptr: *const (), align: usize, is_zst: bool } -> bool: - if const #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] { + if const { is_zst || !ptr.is_null() } else { ptr.is_aligned_to(align) && (is_zst || !ptr.is_null()) @@ -141,8 +143,8 @@ pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool { /// Note that in const-eval this function just returns `true` and therefore must /// only be used with `assert_unsafe_precondition!`, similar to `is_aligned_and_not_null`. #[inline] -#[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] -pub(crate) const fn is_nonoverlapping( +#[rustc_allow_const_fn_unstable(const_eval_select)] +pub(crate) const fn maybe_is_nonoverlapping( src: *const (), dst: *const (), size: usize, diff --git a/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile index dcfea77149e..eb39861d8c7 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu-debug/Dockerfile @@ -55,4 +55,4 @@ ENV RUST_CONFIGURE_ARGS \ ENV SCRIPT \ python3 ../x.py --stage 2 build && \ - python3 ../x.py --stage 2 test tests/run-make --test-args clang + python3 ../x.py --stage 2 test tests/run-make diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 6d118ae5784..c1a021e9f8d 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -692,8 +692,6 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) { const quadcolon = /::\s*::/.exec(path); if (path.startsWith("::")) { throw ["Paths cannot start with ", "::"]; - } else if (path.endsWith("::")) { - throw ["Paths cannot end with ", "::"]; } else if (quadcolon !== null) { throw ["Unexpected ", quadcolon[0]]; } @@ -3974,18 +3972,19 @@ class DocSearch { if (parsedQuery.foundElems === 1 && !parsedQuery.hasReturnArrow) { const elem = parsedQuery.elems[0]; - for (const id of this.nameTrie.search(elem.normalizedPathLast, this.tailTable)) { + // use arrow functions to preserve `this`. + const handleNameSearch = id => { const row = this.searchIndex[id]; if (!typePassesFilter(elem.typeFilter, row.ty) || (filterCrates !== null && row.crate !== filterCrates)) { - continue; + return; } let pathDist = 0; if (elem.fullPath.length > 1) { pathDist = checkPath(elem.pathWithoutLast, row); if (pathDist === null) { - continue; + return; } } @@ -4008,9 +4007,20 @@ class DocSearch { maxEditDistance, ); } + }; + if (elem.normalizedPathLast !== "") { + const last = elem.normalizedPathLast; + for (const id of this.nameTrie.search(last, this.tailTable)) { + handleNameSearch(id); + } } const length = this.searchIndex.length; + for (let i = 0, nSearchIndex = length; i < nSearchIndex; ++i) { + // queries that end in :: bypass the trie + if (elem.normalizedPathLast === "") { + handleNameSearch(i); + } const row = this.searchIndex[i]; if (filterCrates !== null && row.crate !== filterCrates) { continue; diff --git a/src/tools/cargo b/src/tools/cargo index 4a2d8dc6364..69e595908e2 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 4a2d8dc636445b276288543882e076f254b3ae95 +Subproject commit 69e595908e2c420e7f0d1be34e6c5b984c8cfb84 diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 6c84893627a..35108ef7621 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3bc6916f4ca50bb83b211d9013dac38e84618750 +3fb7e441aecc3c054d71eb4d752d06e7776e8888 diff --git a/src/tools/miri/tests/pass/shims/time-with-isolation.stdout b/src/tools/miri/tests/pass/shims/time-with-isolation.stdout index 2d7fb5f4a61..6058735f005 100644 --- a/src/tools/miri/tests/pass/shims/time-with-isolation.stdout +++ b/src/tools/miri/tests/pass/shims/time-with-isolation.stdout @@ -1,2 +1,2 @@ -The loop took around 1250ms +The loop took around 1350ms (It's fine for this number to change when you `--bless` this test.) diff --git a/src/tools/run-make-support/src/external_deps/c_build.rs b/src/tools/run-make-support/src/external_deps/c_build.rs index f8d1666adda..9dd30713f95 100644 --- a/src/tools/run-make-support/src/external_deps/c_build.rs +++ b/src/tools/run-make-support/src/external_deps/c_build.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use crate::artifact_names::{dynamic_lib_name, static_lib_name}; -use crate::external_deps::cc::{cc, cxx}; +use crate::external_deps::c_cxx_compiler::{cc, cxx}; use crate::external_deps::llvm::llvm_ar; use crate::path_helpers::path; use crate::targets::{is_darwin, is_msvc, is_windows}; diff --git a/src/tools/run-make-support/src/external_deps/cc.rs b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/cc.rs similarity index 55% rename from src/tools/run-make-support/src/external_deps/cc.rs rename to src/tools/run-make-support/src/external_deps/c_cxx_compiler/cc.rs index 011ad89e170..becb91ae989 100644 --- a/src/tools/run-make-support/src/external_deps/cc.rs +++ b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/cc.rs @@ -1,7 +1,7 @@ use std::path::Path; use crate::command::Command; -use crate::{env_var, is_msvc, is_windows, uname}; +use crate::{env_var, is_msvc}; /// Construct a new platform-specific C compiler invocation. /// @@ -127,99 +127,3 @@ impl Cc { self } } - -/// `EXTRACFLAGS` -pub fn extra_c_flags() -> Vec<&'static str> { - // Adapted from tools.mk (trimmed): - // - // ```makefile - // ifdef IS_WINDOWS - // ifdef IS_MSVC - // EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib bcrypt.lib ntdll.lib synchronization.lib - // else - // EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt -lntdll -lsynchronization - // endif - // else - // ifeq ($(UNAME),Darwin) - // EXTRACFLAGS := -lresolv - // else - // ifeq ($(UNAME),FreeBSD) - // EXTRACFLAGS := -lm -lpthread -lgcc_s - // else - // ifeq ($(UNAME),SunOS) - // EXTRACFLAGS := -lm -lpthread -lposix4 -lsocket -lresolv - // else - // ifeq ($(UNAME),OpenBSD) - // EXTRACFLAGS := -lm -lpthread -lc++abi - // else - // EXTRACFLAGS := -lm -lrt -ldl -lpthread - // endif - // endif - // endif - // endif - // endif - // ``` - - if is_windows() { - if is_msvc() { - vec![ - "ws2_32.lib", - "userenv.lib", - "advapi32.lib", - "bcrypt.lib", - "ntdll.lib", - "synchronization.lib", - ] - } else { - vec!["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"] - } - } else { - match uname() { - n if n.contains("Darwin") => vec!["-lresolv"], - n if n.contains("FreeBSD") => vec!["-lm", "-lpthread", "-lgcc_s"], - n if n.contains("SunOS") => { - vec!["-lm", "-lpthread", "-lposix4", "-lsocket", "-lresolv"] - } - n if n.contains("OpenBSD") => vec!["-lm", "-lpthread", "-lc++abi"], - _ => vec!["-lm", "-lrt", "-ldl", "-lpthread"], - } - } -} - -/// `EXTRACXXFLAGS` -pub fn extra_cxx_flags() -> Vec<&'static str> { - // Adapted from tools.mk (trimmed): - // - // ```makefile - // ifdef IS_WINDOWS - // ifdef IS_MSVC - // else - // EXTRACXXFLAGS := -lstdc++ - // endif - // else - // ifeq ($(UNAME),Darwin) - // EXTRACXXFLAGS := -lc++ - // else - // ifeq ($(UNAME),FreeBSD) - // else - // ifeq ($(UNAME),SunOS) - // else - // ifeq ($(UNAME),OpenBSD) - // else - // EXTRACXXFLAGS := -lstdc++ - // endif - // endif - // endif - // endif - // endif - // ``` - if is_windows() { - if is_msvc() { vec![] } else { vec!["-lstdc++"] } - } else { - match &uname()[..] { - "Darwin" => vec!["-lc++"], - "FreeBSD" | "SunOS" | "OpenBSD" => vec![], - _ => vec!["-lstdc++"], - } - } -} diff --git a/src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs new file mode 100644 index 00000000000..49210d75e06 --- /dev/null +++ b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs @@ -0,0 +1,97 @@ +use crate::{is_msvc, is_windows, uname}; + +/// `EXTRACFLAGS` +pub fn extra_c_flags() -> Vec<&'static str> { + // Adapted from tools.mk (trimmed): + // + // ```makefile + // ifdef IS_WINDOWS + // ifdef IS_MSVC + // EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib bcrypt.lib ntdll.lib synchronization.lib + // else + // EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt -lntdll -lsynchronization + // endif + // else + // ifeq ($(UNAME),Darwin) + // EXTRACFLAGS := -lresolv + // else + // ifeq ($(UNAME),FreeBSD) + // EXTRACFLAGS := -lm -lpthread -lgcc_s + // else + // ifeq ($(UNAME),SunOS) + // EXTRACFLAGS := -lm -lpthread -lposix4 -lsocket -lresolv + // else + // ifeq ($(UNAME),OpenBSD) + // EXTRACFLAGS := -lm -lpthread -lc++abi + // else + // EXTRACFLAGS := -lm -lrt -ldl -lpthread + // endif + // endif + // endif + // endif + // endif + // ``` + + if is_windows() { + if is_msvc() { + vec![ + "ws2_32.lib", + "userenv.lib", + "advapi32.lib", + "bcrypt.lib", + "ntdll.lib", + "synchronization.lib", + ] + } else { + vec!["-lws2_32", "-luserenv", "-lbcrypt", "-lntdll", "-lsynchronization"] + } + } else { + match uname() { + n if n.contains("Darwin") => vec!["-lresolv"], + n if n.contains("FreeBSD") => vec!["-lm", "-lpthread", "-lgcc_s"], + n if n.contains("SunOS") => { + vec!["-lm", "-lpthread", "-lposix4", "-lsocket", "-lresolv"] + } + n if n.contains("OpenBSD") => vec!["-lm", "-lpthread", "-lc++abi"], + _ => vec!["-lm", "-lrt", "-ldl", "-lpthread"], + } + } +} + +/// `EXTRACXXFLAGS` +pub fn extra_cxx_flags() -> Vec<&'static str> { + // Adapted from tools.mk (trimmed): + // + // ```makefile + // ifdef IS_WINDOWS + // ifdef IS_MSVC + // else + // EXTRACXXFLAGS := -lstdc++ + // endif + // else + // ifeq ($(UNAME),Darwin) + // EXTRACXXFLAGS := -lc++ + // else + // ifeq ($(UNAME),FreeBSD) + // else + // ifeq ($(UNAME),SunOS) + // else + // ifeq ($(UNAME),OpenBSD) + // else + // EXTRACXXFLAGS := -lstdc++ + // endif + // endif + // endif + // endif + // endif + // ``` + if is_windows() { + if is_msvc() { vec![] } else { vec!["-lstdc++"] } + } else { + match &uname()[..] { + "Darwin" => vec!["-lc++"], + "FreeBSD" | "SunOS" | "OpenBSD" => vec![], + _ => vec!["-lstdc++"], + } + } +} diff --git a/src/tools/run-make-support/src/external_deps/c_cxx_compiler/gcc.rs b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/gcc.rs new file mode 100644 index 00000000000..e02c4f97255 --- /dev/null +++ b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/gcc.rs @@ -0,0 +1,66 @@ +use std::path::Path; + +use crate::command::Command; + +/// Construct a gcc invocation. +/// +/// WARNING: This assumes *a* `gcc` exists in the environment and is suitable for use. +#[track_caller] +pub fn gcc() -> Gcc { + Gcc::new() +} + +/// A specific `gcc`. +#[derive(Debug)] +#[must_use] +pub struct Gcc { + cmd: Command, +} + +crate::macros::impl_common_helpers!(Gcc); + +impl Gcc { + /// Construct a `gcc` invocation. This assumes that *a* suitable `gcc` is available in the + /// environment. + /// + /// Note that this does **not** prepopulate the `gcc` invocation with `CC_DEFAULT_FLAGS`. + #[track_caller] + pub fn new() -> Self { + let cmd = Command::new("gcc"); + Self { cmd } + } + + /// Specify path of the input file. + pub fn input>(&mut self, path: P) -> &mut Self { + self.cmd.arg(path.as_ref()); + self + } + + /// Adds directories to the list that the linker searches for libraries. + /// Equivalent to `-L`. + pub fn library_search_path>(&mut self, path: P) -> &mut Self { + self.cmd.arg("-L"); + self.cmd.arg(path.as_ref()); + self + } + + /// Specify `-o`. + pub fn out_exe(&mut self, name: &str) -> &mut Self { + self.cmd.arg("-o"); + self.cmd.arg(name); + self + } + + /// Specify path of the output binary. + pub fn output>(&mut self, path: P) -> &mut Self { + self.cmd.arg("-o"); + self.cmd.arg(path.as_ref()); + self + } + + /// Optimize the output at `-O3`. + pub fn optimize(&mut self) -> &mut Self { + self.cmd.arg("-O3"); + self + } +} diff --git a/src/tools/run-make-support/src/external_deps/c_cxx_compiler/mod.rs b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/mod.rs new file mode 100644 index 00000000000..9aaefd8aa47 --- /dev/null +++ b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/mod.rs @@ -0,0 +1,7 @@ +mod cc; +mod extras; +mod gcc; + +pub use cc::*; +pub use extras::*; +pub use gcc::*; diff --git a/src/tools/run-make-support/src/external_deps/mod.rs b/src/tools/run-make-support/src/external_deps/mod.rs index 80c34a9070f..129b06761ef 100644 --- a/src/tools/run-make-support/src/external_deps/mod.rs +++ b/src/tools/run-make-support/src/external_deps/mod.rs @@ -2,8 +2,8 @@ //! such as `cc` or `python`. pub mod c_build; +pub mod c_cxx_compiler; pub mod cargo; -pub mod cc; pub mod clang; pub mod htmldocck; pub mod llvm; diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 6cf0aedfe9f..819bbc161e6 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -46,10 +46,10 @@ pub use wasmparser; // tidy-alphabetical-end // Re-exports of external dependencies. -pub use external_deps::{c_build, cc, clang, htmldocck, llvm, python, rustc, rustdoc}; +pub use external_deps::{c_build, c_cxx_compiler, clang, htmldocck, llvm, python, rustc, rustdoc}; // These rely on external dependencies. -pub use cc::{cc, cxx, extra_c_flags, extra_cxx_flags, Cc}; +pub use c_cxx_compiler::{Cc, Gcc, cc, cxx, extra_c_flags, extra_cxx_flags, gcc}; pub use c_build::{ build_native_dynamic_lib, build_native_static_lib, build_native_static_lib_cxx, build_native_static_lib_optimized, diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 327a547b295..68c481bda6e 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -3449,21 +3449,14 @@ impl Rewrite for ast::ForeignItem { ref generics, ref body, } = **fn_kind; - if let Some(ref body) = body { + if body.is_some() { let mut visitor = FmtVisitor::from_context(context); visitor.block_indent = shape.indent; visitor.last_pos = self.span.lo(); let inner_attrs = inner_attributes(&self.attrs); let fn_ctxt = visit::FnCtxt::Foreign; visitor.visit_fn( - visit::FnKind::Fn( - fn_ctxt, - self.ident, - sig, - &self.vis, - generics, - Some(body), - ), + visit::FnKind::Fn(fn_ctxt, &self.ident, sig, &self.vis, generics, body), &sig.decl, self.span, defaultness, diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 8102fe7ad8f..9b116b620b7 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -390,7 +390,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { block = b; self.rewrite_fn_before_block( indent, - ident, + *ident, &FnSig::from_fn_kind(&fk, fd, defaultness), mk_sp(s.lo(), b.span.lo()), ) @@ -540,21 +540,14 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ref generics, ref body, } = **fn_kind; - if let Some(ref body) = body { + if body.is_some() { let inner_attrs = inner_attributes(&item.attrs); let fn_ctxt = match sig.header.ext { ast::Extern::None => visit::FnCtxt::Free, _ => visit::FnCtxt::Foreign, }; self.visit_fn( - visit::FnKind::Fn( - fn_ctxt, - item.ident, - sig, - &item.vis, - generics, - Some(body), - ), + visit::FnKind::Fn(fn_ctxt, &item.ident, sig, &item.vis, generics, body), &sig.decl, item.span, defaultness, @@ -648,11 +641,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ref generics, ref body, } = **fn_kind; - if let Some(ref body) = body { + if body.is_some() { let inner_attrs = inner_attributes(&ai.attrs); let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt); self.visit_fn( - visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, generics, Some(body)), + visit::FnKind::Fn(fn_ctxt, &ai.ident, sig, &ai.vis, generics, body), &sig.decl, ai.span, defaultness, diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs index 751d678e581..a66ccd37070 100644 --- a/src/tools/tidy/src/target_specific_tests.rs +++ b/src/tools/tidy/src/target_specific_tests.rs @@ -10,26 +10,6 @@ use crate::walk::filter_not_rust; const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:"; const COMPILE_FLAGS_HEADER: &str = "compile-flags:"; -const KNOWN_LLVM_COMPONENTS: &[&str] = &[ - "aarch64", - "arm", - "avr", - "bpf", - "csky", - "hexagon", - "loongarch", - "m68k", - "mips", - "msp430", - "nvptx", - "powerpc", - "riscv", - "sparc", - "systemz", - "webassembly", - "x86", -]; - #[derive(Default, Debug)] struct RevisionInfo<'a> { target_arch: Option<&'a str>, @@ -94,20 +74,6 @@ pub fn check(tests_path: &Path, bad: &mut bool) { // gathered. } } - if let Some(llvm_components) = llvm_components { - for component in llvm_components { - // Ensure the given component even exists. - // This is somewhat redundant with COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS, - // but helps detect such problems earlier (PR CI rather than bors CI). - if !KNOWN_LLVM_COMPONENTS.contains(component) { - eprintln!( - "{}: revision {} specifies unknown LLVM component `{}`", - file, rev, component - ); - *bad = true; - } - } - } } }); } diff --git a/tests/codegen/checked_math.rs b/tests/codegen/checked_math.rs index 63f5c3d34f7..c612ddccdaa 100644 --- a/tests/codegen/checked_math.rs +++ b/tests/codegen/checked_math.rs @@ -90,7 +90,7 @@ pub fn checked_shr_signed(a: i32, b: u32) -> Option { #[no_mangle] pub fn checked_add_one_unwrap_unsigned(x: u32) -> u32 { // CHECK: %[[IS_MAX:.+]] = icmp eq i32 %x, -1 - // CHECK: br i1 %[[IS_MAX]], label %[[NONE_BB:.+]], label %[[SOME_BB:.+]] + // CHECK: br i1 %[[IS_MAX]], label %[[NONE_BB:.+]], label %[[SOME_BB:.+]], // CHECK: [[SOME_BB]]: // CHECK: %[[R:.+]] = add nuw i32 %x, 1 // CHECK: ret i32 %[[R]] diff --git a/tests/codegen/intrinsics/cold_path.rs b/tests/codegen/intrinsics/cold_path.rs new file mode 100644 index 00000000000..24ee84e07bf --- /dev/null +++ b/tests/codegen/intrinsics/cold_path.rs @@ -0,0 +1,13 @@ +//@ compile-flags: -O +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +use std::intrinsics::cold_path; + +#[no_mangle] +pub fn test_cold_path(x: bool) { + cold_path(); +} + +// CHECK-LABEL: @test_cold_path( +// CHECK-NOT: cold_path diff --git a/tests/codegen/intrinsics/likely.rs b/tests/codegen/intrinsics/likely.rs index 9dc31d21045..e318390db20 100644 --- a/tests/codegen/intrinsics/likely.rs +++ b/tests/codegen/intrinsics/likely.rs @@ -1,22 +1,35 @@ -//@ compile-flags: -C no-prepopulate-passes -Copt-level=1 - +//@ compile-flags: -O #![crate_type = "lib"] #![feature(core_intrinsics)] -use std::intrinsics::{likely, unlikely}; +use std::intrinsics::likely; +#[inline(never)] #[no_mangle] -pub fn check_likely(x: i32, y: i32) -> Option { - unsafe { - // CHECK: call i1 @llvm.expect.i1(i1 %{{.*}}, i1 true) - if likely(x == y) { None } else { Some(x + y) } - } +pub fn path_a() { + println!("path a"); +} + +#[inline(never)] +#[no_mangle] +pub fn path_b() { + println!("path b"); } #[no_mangle] -pub fn check_unlikely(x: i32, y: i32) -> Option { - unsafe { - // CHECK: call i1 @llvm.expect.i1(i1 %{{.*}}, i1 false) - if unlikely(x == y) { None } else { Some(x + y) } +pub fn test_likely(x: bool) { + if likely(x) { + path_a(); + } else { + path_b(); } } + +// CHECK-LABEL: @test_likely( +// CHECK: br i1 %x, label %bb2, label %bb3, !prof ![[NUM:[0-9]+]] +// CHECK: bb3: +// CHECK-NOT: cold_path +// CHECK: path_b +// CHECK: bb2: +// CHECK: path_a +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} diff --git a/tests/codegen/intrinsics/likely_assert.rs b/tests/codegen/intrinsics/likely_assert.rs new file mode 100644 index 00000000000..0ddbd6206ae --- /dev/null +++ b/tests/codegen/intrinsics/likely_assert.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -O +#![crate_type = "lib"] + +#[no_mangle] +pub fn test_assert(x: bool) { + assert!(x); +} + +// check that assert! emits branch weights + +// CHECK-LABEL: @test_assert( +// CHECK: br i1 %x, label %bb2, label %bb1, !prof ![[NUM:[0-9]+]] +// CHECK: bb1: +// CHECK: panic +// CHECK: bb2: +// CHECK: ret void +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} diff --git a/tests/codegen/intrinsics/unlikely.rs b/tests/codegen/intrinsics/unlikely.rs new file mode 100644 index 00000000000..2d776031a52 --- /dev/null +++ b/tests/codegen/intrinsics/unlikely.rs @@ -0,0 +1,35 @@ +//@ compile-flags: -O +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +use std::intrinsics::unlikely; + +#[inline(never)] +#[no_mangle] +pub fn path_a() { + println!("path a"); +} + +#[inline(never)] +#[no_mangle] +pub fn path_b() { + println!("path b"); +} + +#[no_mangle] +pub fn test_unlikely(x: bool) { + if unlikely(x) { + path_a(); + } else { + path_b(); + } +} + +// CHECK-LABEL: @test_unlikely( +// CHECK: br i1 %x, label %bb2, label %bb4, !prof ![[NUM:[0-9]+]] +// CHECK: bb4: +// CHECK: path_b +// CHECK: bb2: +// CHECK-NOT: cold_path +// CHECK: path_a +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 1, i32 2000} diff --git a/tests/crashes/123077-2.rs b/tests/crashes/123077-2.rs deleted file mode 100644 index e086e330337..00000000000 --- a/tests/crashes/123077-2.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #123077 -//@ only-x86_64 -use std::arch::x86_64::{__m128, _mm_blend_ps}; - -pub fn sse41_blend_noinline( ) -> __m128 { - let f = { |x, y| unsafe { - _mm_blend_ps(x, y, { |x, y| unsafe }) - }}; - f(x, y) -} - -pub fn main() {} diff --git a/tests/crashes/129150.rs b/tests/crashes/129150.rs deleted file mode 100644 index 9f8c2ba1739..00000000000 --- a/tests/crashes/129150.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: rust-lang/rust#129150 -//@ only-x86_64 -use std::arch::x86_64::_mm_blend_ps; - -pub fn main() { - _mm_blend_ps(1, 2, &const {} ); -} diff --git a/tests/crashes/130687.rs b/tests/crashes/130687.rs deleted file mode 100644 index 361be0905df..00000000000 --- a/tests/crashes/130687.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #130687 -//@ only-x86_64 -pub struct Data([u8; usize::MAX >> 16]); -const _: &'static Data = &Data([0; usize::MAX >> 16]); diff --git a/tests/crashes/131535.rs b/tests/crashes/131535.rs deleted file mode 100644 index 47ccdf87f2d..00000000000 --- a/tests/crashes/131535.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #131535 -#![feature(non_lifetime_binders)] -trait v0<> {} -fn kind :(v0<'_, > impl for v0<'_, v2 = impl v0 + '_>) {} diff --git a/tests/crashes/131637.rs b/tests/crashes/131637.rs deleted file mode 100644 index 7d328384a74..00000000000 --- a/tests/crashes/131637.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #121637 -#![feature(non_lifetime_binders)] -trait Trait { - type Type; - - fn method(&self) -> impl for Trait>; -} diff --git a/tests/crashes/132530.rs b/tests/crashes/132530.rs deleted file mode 100644 index b43da62bfc1..00000000000 --- a/tests/crashes/132530.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #132530 - -#![feature(non_lifetime_binders)] - -trait Trait<'a, A> { - type Assoc<'a> = i32; -} - -fn a() -> impl for Trait> {} diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs index 9d232578979..9a0fd01d7e2 100644 --- a/tests/debuginfo/numeric-types.rs +++ b/tests/debuginfo/numeric-types.rs @@ -2,6 +2,14 @@ //@ ignore-windows-gnu: #128981 +// Note: u128 visualization was not supported in 10.0.22621.3233 but was fixed in 10.0.26100.2161. + +// FIXME(#133107): this is temporarily marked as `only-64bit` because of course 32-bit msvc has +// a different integer width and thus underlying integer type display. Only marked as such to +// unblock the tree. +//@ only-64bit +//@ min-cdb-version: 10.0.26100.2161 + // Tests the visualizations for `NonZero`, `Wrapping` and // `Atomic{Bool,I8,I16,I32,I64,Isize,U8,U16,U32,U64,Usize}` located in `libcore.natvis`. @@ -48,8 +56,8 @@ // cdb-check:nz_u64 : 0x64 [Type: core::num::nonzero::NonZero] // cdb-check: [] [Type: core::num::nonzero::NonZero] -// 128-bit integers don't seem to work in CDB // cdb-command: dx nz_u128 +// cdb-check:nz_u128 : 111 [Type: core::num::nonzero::NonZero] // cdb-check: [] [Type: core::num::nonzero::NonZero] // cdb-command: dx nz_usize @@ -58,101 +66,99 @@ // cdb-command: dx w_i8 // cdb-check:w_i8 : 10 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 10 [Type: char] // cdb-command: dx w_i16 // cdb-check:w_i16 : 20 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 20 [Type: short] // cdb-command: dx w_i32 // cdb-check:w_i32 : 30 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 30 [Type: int] // cdb-command: dx w_i64 // cdb-check:w_i64 : 40 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 40 [Type: __int64] -// 128-bit integers don't seem to work in CDB // cdb-command: dx w_i128 -// cdb-check:w_i128 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check:w_i128 : 50 [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 50 [Type: i128] // cdb-command: dx w_isize // cdb-check:w_isize : 60 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 60 [Type: __int64] // cdb-command: dx w_u8 // cdb-check:w_u8 : 0x46 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x46 [Type: unsigned char] // cdb-command: dx w_u16 // cdb-check:w_u16 : 0x50 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x50 [Type: unsigned short] // cdb-command: dx w_u32 // cdb-check:w_u32 : 0x5a [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x5a [Type: unsigned int] // cdb-command: dx w_u64 // cdb-check:w_u64 : 0x64 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x64 [Type: unsigned __int64] -// 128-bit integers don't seem to work in CDB // cdb-command: dx w_u128 -// cdb-check:w_u128 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check:w_u128 : 110 [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 110 [Type: u128] // cdb-command: dx w_usize // cdb-check:w_usize : 0x78 [Type: core::num::wrapping::Wrapping] -// cdb-check: [] [Type: core::num::wrapping::Wrapping] +// cdb-check: [+0x000] __0 : 0x78 [Type: unsigned __int64] // cdb-command: dx a_bool_t // cdb-check:a_bool_t : true [Type: core::sync::atomic::AtomicBool] -// cdb-check: [] [Type: core::sync::atomic::AtomicBool] +// cdb-check: [+0x000] v : 0x1 [Type: core::cell::UnsafeCell] // cdb-command: dx a_bool_f // cdb-check:a_bool_f : false [Type: core::sync::atomic::AtomicBool] -// cdb-check: [] [Type: core::sync::atomic::AtomicBool] +// cdb-check: [+0x000] v : 0x0 [Type: core::cell::UnsafeCell] // cdb-command: dx a_i8 // cdb-check:a_i8 : 2 [Type: core::sync::atomic::AtomicI8] -// cdb-check: [] [Type: core::sync::atomic::AtomicI8] +// cdb-check: [+0x000] v : 2 [Type: core::cell::UnsafeCell] // cdb-command: dx a_i16 // cdb-check:a_i16 : 4 [Type: core::sync::atomic::AtomicI16] -// cdb-check: [] [Type: core::sync::atomic::AtomicI16] +// cdb-check: [+0x000] v : 4 [Type: core::cell::UnsafeCell] // cdb-command: dx a_i32 // cdb-check:a_i32 : 8 [Type: core::sync::atomic::AtomicI32] -// cdb-check: [] [Type: core::sync::atomic::AtomicI32] +// cdb-check: [+0x000] v : 8 [Type: core::cell::UnsafeCell] // cdb-command: dx a_i64 // cdb-check:a_i64 : 16 [Type: core::sync::atomic::AtomicI64] -// cdb-check: [] [Type: core::sync::atomic::AtomicI64] +// cdb-check: [+0x000] v : 16 [Type: core::cell::UnsafeCell] // cdb-command: dx a_isize // cdb-check:a_isize : 32 [Type: core::sync::atomic::AtomicIsize] -// cdb-check: [] [Type: core::sync::atomic::AtomicIsize] +// cdb-check: [+0x000] v : 32 [Type: core::cell::UnsafeCell] // cdb-command: dx a_u8 // cdb-check:a_u8 : 0x40 [Type: core::sync::atomic::AtomicU8] -// cdb-check: [] [Type: core::sync::atomic::AtomicU8] +// cdb-check: [+0x000] v : 0x40 [Type: core::cell::UnsafeCell] // cdb-command: dx a_u16 // cdb-check:a_u16 : 0x80 [Type: core::sync::atomic::AtomicU16] -// cdb-check: [] [Type: core::sync::atomic::AtomicU16] +// cdb-check: [+0x000] v : 0x80 [Type: core::cell::UnsafeCell] // cdb-command: dx a_u32 // cdb-check:a_u32 : 0x100 [Type: core::sync::atomic::AtomicU32] -// cdb-check: [] [Type: core::sync::atomic::AtomicU32] +// cdb-check: [+0x000] v : 0x100 [Type: core::cell::UnsafeCell] // cdb-command: dx a_u64 // cdb-check:a_u64 : 0x200 [Type: core::sync::atomic::AtomicU64] -// cdb-check: [] [Type: core::sync::atomic::AtomicU64] +// cdb-check: [+0x000] v : 0x200 [Type: core::cell::UnsafeCell] // cdb-command: dx a_usize // cdb-check:a_usize : 0x400 [Type: core::sync::atomic::AtomicUsize] -// cdb-check: [] [Type: core::sync::atomic::AtomicUsize] +// cdb-check: [+0x000] v : 0x400 [Type: core::cell::UnsafeCell] // === GDB TESTS =================================================================================== diff --git a/tests/debuginfo/range-types.rs b/tests/debuginfo/range-types.rs index 8c18fd9addd..068a55a5767 100644 --- a/tests/debuginfo/range-types.rs +++ b/tests/debuginfo/range-types.rs @@ -1,7 +1,10 @@ // Testing the display of range types in cdb. -// cdb-only -//@ min-cdb-version: 10.0.18317.1001 +//@ only-cdb + +// FIXME(jieyouxu): triple check in CI if the directive actually works +//@ min-cdb-version: 10.0.26100.2161 + //@ compile-flags:-g // === CDB TESTS ================================================================================== @@ -10,23 +13,26 @@ // cdb-command: dx r1,d // cdb-check:r1,d : (3..5) [Type: core::ops::range::Range] -// cdb-check: [] [Type: core::ops::range::Range] +// cdb-check: [+0x000] start : 3 [Type: int] +// cdb-check: [+0x004] end : 5 [Type: int] // cdb-command: dx r2,d // cdb-check:r2,d : (2..) [Type: core::ops::range::RangeFrom] -// cdb-check: [] [Type: core::ops::range::RangeFrom] +// cdb-check: [+0x000] start : 2 [Type: int] // cdb-command: dx r3,d // cdb-check:r3,d : (1..=4) [Type: core::ops::range::RangeInclusive] -// cdb-check: [] [Type: core::ops::range::RangeInclusive] +// cdb-check: [+0x000] start : 1 [Type: int] +// cdb-check: [+0x004] end : 4 [Type: int] +// cdb-check: [+0x008] exhausted : false [Type: bool] // cdb-command: dx r4,d // cdb-check:r4,d : (..10) [Type: core::ops::range::RangeTo] -// cdb-check: [] [Type: core::ops::range::RangeTo] +// cdb-check: [+0x000] end : 10 [Type: int] // cdb-command: dx r5,d // cdb-check:r5,d : (..=3) [Type: core::ops::range::RangeToInclusive] -// cdb-check: [] [Type: core::ops::range::RangeToInclusive] +// cdb-check: [+0x000] end : 3 [Type: int] // cdb-command: dx r6,d // cdb-check:r6,d [Type: core::ops::range::RangeFull] diff --git a/tests/debuginfo/unit-type.rs b/tests/debuginfo/unit-type.rs index 42c0ff11f71..0ffa2fe490a 100644 --- a/tests/debuginfo/unit-type.rs +++ b/tests/debuginfo/unit-type.rs @@ -1,5 +1,8 @@ //@ compile-flags:-g +// FIXME(jieyouxu): triple check if this works in CI +//@ min-cdb-version: 10.0.26100.2161 + // === GDB TESTS =================================================================================== // gdb-command: run @@ -26,18 +29,18 @@ // cdb-check: Breakpoint 0 hit // cdb-command: dx _ref -// cdb-check: _ref : 0x[...] : () [Type: tuple$<> *] +// cdb-check: _ref : 0x[...] [Type: tuple$<> *] // cdb-command: dx _ptr -// cdb-check: _ptr : 0x[...] : () [Type: tuple$<> *] +// cdb-check: _ptr : 0x[...] [Type: tuple$<> *] // cdb-command: dx _local -// cdb-check: _local : () [Type: tuple$<>] +// cdb-check: _local [Type: tuple$<>] // cdb-command: dx _field,d // cdb-check: _field,d [Type: unit_type::_TypeContainingUnitField] // cdb-check: [+0x[...]] _a : 123 [Type: unsigned int] -// cdb-check: [+0x[...]] _unit : () [Type: tuple$<>] +// cdb-check: [+0x[...]] _unit [Type: tuple$<>] // cdb-check: [+0x[...]] _b : 456 [Type: unsigned __int64] // Check that we can cast "void pointers" to their actual type in the debugger diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir index 935e67fc3c0..cff5b4c7243 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir @@ -13,7 +13,9 @@ fn step_forward(_1: u16, _2: usize) -> u16 { scope 6 (inlined core::num::::checked_add) { let mut _5: (u16, bool); let mut _6: bool; - let mut _7: bool; + scope 7 (inlined unlikely) { + let _7: (); + } } } scope 5 (inlined convert::num::ptr_try_from_impls:: for u16>::try_from) { @@ -21,11 +23,11 @@ fn step_forward(_1: u16, _2: usize) -> u16 { let mut _4: u16; } } - scope 7 (inlined Option::::is_none) { - scope 8 (inlined Option::::is_some) { + scope 8 (inlined Option::::is_none) { + scope 9 (inlined Option::::is_some) { } } - scope 9 (inlined core::num::::wrapping_add) { + scope 10 (inlined core::num::::wrapping_add) { } } @@ -39,29 +41,26 @@ fn step_forward(_1: u16, _2: usize) -> u16 { bb1: { _4 = copy _2 as u16 (IntToInt); StorageDead(_3); - StorageLive(_7); StorageLive(_6); StorageLive(_5); _5 = AddWithOverflow(copy _1, copy _4); _6 = copy (_5.1: bool); - _7 = unlikely(move _6) -> [return: bb2, unwind unreachable]; + switchInt(copy _6) -> [0: bb2, otherwise: bb3]; } bb2: { - switchInt(move _7) -> [0: bb3, otherwise: bb4]; + StorageDead(_5); + StorageDead(_6); + goto -> bb7; } bb3: { - StorageDead(_5); - StorageDead(_6); - StorageDead(_7); - goto -> bb7; + _7 = cold_path() -> [return: bb4, unwind unreachable]; } bb4: { StorageDead(_5); StorageDead(_6); - StorageDead(_7); goto -> bb6; } diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir index bf1ffd1ef32..6e0242a220d 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir @@ -13,7 +13,9 @@ fn step_forward(_1: u16, _2: usize) -> u16 { scope 6 (inlined core::num::::checked_add) { let mut _5: (u16, bool); let mut _6: bool; - let mut _7: bool; + scope 7 (inlined unlikely) { + let _7: (); + } } } scope 5 (inlined convert::num::ptr_try_from_impls:: for u16>::try_from) { @@ -21,11 +23,11 @@ fn step_forward(_1: u16, _2: usize) -> u16 { let mut _4: u16; } } - scope 7 (inlined Option::::is_none) { - scope 8 (inlined Option::::is_some) { + scope 8 (inlined Option::::is_none) { + scope 9 (inlined Option::::is_some) { } } - scope 9 (inlined core::num::::wrapping_add) { + scope 10 (inlined core::num::::wrapping_add) { } } @@ -39,29 +41,26 @@ fn step_forward(_1: u16, _2: usize) -> u16 { bb1: { _4 = copy _2 as u16 (IntToInt); StorageDead(_3); - StorageLive(_7); StorageLive(_6); StorageLive(_5); _5 = AddWithOverflow(copy _1, copy _4); _6 = copy (_5.1: bool); - _7 = unlikely(move _6) -> [return: bb2, unwind unreachable]; + switchInt(copy _6) -> [0: bb2, otherwise: bb3]; } bb2: { - switchInt(move _7) -> [0: bb3, otherwise: bb4]; + StorageDead(_5); + StorageDead(_6); + goto -> bb7; } bb3: { - StorageDead(_5); - StorageDead(_6); - StorageDead(_7); - goto -> bb7; + _7 = cold_path() -> [return: bb4, unwind unreachable]; } bb4: { StorageDead(_5); StorageDead(_6); - StorageDead(_7); goto -> bb6; } diff --git a/tests/run-make/mte-ffi/rmake.rs b/tests/run-make/mte-ffi/rmake.rs index f4fafb796e3..50f5f14191b 100644 --- a/tests/run-make/mte-ffi/rmake.rs +++ b/tests/run-make/mte-ffi/rmake.rs @@ -1,14 +1,12 @@ -// Tests that MTE tags and values stored in the top byte of a pointer (TBI) are -// preserved across FFI boundaries (C <-> Rust). -// This test does not require MTE: whilst the test will use MTE if available, if it is not, -// arbitrary tag bits are set using TBI. +//! Tests that MTE tags and values stored in the top byte of a pointer (TBI) are preserved across +//! FFI boundaries (C <-> Rust). This test does not require MTE: whilst the test will use MTE if +//! available, if it is not, arbitrary tag bits are set using TBI. -// This test is only valid for AArch64. -// The linker must be explicitly specified when cross-compiling, so it is limited to -// `aarch64-unknown-linux-gnu`. //@ only-aarch64-unknown-linux-gnu +// Reason: this test is only valid for AArch64 with `gcc`. The linker must be explicitly specified +// when cross-compiling, so it is limited to `aarch64-unknown-linux-gnu`. -use run_make_support::{cc, dynamic_lib_name, extra_c_flags, run, rustc, target}; +use run_make_support::{dynamic_lib_name, extra_c_flags, gcc, run, rustc, target}; fn main() { run_test("int"); @@ -29,7 +27,8 @@ fn run_test(variant: &str) { .target(target()) .linker("aarch64-linux-gnu-gcc") .run(); - cc().input(format!("bar_{variant}.c")) + gcc() + .input(format!("bar_{variant}.c")) .input(dynamic_lib_name("foo")) .out_exe("test") .args(&flags) diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js index 068298e7236..8bffef61c8f 100644 --- a/tests/rustdoc-js-std/parser-errors.js +++ b/tests/rustdoc-js-std/parser-errors.js @@ -143,14 +143,6 @@ const PARSED = [ returned: [], error: "Unexpected `:: ::`", }, - { - query: "a::b::", - elems: [], - foundElems: 0, - userQuery: "a::b::", - returned: [], - error: "Paths cannot end with `::`", - }, { query: ":a", elems: [], diff --git a/tests/rustdoc-js-std/path-end-empty.js b/tests/rustdoc-js-std/path-end-empty.js new file mode 100644 index 00000000000..6e853c61b4d --- /dev/null +++ b/tests/rustdoc-js-std/path-end-empty.js @@ -0,0 +1,6 @@ +const EXPECTED = { + 'query': 'Option::', + 'others': [ + { 'path': 'std::option::Option', 'name': 'get_or_insert_default' }, + ], +} diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs index d7f37f36681..3534228f73e 100644 --- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs +++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs @@ -64,7 +64,7 @@ fn check_instance(instance: &Instance) { if instance.has_body() { let Some(body) = instance.body() else { unreachable!("Expected a body") }; assert!(!body.blocks.is_empty()); - assert_eq!(&name, "likely"); + assert_eq!(&name, "select_unpredictable"); } else { assert!(instance.body().is_none()); assert_matches!(name.as_str(), "size_of_val" | "vtable_size"); @@ -78,7 +78,7 @@ fn check_def(fn_def: FnDef) { let name = intrinsic.fn_name(); match name.as_str() { - "likely" => { + "select_unpredictable" => { assert!(!intrinsic.must_be_overridden()); assert!(fn_def.has_body()); } @@ -132,7 +132,7 @@ fn generate_input(path: &str) -> std::io::Result<()> { pub fn use_intrinsics(init: bool) -> bool {{ let vtable_sz = unsafe {{ vtable_size(0 as *const ()) }}; let sz = unsafe {{ size_of_val("hi") }}; - likely(init && sz == 2) + select_unpredictable(init && sz == 2, false, true) }} "# )?; diff --git a/tests/ui/consts/const-ptr-is-null.rs b/tests/ui/consts/const-ptr-is-null.rs index 82c293c0ad6..92cf87a9782 100644 --- a/tests/ui/consts/const-ptr-is-null.rs +++ b/tests/ui/consts/const-ptr-is-null.rs @@ -1,4 +1,3 @@ -#![feature(const_ptr_is_null)] use std::ptr; const IS_NULL: () = { diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr index 5fd35142818..f71b3752772 100644 --- a/tests/ui/consts/const-ptr-is-null.stderr +++ b/tests/ui/consts/const-ptr-is-null.stderr @@ -8,7 +8,7 @@ note: inside `std::ptr::const_ptr::::is_null::compiletime` note: inside `std::ptr::const_ptr::::is_null` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `MAYBE_NULL` - --> $DIR/const-ptr-is-null.rs:17:14 + --> $DIR/const-ptr-is-null.rs:16:14 | LL | assert!(!ptr.wrapping_sub(512).is_null()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/is_val_statically_known.rs b/tests/ui/consts/is_val_statically_known.rs index a9059817bcc..d55910d32d3 100644 --- a/tests/ui/consts/is_val_statically_known.rs +++ b/tests/ui/consts/is_val_statically_known.rs @@ -1,6 +1,6 @@ //@ run-pass -#![feature(core_intrinsics, is_val_statically_known)] +#![feature(core_intrinsics)] use std::intrinsics::is_val_statically_known; diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs new file mode 100644 index 00000000000..b923a768cbf --- /dev/null +++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs @@ -0,0 +1,12 @@ +//! Ensure we do not ICE when a promoted fails to evaluate due to running out of memory. +//! Also see . + +// Needs the max type size to be much bigger than the RAM people typically have. +//@ only-64bit + +pub struct Data([u8; (1 << 47) - 1]); +const _: &'static Data = &Data([0; (1 << 47) - 1]); +//~^ERROR: evaluation of constant value failed +//~| tried to allocate more memory than available to compiler + +fn main() {} diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr new file mode 100644 index 00000000000..50e920f05f9 --- /dev/null +++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:32 + | +LL | const _: &'static Data = &Data([0; (1 << 47) - 1]); + | ^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler + +note: erroneous constant encountered + --> $DIR/promoted_running_out_of_memory_issue-130687.rs:8:26 + | +LL | const _: &'static Data = &Data([0; (1 << 47) - 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/ptr_is_null.rs b/tests/ui/consts/ptr_is_null.rs index bbf13802312..8b41f5718e8 100644 --- a/tests/ui/consts/ptr_is_null.rs +++ b/tests/ui/consts/ptr_is_null.rs @@ -1,7 +1,6 @@ //@ compile-flags: --crate-type=lib //@ check-pass -#![feature(const_ptr_is_null)] #![allow(useless_ptr_null_checks)] const FOO: &usize = &42; diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs index b35af76da3e..af1c20976d7 100644 --- a/tests/ui/delegation/unsupported.rs +++ b/tests/ui/delegation/unsupported.rs @@ -10,15 +10,11 @@ mod opaque { mod to_reuse { use super::Trait; - pub fn opaque_ret() -> impl Trait { unimplemented!() } - //~^ warn: this function depends on never type fallback being `()` - //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + pub fn opaque_ret() -> impl Trait { () } } trait ToReuse { - fn opaque_ret() -> impl Trait { unimplemented!() } - //~^ warn: this function depends on never type fallback being `()` - //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + fn opaque_ret() -> impl Trait { () } } // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls. diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.stderr index 9391763dca2..2b0bcf9d84e 100644 --- a/tests/ui/delegation/unsupported.stderr +++ b/tests/ui/delegation/unsupported.stderr @@ -1,74 +1,43 @@ -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/unsupported.rs:26:25 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/unsupported.rs:22:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/unsupported.rs:26:25 + --> $DIR/unsupported.rs:22:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/unsupported.rs:25:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/unsupported.rs:21:5 | LL | impl ToReuse for u8 { | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -warning: this function depends on never type fallback being `()` - --> $DIR/unsupported.rs:13:9 - | -LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = 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 #123748 - = help: specify the types explicitly -note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/unsupported.rs:13:32 - | -LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default - -warning: this function depends on never type fallback being `()` - --> $DIR/unsupported.rs:19:9 - | -LL | fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = 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 #123748 - = help: specify the types explicitly -note: in edition 2024, the requirement `!: opaque::Trait` will fail - --> $DIR/unsupported.rs:19:28 - | -LL | fn opaque_ret() -> impl Trait { unimplemented!() } - | ^^^^^^^^^^ - -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/unsupported.rs:29:24 +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/unsupported.rs:25:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/unsupported.rs:29:24 + --> $DIR/unsupported.rs:25:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/unsupported.rs:28:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/unsupported.rs:24:5 | LL | impl ToReuse for u16 { | ^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: recursive delegation is not supported yet - --> $DIR/unsupported.rs:42:22 + --> $DIR/unsupported.rs:38:22 | LL | pub reuse to_reuse2::foo; | --- callee defined here @@ -77,14 +46,14 @@ LL | reuse to_reuse1::foo; | ^^^ error[E0283]: type annotations needed - --> $DIR/unsupported.rs:52:18 + --> $DIR/unsupported.rs:48:18 | LL | reuse Trait::foo; | ^^^ cannot infer type | = note: cannot satisfy `_: effects::Trait` -error: aborting due to 4 previous errors; 2 warnings emitted +error: aborting due to 4 previous errors Some errors have detailed explanations: E0283, E0391. For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed index 3fed16f0ee7..75bc598d17b 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed @@ -16,7 +16,7 @@ fn main() { fn m() { //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x: () = match true { true => Default::default(), //[e2024]~^ error: the trait bound `!: Default` is not satisfied @@ -28,7 +28,7 @@ fn m() { fn q() -> Option<()> { //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! fn deserialize() -> Option { Some(T::default()) } @@ -45,7 +45,7 @@ fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { } fn meow() -> Result<(), ()> { //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! help::<(), _>(1)?; //[e2024]~^ error: the trait bound `(): From` is not satisfied Ok(()) diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr index fdc97e54d4e..454e88d4569 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr @@ -4,7 +4,7 @@ warning: this function depends on never type fallback being `()` LL | fn m() { | ^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail @@ -24,7 +24,7 @@ warning: this function depends on never type fallback being `()` LL | fn q() -> Option<()> { | ^^^^^^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail @@ -43,7 +43,7 @@ warning: this function depends on never type fallback being `()` LL | fn meow() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `(): From` will fail diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs index 71d36f3a2d9..32e83e74139 100644 --- a/tests/ui/editions/never-type-fallback-breaking.rs +++ b/tests/ui/editions/never-type-fallback-breaking.rs @@ -16,7 +16,7 @@ fn main() { fn m() { //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x = match true { true => Default::default(), //[e2024]~^ error: the trait bound `!: Default` is not satisfied @@ -28,7 +28,7 @@ fn m() { fn q() -> Option<()> { //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! fn deserialize() -> Option { Some(T::default()) } @@ -45,7 +45,7 @@ fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { } fn meow() -> Result<(), ()> { //[e2021]~^ this function depends on never type fallback being `()` - //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! help(1)?; //[e2024]~^ error: the trait bound `(): From` is not satisfied Ok(()) diff --git a/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-macro.rs b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-macro.rs new file mode 100644 index 00000000000..2efdc2342c1 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-macro.rs @@ -0,0 +1,20 @@ +// A macro_rules macro in 2015 that has an RPIT without `use<>` that would +// cause a problem with 2024 capturing rules. + +#[macro_export] +macro_rules! macro_rpit { + () => { + fn test_mbe(x: &Vec) -> impl std::fmt::Display { + x[0] + } + + pub fn from_mbe() { + let mut x = vec![]; + x.push(1); + + let element = test_mbe(&x); + x.push(2); + println!("{element}"); + } + }; +} diff --git a/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs new file mode 100644 index 00000000000..e197dcfef80 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/auxiliary/no-use-pm.rs @@ -0,0 +1,29 @@ +// A proc-macro in 2015 that has an RPIT without `use<>` that would cause a +// problem with 2024 capturing rules. + +//@ force-host +//@ no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn pm_rpit(input: TokenStream) -> TokenStream { + "fn test_pm(x: &Vec) -> impl std::fmt::Display { + x[0] +} + +pub fn from_pm() { + let mut x = vec![]; + x.push(1); + + let element = test_pm(&x); + x.push(2); + println!(\"{element}\"); +} +" + .parse() + .unwrap() +} diff --git a/tests/ui/impl-trait/precise-capturing/external-macro.rs b/tests/ui/impl-trait/precise-capturing/external-macro.rs new file mode 100644 index 00000000000..492e8036461 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/external-macro.rs @@ -0,0 +1,26 @@ +// Tests that code generated from an external macro (MBE and proc-macro) that +// has an RPIT will not fail when the call-site is 2024. +// https://github.com/rust-lang/rust/issues/132917 + +//@ aux-crate: no_use_pm=no-use-pm.rs +//@ aux-crate: no_use_macro=no-use-macro.rs +//@ edition: 2024 +//@ compile-flags:-Z unstable-options +//@ check-pass + +no_use_pm::pm_rpit!{} + +no_use_macro::macro_rpit!{} + +fn main() { + let mut x = vec![]; + x.push(1); + + let element = test_pm(&x); + x.push(2); + println!("{element}"); + + let element = test_mbe(&x); + x.push(2); + println!("{element}"); +} diff --git a/tests/ui/intrinsics/reify-intrinsic.rs b/tests/ui/intrinsics/reify-intrinsic.rs index 6c52651f060..0d047ccf4a3 100644 --- a/tests/ui/intrinsics/reify-intrinsic.rs +++ b/tests/ui/intrinsics/reify-intrinsic.rs @@ -13,9 +13,9 @@ fn b() { } fn c() { - let _: [unsafe extern "rust-intrinsic" fn(bool) -> bool; 2] = [ - std::intrinsics::likely, //~ ERROR cannot coerce - std::intrinsics::unlikely, + let _: [unsafe extern "rust-intrinsic" fn(f32) -> f32; 2] = [ + std::intrinsics::floorf32, //~ ERROR cannot coerce + std::intrinsics::log2f32, ]; } diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr index 7af17147f28..a456e81e762 100644 --- a/tests/ui/intrinsics/reify-intrinsic.stderr +++ b/tests/ui/intrinsics/reify-intrinsic.stderr @@ -18,11 +18,11 @@ LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) error[E0308]: cannot coerce intrinsics to function pointers --> $DIR/reify-intrinsic.rs:17:9 | -LL | std::intrinsics::likely, - | ^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers +LL | std::intrinsics::floorf32, + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _` - found fn item `fn(_) -> _ {likely}` + found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {floorf32}` error: aborting due to 3 previous errors diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.rs b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.rs new file mode 100644 index 00000000000..8d854c6c237 --- /dev/null +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.rs @@ -0,0 +1,31 @@ +//@ only-x86_64 + +const fn foo() -> i32 { + U +} + +fn main() { + std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, || ()); + //~^ invalid argument to a legacy const generic + + std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ()); + //~^ invalid argument to a legacy const generic + + std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<{ 1 + 2 }>()); + //~^ invalid argument to a legacy const generic + + std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<3>()); + //~^ invalid argument to a legacy const generic + + std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, &const {}); + //~^ invalid argument to a legacy const generic + + std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, { + struct F(); + //~^ invalid argument to a legacy const generic + 1 + }); + + std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ()); + //~^ invalid argument to a legacy const generic +} diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr new file mode 100644 index 00000000000..7e05ae4f20c --- /dev/null +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-issue-123077.stderr @@ -0,0 +1,82 @@ +error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items + --> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:8:55 + | +LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, || ()); + | ^^^^^ + | +help: try using a const generic argument instead + | +LL | std::arch::x86_64::_mm_blend_ps::<{ || () }>(loop {}, loop {}); + | +++++++++++++ ~~~~~~~~~~~~~~~~ + +error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items + --> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:11:59 + | +LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, 5 + || ()); + | ^^^^^ + | +help: try using a const generic argument instead + | +LL | std::arch::x86_64::_mm_blend_ps::<{ 5 + (|| ()) }>(loop {}, loop {}); + | +++++++++++++++++++ ~~~~~~~~~~~~~~~~ + +error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items + --> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:14:61 + | +LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<{ 1 + 2 }>()); + | ^^^^^^^^^ + | +help: try using a const generic argument instead + | +LL | std::arch::x86_64::_mm_blend_ps::<{ foo::<{ 1 + 2 }>() }>(loop {}, loop {}); + | ++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~ + +error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items + --> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:17:61 + | +LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, foo::<3>()); + | ^ + | +help: try using a const generic argument instead + | +LL | std::arch::x86_64::_mm_blend_ps::<{ foo::<3>() }>(loop {}, loop {}); + | ++++++++++++++++++ ~~~~~~~~~~~~~~~~ + +error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items + --> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:20:56 + | +LL | std::arch::x86_64::_mm_blend_ps(loop {}, loop {}, &const {}); + | ^^^^^^^^ + | +help: try using a const generic argument instead + | +LL | std::arch::x86_64::_mm_blend_ps::<{ &const {} }>(loop {}, loop {}); + | +++++++++++++++++ ~~~~~~~~~~~~~~~~ + +error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items + --> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:24:9 + | +LL | struct F(); + | ^^^^^^^^^^^ + | +help: try using a const generic argument instead + | +LL ~ std::arch::x86_64::_mm_blend_ps::<{ { +LL + struct F(); +LL + 1 +LL ~ } }>(loop {}, loop {}); + | + +error: invalid argument to a legacy const generic: cannot have const blocks, closures, async blocks or items + --> $DIR/invalid-rustc_legacy_const_generics-issue-123077.rs:29:59 + | +LL | std::arch::x86_64::_mm_inserti_si64(loop {}, loop {}, || (), 1 + || ()); + | ^^^^^ + | +help: try using a const generic argument instead + | +LL | std::arch::x86_64::_mm_inserti_si64::<{ || () }, { 1 + (|| ()) }>(loop {}, loop {}); + | ++++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~ + +error: aborting due to 7 previous errors + diff --git a/tests/ui/issues/issue-39848.stderr b/tests/ui/issues/issue-39848.stderr index a6c6c61f170..1ffed2d4a1d 100644 --- a/tests/ui/issues/issue-39848.stderr +++ b/tests/ui/issues/issue-39848.stderr @@ -16,10 +16,10 @@ LL | if $tgt.has_$field() {} LL | get_opt!(bar, foo); | ------------------ in this macro invocation = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info) -help: try placing this code inside a block +help: you might have meant to write a method call | -LL | if $tgt.has_{ $field() } {} - | + + +LL | if $tgt.has_.$field() {} + | + error: aborting due to 1 previous error diff --git a/tests/ui/let-else/let-else-if.stderr b/tests/ui/let-else/let-else-if.stderr index 7e2215c8c05..ad36b423150 100644 --- a/tests/ui/let-else/let-else-if.stderr +++ b/tests/ui/let-else/let-else-if.stderr @@ -4,7 +4,7 @@ error: conditional `else if` is not supported for `let...else` LL | let Some(_) = Some(()) else if true { | ^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL ~ let Some(_) = Some(()) else { if true { LL | diff --git a/tests/ui/lint/issue-104392.stderr b/tests/ui/lint/issue-104392.stderr index 8e466439ae6..4d8d8c56d41 100644 --- a/tests/ui/lint/issue-104392.stderr +++ b/tests/ui/lint/issue-104392.stderr @@ -6,7 +6,7 @@ LL | { unsafe 92 } | | | while parsing this `unsafe` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { unsafe { 92 } } | + + diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed index 7cf4aa6cdd4..ada37ccd640 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed @@ -10,7 +10,7 @@ unused_mut, unused_variables )] -#![deny(unused_parens)] +#![deny(unused_parens, unused_braces)] fn lint_on_top_level() { let a = 0; //~ ERROR unnecessary parentheses around pattern @@ -43,8 +43,10 @@ fn no_lint_ops() { fn lint_break_if_not_followed_by_block() { #![allow(unreachable_code)] loop { if break {} } //~ ERROR unnecessary parentheses - loop { if break ({ println!("hello") }) {} } //~ ERROR unnecessary parentheses - loop { if (break { println!("hello") }) {} } + loop { if break { println!("hello") } {} } + //~^ ERROR unnecessary parentheses around `if` condition + //~| ERROR unnecessary parentheses around `break` value + loop { if (break println!("hello")) {} } //~ ERROR unnecessary braces around `break` value } // Don't lint in these cases (#64106). diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs index 013255dc213..67066c3bee3 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs @@ -10,7 +10,7 @@ unused_mut, unused_variables )] -#![deny(unused_parens)] +#![deny(unused_parens, unused_braces)] fn lint_on_top_level() { let (a) = 0; //~ ERROR unnecessary parentheses around pattern @@ -43,8 +43,10 @@ fn no_lint_ops() { fn lint_break_if_not_followed_by_block() { #![allow(unreachable_code)] loop { if (break) {} } //~ ERROR unnecessary parentheses - loop { if (break ({ println!("hello") })) {} } //~ ERROR unnecessary parentheses - loop { if (break { println!("hello") }) {} } + loop { if (break ({ println!("hello") })) {} } + //~^ ERROR unnecessary parentheses around `if` condition + //~| ERROR unnecessary parentheses around `break` value + loop { if (break { println!("hello") }) {} } //~ ERROR unnecessary braces around `break` value } // Don't lint in these cases (#64106). diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr index f916bba8194..d5fdaef42d8 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr @@ -7,7 +7,7 @@ LL | let (a) = 0; note: the lint level is defined here --> $DIR/issue-54538-unused-parens-lint.rs:13:9 | -LL | #![deny(unused_parens)] +LL | #![deny(unused_parens, unused_braces)] | ^^^^^^^^^^^^^ help: remove these parentheses | @@ -99,8 +99,37 @@ LL - loop { if (break ({ println!("hello") })) {} } LL + loop { if break ({ println!("hello") }) {} } | +error: unnecessary parentheses around `break` value + --> $DIR/issue-54538-unused-parens-lint.rs:46:22 + | +LL | loop { if (break ({ println!("hello") })) {} } + | ^ ^ + | +help: remove these parentheses + | +LL - loop { if (break ({ println!("hello") })) {} } +LL + loop { if (break { println!("hello") }) {} } + | + +error: unnecessary braces around `break` value + --> $DIR/issue-54538-unused-parens-lint.rs:49:22 + | +LL | loop { if (break { println!("hello") }) {} } + | ^^ ^^ + | +note: the lint level is defined here + --> $DIR/issue-54538-unused-parens-lint.rs:13:24 + | +LL | #![deny(unused_parens, unused_braces)] + | ^^^^^^^^^^^^^ +help: remove these braces + | +LL - loop { if (break { println!("hello") }) {} } +LL + loop { if (break println!("hello")) {} } + | + error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:71:12 + --> $DIR/issue-54538-unused-parens-lint.rs:73:12 | LL | if let (0 | 1) = 0 {} | ^ ^ @@ -112,7 +141,7 @@ LL + if let 0 | 1 = 0 {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:72:13 + --> $DIR/issue-54538-unused-parens-lint.rs:74:13 | LL | if let ((0 | 1),) = (0,) {} | ^ ^ @@ -124,7 +153,7 @@ LL + if let (0 | 1,) = (0,) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:73:13 + --> $DIR/issue-54538-unused-parens-lint.rs:75:13 | LL | if let [(0 | 1)] = [0] {} | ^ ^ @@ -136,7 +165,7 @@ LL + if let [0 | 1] = [0] {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:74:16 + --> $DIR/issue-54538-unused-parens-lint.rs:76:16 | LL | if let 0 | (1 | 2) = 0 {} | ^ ^ @@ -148,7 +177,7 @@ LL + if let 0 | 1 | 2 = 0 {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:76:15 + --> $DIR/issue-54538-unused-parens-lint.rs:78:15 | LL | if let TS((0 | 1)) = TS(0) {} | ^ ^ @@ -160,7 +189,7 @@ LL + if let TS(0 | 1) = TS(0) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:78:20 + --> $DIR/issue-54538-unused-parens-lint.rs:80:20 | LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} | ^ ^ @@ -172,7 +201,7 @@ LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:88:9 + --> $DIR/issue-54538-unused-parens-lint.rs:90:9 | LL | (_) => {} | ^ ^ @@ -184,7 +213,7 @@ LL + _ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:89:9 + --> $DIR/issue-54538-unused-parens-lint.rs:91:9 | LL | (y) => {} | ^ ^ @@ -196,7 +225,7 @@ LL + y => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:90:9 + --> $DIR/issue-54538-unused-parens-lint.rs:92:9 | LL | (ref r) => {} | ^ ^ @@ -208,7 +237,7 @@ LL + ref r => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:91:9 + --> $DIR/issue-54538-unused-parens-lint.rs:93:9 | LL | (e @ 1...2) => {} | ^ ^ @@ -220,7 +249,7 @@ LL + e @ 1...2 => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:97:9 + --> $DIR/issue-54538-unused-parens-lint.rs:99:9 | LL | (e @ &(1...2)) => {} | ^ ^ @@ -232,7 +261,7 @@ LL + e @ &(1...2) => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:98:10 + --> $DIR/issue-54538-unused-parens-lint.rs:100:10 | LL | &(_) => {} | ^ ^ @@ -244,7 +273,7 @@ LL + &_ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:109:9 + --> $DIR/issue-54538-unused-parens-lint.rs:111:9 | LL | (_) => {} | ^ ^ @@ -256,7 +285,7 @@ LL + _ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:110:9 + --> $DIR/issue-54538-unused-parens-lint.rs:112:9 | LL | (y) => {} | ^ ^ @@ -268,7 +297,7 @@ LL + y => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:111:9 + --> $DIR/issue-54538-unused-parens-lint.rs:113:9 | LL | (ref r) => {} | ^ ^ @@ -280,7 +309,7 @@ LL + ref r => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:112:9 + --> $DIR/issue-54538-unused-parens-lint.rs:114:9 | LL | (e @ 1..=2) => {} | ^ ^ @@ -292,7 +321,7 @@ LL + e @ 1..=2 => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:118:9 + --> $DIR/issue-54538-unused-parens-lint.rs:120:9 | LL | (e @ &(1..=2)) => {} | ^ ^ @@ -304,7 +333,7 @@ LL + e @ &(1..=2) => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:119:10 + --> $DIR/issue-54538-unused-parens-lint.rs:121:10 | LL | &(_) => {} | ^ ^ @@ -315,5 +344,5 @@ LL - &(_) => {} LL + &_ => {} | -error: aborting due to 26 previous errors +error: aborting due to 28 previous errors diff --git a/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.fixed b/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.fixed new file mode 100644 index 00000000000..9343d906cdc --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.fixed @@ -0,0 +1,32 @@ +//@ run-rustfix +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn foo() { + loop { + break (_ = 42); + // lint unused_parens should not be triggered here. + } + + let _ = loop { + let a = 1; + let b = 2; + break a + b; //~ERROR unnecessary parentheses + }; + + loop { + if break return () { + //~^ ERROR unnecessary parentheses + } + if break return () { + //~^ ERROR unnecessary parentheses + } + } + + return (_ = 42); + // lint unused_parens should not be triggered here. +} + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.rs b/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.rs new file mode 100644 index 00000000000..fe9cba3e168 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.rs @@ -0,0 +1,32 @@ +//@ run-rustfix +#![deny(unused_parens)] +#![allow(unreachable_code)] + +fn foo() { + loop { + break (_ = 42); + // lint unused_parens should not be triggered here. + } + + let _ = loop { + let a = 1; + let b = 2; + break (a + b); //~ERROR unnecessary parentheses + }; + + loop { + if (break return ()) { + //~^ ERROR unnecessary parentheses + } + if break (return ()) { + //~^ ERROR unnecessary parentheses + } + } + + return (_ = 42); + // lint unused_parens should not be triggered here. +} + +fn main() { + let _ = foo(); +} diff --git a/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.stderr b/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.stderr new file mode 100644 index 00000000000..c41cf32bade --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-assign-expr-in-ret-issue-131989.stderr @@ -0,0 +1,43 @@ +error: unnecessary parentheses around `break` value + --> $DIR/unused-parens-assign-expr-in-ret-issue-131989.rs:14:15 + | +LL | break (a + b); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused-parens-assign-expr-in-ret-issue-131989.rs:2:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - break (a + b); +LL + break a + b; + | + +error: unnecessary parentheses around `if` condition + --> $DIR/unused-parens-assign-expr-in-ret-issue-131989.rs:18:12 + | +LL | if (break return ()) { + | ^ ^ + | +help: remove these parentheses + | +LL - if (break return ()) { +LL + if break return () { + | + +error: unnecessary parentheses around `break` value + --> $DIR/unused-parens-assign-expr-in-ret-issue-131989.rs:21:18 + | +LL | if break (return ()) { + | ^ ^ + | +help: remove these parentheses + | +LL - if break (return ()) { +LL + if break return () { + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused_parens_json_suggestion.fixed b/tests/ui/lint/unused_parens_json_suggestion.fixed index 89fd0d86614..f26bedc3fd5 100644 --- a/tests/ui/lint/unused_parens_json_suggestion.fixed +++ b/tests/ui/lint/unused_parens_json_suggestion.fixed @@ -9,7 +9,7 @@ // test of the JSON error format. #![deny(unused_parens)] -#![allow(unreachable_code)] +#![allow(unreachable_code, unused_braces)] fn main() { // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not diff --git a/tests/ui/lint/unused_parens_json_suggestion.rs b/tests/ui/lint/unused_parens_json_suggestion.rs index 4526084196c..af3d88f71bb 100644 --- a/tests/ui/lint/unused_parens_json_suggestion.rs +++ b/tests/ui/lint/unused_parens_json_suggestion.rs @@ -9,7 +9,7 @@ // test of the JSON error format. #![deny(unused_parens)] -#![allow(unreachable_code)] +#![allow(unreachable_code, unused_braces)] fn main() { // We want to suggest the properly-balanced expression `1 / (2 + 3)`, not diff --git a/tests/ui/lint/unused_parens_json_suggestion.stderr b/tests/ui/lint/unused_parens_json_suggestion.stderr index 1f4928cd464..2ce31817d29 100644 --- a/tests/ui/lint/unused_parens_json_suggestion.stderr +++ b/tests/ui/lint/unused_parens_json_suggestion.stderr @@ -1,4 +1,4 @@ -{"$message_type":"diagnostic","message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":633,"byte_end":634,"line_start":17,"line_end":17,"column_start":26,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":26,"highlight_end":27}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":439,"byte_end":452,"line_start":11,"line_end":11,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![deny(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":633,"byte_end":634,"line_start":17,"line_end":17,"column_start":26,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":26,"highlight_end":27}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around assigned value +{"$message_type":"diagnostic","message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":636,"byte_end":637,"line_start":17,"line_end":17,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":648,"byte_end":649,"line_start":17,"line_end":17,"column_start":26,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":26,"highlight_end":27}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":439,"byte_end":452,"line_start":11,"line_end":11,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![deny(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":636,"byte_end":637,"line_start":17,"line_end":17,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":648,"byte_end":649,"line_start":17,"line_end":17,"column_start":26,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":26,"highlight_end":27}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around assigned value --> $DIR/unused_parens_json_suggestion.rs:17:14 | LL | let _a = (1 / (2 + 3)); diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.fixed b/tests/ui/lint/unused_parens_remove_json_suggestion.fixed index e2774d5d7e5..899c24f83ed 100644 --- a/tests/ui/lint/unused_parens_remove_json_suggestion.fixed +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.fixed @@ -9,7 +9,7 @@ // test of the JSON error format. #![deny(unused_parens)] -#![allow(unreachable_code)] +#![allow(unreachable_code, unused_braces)] fn main() { diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.rs b/tests/ui/lint/unused_parens_remove_json_suggestion.rs index b3ac87178db..7f5d935c4ac 100644 --- a/tests/ui/lint/unused_parens_remove_json_suggestion.rs +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.rs @@ -9,7 +9,7 @@ // test of the JSON error format. #![deny(unused_parens)] -#![allow(unreachable_code)] +#![allow(unreachable_code, unused_braces)] fn main() { diff --git a/tests/ui/lint/unused_parens_remove_json_suggestion.stderr b/tests/ui/lint/unused_parens_remove_json_suggestion.stderr index 9268fc1abc4..975de4edfdf 100644 --- a/tests/ui/lint/unused_parens_remove_json_suggestion.stderr +++ b/tests/ui/lint/unused_parens_remove_json_suggestion.stderr @@ -1,4 +1,4 @@ -{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":525,"byte_end":526,"line_start":18,"line_end":18,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":528,"byte_end":529,"line_start":18,"line_end":18,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":439,"byte_end":452,"line_start":11,"line_end":11,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![deny(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":525,"byte_end":526,"line_start":18,"line_end":18,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":528,"byte_end":529,"line_start":18,"line_end":18,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition +{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":540,"byte_end":541,"line_start":18,"line_end":18,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":543,"byte_end":544,"line_start":18,"line_end":18,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":439,"byte_end":452,"line_start":11,"line_end":11,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![deny(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":540,"byte_end":541,"line_start":18,"line_end":18,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":543,"byte_end":544,"line_start":18,"line_end":18,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" if (_b) {","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition --> $DIR/unused_parens_remove_json_suggestion.rs:18:8 | LL | if (_b) { @@ -16,7 +16,7 @@ LL + if _b { | "} -{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":622,"byte_end":623,"line_start":29,"line_end":29,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":7,"highlight_end":8}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":624,"byte_end":625,"line_start":29,"line_end":29,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":622,"byte_end":623,"line_start":29,"line_end":29,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":7,"highlight_end":8}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":624,"byte_end":625,"line_start":29,"line_end":29,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition +{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":637,"byte_end":638,"line_start":29,"line_end":29,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":7,"highlight_end":8}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":639,"byte_end":640,"line_start":29,"line_end":29,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":637,"byte_end":638,"line_start":29,"line_end":29,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":7,"highlight_end":8}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":639,"byte_end":640,"line_start":29,"line_end":29,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" if(c) {","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition --> $DIR/unused_parens_remove_json_suggestion.rs:29:7 | LL | if(c) { @@ -29,7 +29,7 @@ LL + if c { | "} -{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":668,"byte_end":669,"line_start":33,"line_end":33,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":670,"byte_end":671,"line_start":33,"line_end":33,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" if (c){","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":668,"byte_end":669,"line_start":33,"line_end":33,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":670,"byte_end":671,"line_start":33,"line_end":33,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" if (c){","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition +{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":683,"byte_end":684,"line_start":33,"line_end":33,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":685,"byte_end":686,"line_start":33,"line_end":33,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" if (c){","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":683,"byte_end":684,"line_start":33,"line_end":33,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){","highlight_start":8,"highlight_end":9}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":685,"byte_end":686,"line_start":33,"line_end":33,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" if (c){","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition --> $DIR/unused_parens_remove_json_suggestion.rs:33:8 | LL | if (c){ @@ -42,7 +42,7 @@ LL + if c { | "} -{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":716,"byte_end":717,"line_start":37,"line_end":37,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":730,"byte_end":731,"line_start":37,"line_end":37,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":716,"byte_end":717,"line_start":37,"line_end":37,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":730,"byte_end":731,"line_start":37,"line_end":37,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition +{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":731,"byte_end":732,"line_start":37,"line_end":37,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":745,"byte_end":746,"line_start":37,"line_end":37,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":731,"byte_end":732,"line_start":37,"line_end":37,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":745,"byte_end":746,"line_start":37,"line_end":37,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition --> $DIR/unused_parens_remove_json_suggestion.rs:37:11 | LL | while (false && true){ @@ -55,7 +55,7 @@ LL + while false && true { | "} -{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":744,"byte_end":745,"line_start":38,"line_end":38,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":12,"highlight_end":13}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":746,"byte_end":747,"line_start":38,"line_end":38,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":744,"byte_end":745,"line_start":38,"line_end":38,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":12,"highlight_end":13}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":746,"byte_end":747,"line_start":38,"line_end":38,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition +{"$message_type":"diagnostic","message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":759,"byte_end":760,"line_start":38,"line_end":38,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":12,"highlight_end":13}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":761,"byte_end":762,"line_start":38,"line_end":38,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":759,"byte_end":760,"line_start":38,"line_end":38,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":12,"highlight_end":13}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":761,"byte_end":762,"line_start":38,"line_end":38,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" if (c) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `if` condition --> $DIR/unused_parens_remove_json_suggestion.rs:38:12 | LL | if (c) { @@ -68,7 +68,7 @@ LL + if c { | "} -{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":44,"line_end":44,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":44,"line_end":44,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":24,"highlight_end":25}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":44,"line_end":44,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":44,"line_end":44,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":24,"highlight_end":25}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition +{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":822,"byte_end":823,"line_start":44,"line_end":44,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":836,"byte_end":837,"line_start":44,"line_end":44,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":24,"highlight_end":25}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":822,"byte_end":823,"line_start":44,"line_end":44,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":10,"highlight_end":11}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":836,"byte_end":837,"line_start":44,"line_end":44,"column_start":24,"column_end":25,"is_primary":true,"text":[{"text":" while(true && false) {","highlight_start":24,"highlight_end":25}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition --> $DIR/unused_parens_remove_json_suggestion.rs:44:10 | LL | while(true && false) { @@ -81,7 +81,7 @@ LL + while true && false { | "} -{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":842,"byte_end":843,"line_start":45,"line_end":45,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":18,"highlight_end":19}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":849,"byte_end":850,"line_start":45,"line_end":45,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":842,"byte_end":843,"line_start":45,"line_end":45,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":18,"highlight_end":19}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":849,"byte_end":850,"line_start":45,"line_end":45,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `for` iterator expression +{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":857,"byte_end":858,"line_start":45,"line_end":45,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":18,"highlight_end":19}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":864,"byte_end":865,"line_start":45,"line_end":45,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":857,"byte_end":858,"line_start":45,"line_end":45,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":18,"highlight_end":19}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":864,"byte_end":865,"line_start":45,"line_end":45,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `for` iterator expression --> $DIR/unused_parens_remove_json_suggestion.rs:45:18 | LL | for _ in (0 .. 3){ @@ -94,7 +94,7 @@ LL + for _ in 0 .. 3 { | "} -{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":909,"byte_end":910,"line_start":50,"line_end":50,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":916,"byte_end":917,"line_start":50,"line_end":50,"column_start":21,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":21,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":909,"byte_end":910,"line_start":50,"line_end":50,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":916,"byte_end":917,"line_start":50,"line_end":50,"column_start":21,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":21,"highlight_end":22}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `for` iterator expression +{"$message_type":"diagnostic","message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":924,"byte_end":925,"line_start":50,"line_end":50,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":931,"byte_end":932,"line_start":50,"line_end":50,"column_start":21,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":21,"highlight_end":22}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":924,"byte_end":925,"line_start":50,"line_end":50,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":14,"highlight_end":15}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":931,"byte_end":932,"line_start":50,"line_end":50,"column_start":21,"column_end":22,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {","highlight_start":21,"highlight_end":22}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `for` iterator expression --> $DIR/unused_parens_remove_json_suggestion.rs:50:14 | LL | for _ in (0 .. 3) { @@ -107,7 +107,7 @@ LL + for _ in 0 .. 3 { | "} -{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":934,"byte_end":935,"line_start":51,"line_end":51,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":15,"highlight_end":16}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":948,"byte_end":949,"line_start":51,"line_end":51,"column_start":29,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":29,"highlight_end":30}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":934,"byte_end":935,"line_start":51,"line_end":51,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":15,"highlight_end":16}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":948,"byte_end":949,"line_start":51,"line_end":51,"column_start":29,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":29,"highlight_end":30}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition +{"$message_type":"diagnostic","message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":949,"byte_end":950,"line_start":51,"line_end":51,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":15,"highlight_end":16}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":963,"byte_end":964,"line_start":51,"line_end":51,"column_start":29,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":29,"highlight_end":30}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":949,"byte_end":950,"line_start":51,"line_end":51,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":15,"highlight_end":16}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":963,"byte_end":964,"line_start":51,"line_end":51,"column_start":29,"column_end":30,"is_primary":true,"text":[{"text":" while (true && false) {","highlight_start":29,"highlight_end":30}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition --> $DIR/unused_parens_remove_json_suggestion.rs:51:15 | LL | while (true && false) { diff --git a/tests/ui/missing/missing-block-hint.stderr b/tests/ui/missing/missing-block-hint.stderr index 18719289abd..7a08d70d0ce 100644 --- a/tests/ui/missing/missing-block-hint.stderr +++ b/tests/ui/missing/missing-block-hint.stderr @@ -25,7 +25,7 @@ note: the `if` expression is missing a block after this condition | LL | if (foo) | ^^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { bar; } | + + diff --git a/tests/ui/never_type/defaulted-never-note.nofallback.stderr b/tests/ui/never_type/defaulted-never-note.nofallback.stderr index 6bc4501b6a3..e8d0be10d4d 100644 --- a/tests/ui/never_type/defaulted-never-note.nofallback.stderr +++ b/tests/ui/never_type/defaulted-never-note.nofallback.stderr @@ -4,7 +4,7 @@ warning: this function depends on never type fallback being `()` LL | fn smeg() { | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: ImplementedForUnitButNotNever` will fail diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs index 40861e73b39..badb5d4c51d 100644 --- a/tests/ui/never_type/defaulted-never-note.rs +++ b/tests/ui/never_type/defaulted-never-note.rs @@ -27,7 +27,7 @@ fn foo(_t: T) {} //[fallback]~| NOTE required by a bound in `foo` fn smeg() { //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let _x = return; foo(_x); //[fallback]~^ ERROR the trait bound diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.rs b/tests/ui/never_type/dependency-on-fallback-to-unit.rs index 5448d0be2c6..fad4c7c7df7 100644 --- a/tests/ui/never_type/dependency-on-fallback-to-unit.rs +++ b/tests/ui/never_type/dependency-on-fallback-to-unit.rs @@ -7,7 +7,7 @@ fn main() { fn def() { //~^ warn: this function depends on never type fallback being `()` - //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! match true { false => <_>::default(), true => return, @@ -18,7 +18,7 @@ fn def() { // fn question_mark() -> Result<(), ()> { //~^ warn: this function depends on never type fallback being `()` - //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! deserialize()?; Ok(()) } diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr index 79f47bb5fbc..2f10428ee93 100644 --- a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr +++ b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr @@ -4,7 +4,7 @@ warning: this function depends on never type fallback being `()` LL | fn def() { | ^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail @@ -24,7 +24,7 @@ warning: this function depends on never type fallback being `()` LL | fn question_mark() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail diff --git a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr index d40d1da76f9..35b245bd743 100644 --- a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr @@ -4,7 +4,7 @@ warning: this function depends on never type fallback being `()` LL | fn assignment() { | ^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: UnitDefault` will fail @@ -24,7 +24,7 @@ warning: this function depends on never type fallback being `()` LL | fn assignment_rev() { | ^^^^^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: UnitDefault` will fail diff --git a/tests/ui/never_type/diverging-fallback-control-flow.rs b/tests/ui/never_type/diverging-fallback-control-flow.rs index 575e2e9273c..647667126d4 100644 --- a/tests/ui/never_type/diverging-fallback-control-flow.rs +++ b/tests/ui/never_type/diverging-fallback-control-flow.rs @@ -29,7 +29,7 @@ impl UnitDefault for () { fn assignment() { //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x; if true { @@ -41,7 +41,7 @@ fn assignment() { fn assignment_rev() { //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x; if true { diff --git a/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr index d11c21d9573..689791fc460 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr @@ -4,7 +4,7 @@ warning: this function depends on never type fallback being `()` LL | fn main() { | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Test` will fail diff --git a/tests/ui/never_type/diverging-fallback-no-leak.rs b/tests/ui/never_type/diverging-fallback-no-leak.rs index c6d59c7f273..75ca491bf46 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.rs +++ b/tests/ui/never_type/diverging-fallback-no-leak.rs @@ -13,7 +13,7 @@ fn unconstrained_arg(_: T) {} fn main() { //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! // Here the type variable falls back to `!`, // and hence we get a type error. diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr index 30a5e60a758..42018c54609 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr @@ -4,7 +4,7 @@ warning: this function depends on never type fallback being `()` LL | fn main() { | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: UnitReturn` will fail diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs index 927991db513..fdea3a94d28 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs @@ -27,7 +27,7 @@ fn unconstrained_return() -> T { fn main() { //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! // In Ye Olde Days, the `T` parameter of `unconstrained_return` // winds up "entangled" with the `!` type that results from diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr index fb0166dd9e0..b5b5d87e7dd 100644 --- a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr +++ b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr @@ -4,7 +4,7 @@ warning: this function depends on never type fallback being `()` LL | fn main() { | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Bar` will fail diff --git a/tests/ui/never_type/fallback-closure-ret.rs b/tests/ui/never_type/fallback-closure-ret.rs index 30f9ac54d0b..f1423354f13 100644 --- a/tests/ui/never_type/fallback-closure-ret.rs +++ b/tests/ui/never_type/fallback-closure-ret.rs @@ -20,6 +20,6 @@ fn foo(_: impl Fn() -> R) {} fn main() { //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! foo(|| panic!()); } diff --git a/tests/ui/never_type/impl_trait_fallback.rs b/tests/ui/never_type/impl_trait_fallback.rs index fbe13dbe2ac..bd4caeb2b72 100644 --- a/tests/ui/never_type/impl_trait_fallback.rs +++ b/tests/ui/never_type/impl_trait_fallback.rs @@ -7,6 +7,6 @@ impl T for () {} fn should_ret_unit() -> impl T { //~^ warn: this function depends on never type fallback being `()` - //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! panic!() } diff --git a/tests/ui/never_type/impl_trait_fallback.stderr b/tests/ui/never_type/impl_trait_fallback.stderr index 4496746e018..768c226e989 100644 --- a/tests/ui/never_type/impl_trait_fallback.stderr +++ b/tests/ui/never_type/impl_trait_fallback.stderr @@ -4,7 +4,7 @@ warning: this function depends on never type fallback being `()` LL | fn should_ret_unit() -> impl T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: T` will fail diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr index 6a48a7b9b47..03bb0ca5f3a 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr @@ -4,7 +4,7 @@ warning: never type fallback affects this call to an `unsafe` function LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` on by default @@ -19,7 +19,7 @@ warning: never type fallback affects this call to an `unsafe` function LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -33,7 +33,7 @@ warning: never type fallback affects this union access LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly @@ -43,7 +43,7 @@ warning: never type fallback affects this raw pointer dereference LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -57,7 +57,7 @@ warning: never type fallback affects this call to an `unsafe` function LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -71,7 +71,7 @@ warning: never type fallback affects this call to an `unsafe` function LL | unsafe { zeroed() } | ^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -85,7 +85,7 @@ warning: never type fallback affects this `unsafe` function LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -99,7 +99,7 @@ warning: never type fallback affects this `unsafe` function LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -113,7 +113,7 @@ warning: never type fallback affects this call to an `unsafe` method LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly @@ -126,7 +126,7 @@ LL | match send_message::<_ /* ?0 */>() { LL | msg_send!(); | ----------- in this macro invocation | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly = note: this warning originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr index 844cd62c267..cf12d699f2e 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr @@ -4,7 +4,7 @@ error: never type fallback affects this call to an `unsafe` function LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` on by default @@ -19,7 +19,7 @@ error: never type fallback affects this call to an `unsafe` function LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -33,7 +33,7 @@ error: never type fallback affects this union access LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly @@ -43,7 +43,7 @@ error: never type fallback affects this raw pointer dereference LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -57,7 +57,7 @@ error: never type fallback affects this call to an `unsafe` function LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -71,7 +71,7 @@ error: never type fallback affects this call to an `unsafe` function LL | unsafe { zeroed() } | ^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -85,7 +85,7 @@ error: never type fallback affects this `unsafe` function LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -99,7 +99,7 @@ error: never type fallback affects this `unsafe` function LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly help: use `()` annotations to avoid fallback changes @@ -113,7 +113,7 @@ error: never type fallback affects this call to an `unsafe` method LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly @@ -126,7 +126,7 @@ LL | match send_message::<_ /* ?0 */>() { LL | msg_send!(); | ----------- in this macro invocation | - = warning: this will change its meaning in a future release! + = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see issue #123748 = help: specify the type explicitly = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs index c96f4dda3f8..19b51eea2f5 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs @@ -13,7 +13,7 @@ fn _zero() { unsafe { mem::zeroed() } //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! //[e2024]~| warning: the type `!` does not permit zero-initialization } else { return; @@ -30,7 +30,7 @@ fn _trans() { core::mem::transmute(Zst) //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } } else { return; @@ -47,7 +47,7 @@ fn _union() { unsafe { Union { a: () }.b } //[e2015]~^ warn: never type fallback affects this union access //[e2024]~^^ error: never type fallback affects this union access - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } else { return; }; @@ -58,7 +58,7 @@ fn _deref() { unsafe { *ptr::from_ref(&()).cast() } //[e2015]~^ warn: never type fallback affects this raw pointer dereference //[e2024]~^^ error: never type fallback affects this raw pointer dereference - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } else { return; }; @@ -79,7 +79,7 @@ fn _only_generics() { unsafe { internally_create(x) } //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! x.unwrap() } else { @@ -92,12 +92,12 @@ fn _stored_function() { let zeroed = mem::zeroed; //[e2015]~^ warn: never type fallback affects this `unsafe` function //[e2024]~^^ error: never type fallback affects this `unsafe` function - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! unsafe { zeroed() } //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } else { return; }; @@ -115,7 +115,7 @@ fn _only_generics_stored_function() { let f = internally_create; //[e2015]~^ warn: never type fallback affects this `unsafe` function //[e2024]~^^ error: never type fallback affects this `unsafe` function - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! unsafe { f(x) } @@ -140,7 +140,7 @@ fn _method() { S(marker::PhantomData).create_out_of_thin_air() //[e2015]~^ warn: never type fallback affects this call to an `unsafe` method //[e2024]~^^ error: never type fallback affects this call to an `unsafe` method - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } } else { return; @@ -158,7 +158,7 @@ fn _objc() { match send_message::<_ /* ?0 */>() { //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function - //~| warn: this will change its meaning in a future release! + //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! Ok(x) => x, Err(_) => loop {}, } diff --git a/tests/ui/parser/bad-if-statements.stderr b/tests/ui/parser/bad-if-statements.stderr index ee839db6455..320b1176993 100644 --- a/tests/ui/parser/bad-if-statements.stderr +++ b/tests/ui/parser/bad-if-statements.stderr @@ -29,7 +29,7 @@ note: the `if` expression is missing a block after this condition | LL | if true x | ^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | if true { x } | + + @@ -65,7 +65,7 @@ note: the `if` expression is missing a block after this condition | LL | if true x else {} | ^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | if true { x } else {} | + + diff --git a/tests/ui/parser/block-no-opening-brace.stderr b/tests/ui/parser/block-no-opening-brace.stderr index 83360944ed5..b65de4eac3f 100644 --- a/tests/ui/parser/block-no-opening-brace.stderr +++ b/tests/ui/parser/block-no-opening-brace.stderr @@ -6,7 +6,7 @@ LL | loop LL | let x = 0; | ^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { let x = 0; } | + + @@ -21,7 +21,7 @@ LL | while true LL | let x = 0; | ^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { let x = 0; } | + + @@ -32,7 +32,7 @@ error: expected `{`, found keyword `let` LL | let x = 0; | ^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { let x = 0; } | + + diff --git a/tests/ui/parser/closure-return-syntax.stderr b/tests/ui/parser/closure-return-syntax.stderr index eb8428854af..aacc31ed871 100644 --- a/tests/ui/parser/closure-return-syntax.stderr +++ b/tests/ui/parser/closure-return-syntax.stderr @@ -4,7 +4,7 @@ error: expected `{`, found `22` LL | let x = || -> i32 22; | ^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | let x = || -> i32 { 22 }; | + + diff --git a/tests/ui/parser/else-no-if.stderr b/tests/ui/parser/else-no-if.stderr index 2e3e8f6b50e..eec64b0f4bc 100644 --- a/tests/ui/parser/else-no-if.stderr +++ b/tests/ui/parser/else-no-if.stderr @@ -30,7 +30,7 @@ error: expected `{`, found `falsy` LL | } else falsy(); | ^^^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | } else { falsy() }; | + + @@ -41,7 +41,7 @@ error: expected `{`, found keyword `loop` LL | } else loop{} | ^^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | } else { loop{} } | + + @@ -65,7 +65,7 @@ error: expected `{`, found `falsy` LL | } else falsy!(); | ^^^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | } else { falsy!() }; | + + @@ -74,12 +74,14 @@ error: expected `{`, found `falsy` --> $DIR/else-no-if.rs:47:12 | LL | } else falsy! {} { - | ^^^^^ expected `{` + | ---- ^^^^^ + | | + | expected an `if` or a block after this `else` | -help: try placing this code inside a block +help: add an `if` if this is the condition of a chained `else if` statement | -LL | } else { falsy! {} } { - | + + +LL | } else if falsy! {} { + | ++ error: expected `{`, found `falsy` --> $DIR/else-no-if.rs:54:12 @@ -87,7 +89,7 @@ error: expected `{`, found `falsy` LL | } else falsy! {}; | ^^^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | } else { falsy! {} }; | + + diff --git a/tests/ui/parser/label-after-block-like.stderr b/tests/ui/parser/label-after-block-like.stderr index be8c679d8ce..4dea225e3f3 100644 --- a/tests/ui/parser/label-after-block-like.stderr +++ b/tests/ui/parser/label-after-block-like.stderr @@ -23,7 +23,7 @@ note: the `if` expression is missing a block after this condition | LL | if let () = () 'a {} | ^^^^^^^^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | if let () = () { 'a {} } | + + @@ -53,7 +53,7 @@ note: the `if` expression is missing a block after this condition | LL | if true 'a {} | ^^^^ -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | if true { 'a {} } | + + @@ -80,7 +80,7 @@ LL | loop 'a {} | | | while parsing this `loop` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | loop { 'a {} } | + + @@ -108,7 +108,7 @@ LL | while true 'a {} | | this `while` condition successfully parsed | while parsing the body of this `while` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | while true { 'a {} } | + + @@ -136,7 +136,7 @@ LL | while let () = () 'a {} | | this `while` condition successfully parsed | while parsing the body of this `while` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | while let () = () { 'a {} } | + + @@ -161,7 +161,7 @@ error: expected `{`, found `'a` LL | for _ in 0..0 'a {} | ^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | for _ in 0..0 { 'a {} } | + + @@ -188,7 +188,7 @@ LL | unsafe 'a {} | | | while parsing this `unsafe` expression | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | unsafe { 'a {} } | + + diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.fixed b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.fixed new file mode 100644 index 00000000000..ea9dc4cf6cc --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.fixed @@ -0,0 +1,39 @@ +//@ run-rustfix +#![allow(dead_code)] +fn main() { + for _ in [1, 2, 3].iter().map(|x| x) {} + //~^ ERROR expected `{`, found `map` + //~| HELP you might have meant to write a method call +} +fn foo5() { + let x = (vec![1, 2, 3],); + for _ in x.0 {} + //~^ ERROR expected `{`, found `0` + //~| HELP you might have meant to write a field access +} +fn foo6() { + let x = ((vec![1, 2, 3],),); + for _ in x.0.0 {} + //~^ ERROR expected `{`, found `0.0` + //~| HELP you might have meant to write a field access +} +fn foo7() { + let x = Some(vec![1, 2, 3]); + for _ in x.unwrap() {} + //~^ ERROR expected `{`, found `unwrap` + //~| HELP you might have meant to write a method call +} +fn foo8() { + let x = S { a: A { b: vec![1, 2, 3] } }; + for _ in x.a.b {} + //~^ ERROR expected `{`, found `a` + //~| HELP you might have meant to write a field access +} + +struct S { + a: A, +} + +struct A { + b: Vec, +} diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.rs b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.rs new file mode 100644 index 00000000000..1833f458a8a --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.rs @@ -0,0 +1,39 @@ +//@ run-rustfix +#![allow(dead_code)] +fn main() { + for _ in [1, 2, 3].iter()map(|x| x) {} + //~^ ERROR expected `{`, found `map` + //~| HELP you might have meant to write a method call +} +fn foo5() { + let x = (vec![1, 2, 3],); + for _ in x 0 {} + //~^ ERROR expected `{`, found `0` + //~| HELP you might have meant to write a field access +} +fn foo6() { + let x = ((vec![1, 2, 3],),); + for _ in x 0.0 {} + //~^ ERROR expected `{`, found `0.0` + //~| HELP you might have meant to write a field access +} +fn foo7() { + let x = Some(vec![1, 2, 3]); + for _ in x unwrap() {} + //~^ ERROR expected `{`, found `unwrap` + //~| HELP you might have meant to write a method call +} +fn foo8() { + let x = S { a: A { b: vec![1, 2, 3] } }; + for _ in x a.b {} + //~^ ERROR expected `{`, found `a` + //~| HELP you might have meant to write a field access +} + +struct S { + a: A, +} + +struct A { + b: Vec, +} diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.stderr b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.stderr new file mode 100644 index 00000000000..87f76efffa6 --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression-fixable.stderr @@ -0,0 +1,57 @@ +error: expected `{`, found `map` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:4:30 + | +LL | for _ in [1, 2, 3].iter()map(|x| x) {} + | ^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in [1, 2, 3].iter().map(|x| x) {} + | + + +error: expected `{`, found `0` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:10:16 + | +LL | for _ in x 0 {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0 {} + | + + +error: expected `{`, found `0.0` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:16:16 + | +LL | for _ in x 0.0 {} + | ^^^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0.0 {} + | + + +error: expected `{`, found `unwrap` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:22:16 + | +LL | for _ in x unwrap() {} + | ^^^^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in x.unwrap() {} + | + + +error: expected `{`, found `a` + --> $DIR/missing-dot-on-if-condition-expression-fixable.rs:28:16 + | +LL | for _ in x a.b {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.a.b {} + | + + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs new file mode 100644 index 00000000000..c4a9ed66a83 --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.rs @@ -0,0 +1,57 @@ +fn main() { + for _ in [1, 2, 3].iter()map(|x| x) {} + //~^ ERROR expected `{`, found `map` + //~| HELP you might have meant to write a method call +} +fn foo1() { + for _ in 1.3f64 cos() {} + //~^ ERROR expected `{`, found `cos` + //~| HELP you might have meant to write a method call +} +fn foo2() { + for _ in 1.3 cos {} + //~^ ERROR expected `{`, found `cos` + //~| HELP you might have meant to write a field access +} +fn foo3() { + for _ in 1 cos() {} + //~^ ERROR expected `{`, found `cos` + //~| HELP you might have meant to write a method call +} +fn foo4() { + for _ in 1 cos {} + //~^ ERROR expected `{`, found `cos` + //~| HELP you might have meant to write a field access +} +fn foo5() { + let x = (vec![1, 2, 3],); + for _ in x 0 {} + //~^ ERROR expected `{`, found `0` + //~| HELP you might have meant to write a field access +} +fn foo6() { + let x = ((vec![1, 2, 3],),); + for _ in x 0.0 {} + //~^ ERROR expected `{`, found `0.0` + //~| HELP you might have meant to write a field access +} +fn foo7() { + let x = Some(vec![1, 2, 3]); + for _ in x unwrap() {} + //~^ ERROR expected `{`, found `unwrap` + //~| HELP you might have meant to write a method call +} +fn foo8() { + let x = S { a: A { b: vec![1, 2, 3] } }; + for _ in x a.b {} + //~^ ERROR expected `{`, found `a` + //~| HELP you might have meant to write a field access +} + +struct S { + a: A, +} + +struct A { + b: Vec, +} diff --git a/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr new file mode 100644 index 00000000000..bfb72b95682 --- /dev/null +++ b/tests/ui/parser/recover/missing-dot-on-if-condition-expression.stderr @@ -0,0 +1,101 @@ +error: expected `{`, found `map` + --> $DIR/missing-dot-on-if-condition-expression.rs:2:30 + | +LL | for _ in [1, 2, 3].iter()map(|x| x) {} + | ^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in [1, 2, 3].iter().map(|x| x) {} + | + + +error: expected `{`, found `cos` + --> $DIR/missing-dot-on-if-condition-expression.rs:7:21 + | +LL | for _ in 1.3f64 cos() {} + | ^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in 1.3f64.cos() {} + | + + +error: expected `{`, found `cos` + --> $DIR/missing-dot-on-if-condition-expression.rs:12:18 + | +LL | for _ in 1.3 cos {} + | ^^^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in 1.3.cos {} + | + + +error: expected `{`, found `cos` + --> $DIR/missing-dot-on-if-condition-expression.rs:17:16 + | +LL | for _ in 1 cos() {} + | ^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in 1.cos() {} + | + + +error: expected `{`, found `cos` + --> $DIR/missing-dot-on-if-condition-expression.rs:22:16 + | +LL | for _ in 1 cos {} + | ^^^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in 1.cos {} + | + + +error: expected `{`, found `0` + --> $DIR/missing-dot-on-if-condition-expression.rs:28:16 + | +LL | for _ in x 0 {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0 {} + | + + +error: expected `{`, found `0.0` + --> $DIR/missing-dot-on-if-condition-expression.rs:34:16 + | +LL | for _ in x 0.0 {} + | ^^^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.0.0 {} + | + + +error: expected `{`, found `unwrap` + --> $DIR/missing-dot-on-if-condition-expression.rs:40:16 + | +LL | for _ in x unwrap() {} + | ^^^^^^ expected `{` + | +help: you might have meant to write a method call + | +LL | for _ in x.unwrap() {} + | + + +error: expected `{`, found `a` + --> $DIR/missing-dot-on-if-condition-expression.rs:46:16 + | +LL | for _ in x a.b {} + | ^ expected `{` + | +help: you might have meant to write a field access + | +LL | for _ in x.a.b {} + | + + +error: aborting due to 9 previous errors + diff --git a/tests/ui/parser/unnecessary-let.fixed b/tests/ui/parser/unnecessary-let.fixed new file mode 100644 index 00000000000..bdee07e76aa --- /dev/null +++ b/tests/ui/parser/unnecessary-let.fixed @@ -0,0 +1,13 @@ +//@ run-rustfix + +fn main() { + for _x in [1, 2, 3] {} + //~^ ERROR expected pattern, found `let` + //~| ERROR missing `in` in `for` loop + + match 1 { + 1 => {} + //~^ ERROR expected pattern, found `let` + _ => {} + } +} diff --git a/tests/ui/parser/unnecessary-let.rs b/tests/ui/parser/unnecessary-let.rs index 6279109621d..a889d9f7789 100644 --- a/tests/ui/parser/unnecessary-let.rs +++ b/tests/ui/parser/unnecessary-let.rs @@ -1,5 +1,7 @@ +//@ run-rustfix + fn main() { - for let x of [1, 2, 3] {} + for let _x of [1, 2, 3] {} //~^ ERROR expected pattern, found `let` //~| ERROR missing `in` in `for` loop diff --git a/tests/ui/parser/unnecessary-let.stderr b/tests/ui/parser/unnecessary-let.stderr index 05ac1faafd4..0b28123747a 100644 --- a/tests/ui/parser/unnecessary-let.stderr +++ b/tests/ui/parser/unnecessary-let.stderr @@ -1,31 +1,31 @@ error: expected pattern, found `let` - --> $DIR/unnecessary-let.rs:2:9 + --> $DIR/unnecessary-let.rs:4:9 | -LL | for let x of [1, 2, 3] {} - | ^^^^ +LL | for let _x of [1, 2, 3] {} + | ^^^ | help: remove the unnecessary `let` keyword | -LL - for let x of [1, 2, 3] {} -LL + for x of [1, 2, 3] {} +LL - for let _x of [1, 2, 3] {} +LL + for _x of [1, 2, 3] {} | error: missing `in` in `for` loop - --> $DIR/unnecessary-let.rs:2:15 + --> $DIR/unnecessary-let.rs:4:16 | -LL | for let x of [1, 2, 3] {} - | ^^ +LL | for let _x of [1, 2, 3] {} + | ^^ | help: try using `in` here instead | -LL | for let x in [1, 2, 3] {} - | ~~ +LL | for let _x in [1, 2, 3] {} + | ~~ error: expected pattern, found `let` - --> $DIR/unnecessary-let.rs:7:9 + --> $DIR/unnecessary-let.rs:9:9 | LL | let 1 => {} - | ^^^^ + | ^^^ | help: remove the unnecessary `let` keyword | diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.rs b/tests/ui/pattern/usefulness/conflicting_bindings.rs index 0b3e7ce9e9a..16737e0a894 100644 --- a/tests/ui/pattern/usefulness/conflicting_bindings.rs +++ b/tests/ui/pattern/usefulness/conflicting_bindings.rs @@ -10,6 +10,8 @@ fn main() { //~^ ERROR: mutable more than once if let Some(ref mut y @ ref mut z) = x && true {} //~^ ERROR: mutable more than once + if let Some(_) = Some(()) && let Some(ref mut y @ ref mut z) = x && true {} + //~^ ERROR: mutable more than once while let Some(ref mut y @ ref mut z) = x {} //~^ ERROR: mutable more than once while let Some(ref mut y @ ref mut z) = x && true {} diff --git a/tests/ui/pattern/usefulness/conflicting_bindings.stderr b/tests/ui/pattern/usefulness/conflicting_bindings.stderr index 679fc83e7f5..6f6504e6f64 100644 --- a/tests/ui/pattern/usefulness/conflicting_bindings.stderr +++ b/tests/ui/pattern/usefulness/conflicting_bindings.stderr @@ -31,7 +31,15 @@ LL | if let Some(ref mut y @ ref mut z) = x && true {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:13:20 + --> $DIR/conflicting_bindings.rs:13:43 + | +LL | if let Some(_) = Some(()) && let Some(ref mut y @ ref mut z) = x && true {} + | ^^^^^^^^^ --------- value is mutably borrowed by `z` here + | | + | value is mutably borrowed by `y` here + +error: cannot borrow value as mutable more than once at a time + --> $DIR/conflicting_bindings.rs:15:20 | LL | while let Some(ref mut y @ ref mut z) = x {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -39,7 +47,7 @@ LL | while let Some(ref mut y @ ref mut z) = x {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:15:20 + --> $DIR/conflicting_bindings.rs:17:20 | LL | while let Some(ref mut y @ ref mut z) = x && true {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -47,7 +55,7 @@ LL | while let Some(ref mut y @ ref mut z) = x && true {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:18:9 + --> $DIR/conflicting_bindings.rs:20:9 | LL | ref mut y @ ref mut z => {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here @@ -55,12 +63,12 @@ LL | ref mut y @ ref mut z => {} | value is mutably borrowed by `y` here error: cannot borrow value as mutable more than once at a time - --> $DIR/conflicting_bindings.rs:21:24 + --> $DIR/conflicting_bindings.rs:23:24 | LL | () if let Some(ref mut y @ ref mut z) = x => {} | ^^^^^^^^^ --------- value is mutably borrowed by `z` here | | | value is mutably borrowed by `y` here -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs index 5c333cd7795..47653efffb7 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.rs @@ -94,4 +94,15 @@ fn use_in_arm_ok(c: bool) { }; } +fn use_in_same_chain(c: bool) { + let x: Box<_> = Box::new(1); + + let v = (1, 2); + + match v { + (1, 2) if let y = x && c && let z = x => false, //~ ERROR use of moved value: `x` + _ => true, + }; +} + fn main() {} diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr index 087e54244b3..123c5f19430 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/move-guard-if-let-chain.stderr @@ -60,6 +60,22 @@ help: borrow this binding in the pattern to avoid moving the value LL | (1, 2) if let ref y = x && c => false, | +++ -error: aborting due to 4 previous errors +error[E0382]: use of moved value: `x` + --> $DIR/move-guard-if-let-chain.rs:103:41 + | +LL | let x: Box<_> = Box::new(1); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +... +LL | (1, 2) if let y = x && c && let z = x => false, + | - ^ value used here after move + | | + | value moved here + | +help: borrow this binding in the pattern to avoid moving the value + | +LL | (1, 2) if let ref y = x && c && let z = x => false, + | +++ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/temporary-early-drop.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/temporary-early-drop.rs new file mode 100644 index 00000000000..389c76337f0 --- /dev/null +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/temporary-early-drop.rs @@ -0,0 +1,25 @@ +// issue-103476 +//@ compile-flags: -Zlint-mir -Zunstable-options +//@ edition: 2024 +//@ check-pass + +#![feature(let_chains)] +#![allow(irrefutable_let_patterns)] + +struct Pd; + +impl Pd { + fn it(&self) -> It { + todo!() + } +} + +pub struct It<'a>(Box>); + +trait Tr<'a> {} + +fn f(m: Option) { + if let Some(n) = m && let it = n.it() {}; +} + +fn main() {} diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs index 0183bdba111..a3b510848dc 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs @@ -1,8 +1,6 @@ -//@ ignore-apple: cycle error does not appear on apple +use std::cell::UnsafeCell; -use std::sync::Mutex; - -enum Foo { X(Mutex>) } +enum Foo { X(UnsafeCell>) } //~^ ERROR recursive type `Foo` has infinite size //~| ERROR cycle detected diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr index 22f8519d0ef..b192593d266 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr @@ -1,18 +1,18 @@ error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-6.rs:5:1 + --> $DIR/issue-17431-6.rs:3:1 | -LL | enum Foo { X(Mutex>) } - | ^^^^^^^^ --- recursive without indirection +LL | enum Foo { X(UnsafeCell>) } + | ^^^^^^^^ --- recursive without indirection | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | -LL | enum Foo { X(Mutex>>) } - | ++++ + +LL | enum Foo { X(UnsafeCell>>) } + | ++++ + error[E0391]: cycle detected when computing when `Foo` needs drop - --> $DIR/issue-17431-6.rs:5:1 + --> $DIR/issue-17431-6.rs:3:1 | -LL | enum Foo { X(Mutex>) } +LL | enum Foo { X(UnsafeCell>) } | ^^^^^^^^ | = note: ...which immediately requires computing when `Foo` needs drop again diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs index dda42580e0f..2a301788525 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.rs @@ -7,6 +7,7 @@ fn produce() -> impl for Trait<(), Assoc = impl Trait> { //~^ ERROR associated type `Assoc` not found for `Trait` //~| ERROR associated type `Assoc` not found for `Trait` //~| the trait bound `{integer}: Trait<()>` is not satisfied + //~| ERROR cannot capture late-bound type parameter in nested `impl Trait` 16 } diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr index 6e5bd34ce38..38dcdbd0af2 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr @@ -1,3 +1,9 @@ +error: cannot capture late-bound type parameter in nested `impl Trait` + --> $DIR/non-lifetime-binder-in-constraint.rs:6:58 + | +LL | fn produce() -> impl for Trait<(), Assoc = impl Trait> { + | - parameter defined here ^ + error[E0220]: associated type `Assoc` not found for `Trait` --> $DIR/non-lifetime-binder-in-constraint.rs:6:39 | @@ -27,7 +33,7 @@ help: this trait has no implementations, consider adding one LL | trait Trait {} | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0220, E0277. For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs b/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs index 23951c34270..23f3666618b 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder.rs @@ -5,6 +5,7 @@ trait Trait {} fn f() -> impl for Trait> {} //~^ ERROR nested `impl Trait` is not allowed -//~| ERROR the trait bound `(): Trait>` is not satisfied +//~| ERROR the trait bound `(): Trait>` is not satisfied +//~| ERROR cannot capture late-bound type parameter in nested `impl Trait` fn main() {} diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr b/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr index 5859d952b75..3c352c9889c 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder.stderr @@ -7,11 +7,19 @@ LL | fn f() -> impl for Trait> {} | | nested `impl Trait` here | outer `impl Trait` -error[E0277]: the trait bound `(): Trait>` is not satisfied +error: cannot capture late-bound type parameter in nested `impl Trait` + --> $DIR/non-lifetime-binder.rs:6:40 + | +LL | fn f() -> impl for Trait> {} + | - ^ + | | + | parameter defined here + +error[E0277]: the trait bound `(): Trait>` is not satisfied --> $DIR/non-lifetime-binder.rs:6:11 | LL | fn f() -> impl for Trait> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait>` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait>` is not implemented for `()` | help: this trait has no implementations, consider adding one --> $DIR/non-lifetime-binder.rs:4:1 @@ -19,7 +27,7 @@ help: this trait has no implementations, consider adding one LL | trait Trait {} | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0666. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/unsafe/unsafe-block-without-braces.stderr b/tests/ui/unsafe/unsafe-block-without-braces.stderr index d29e49d73a6..3d8234c15e7 100644 --- a/tests/ui/unsafe/unsafe-block-without-braces.stderr +++ b/tests/ui/unsafe/unsafe-block-without-braces.stderr @@ -6,7 +6,7 @@ LL | unsafe //{ LL | std::mem::transmute::(1.0); | ^^^ expected `{` | -help: try placing this code inside a block +help: you might have meant to write this as part of a block | LL | { std::mem::transmute::(1.0); } | + + diff --git a/triagebot.toml b/triagebot.toml index d5bc549ca9f..c5942fe27cd 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -997,7 +997,6 @@ compiler = [ "@oli-obk", "@petrochenkov", "@pnkfelix", - "@TaKO8Ki", "@wesleywiser", ] libs = [ @@ -1048,7 +1047,6 @@ diagnostics = [ "@davidtwco", "@estebank", "@oli-obk", - "@TaKO8Ki", "@chenyukang", ] parser = [