diff --git a/.reuse/dep5 b/.reuse/dep5 index 6c39025b5de0..06afec2b3fae 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -52,7 +52,7 @@ Copyright: 2019 The Crossbeam Project Developers The Rust Project Developers (see https://thanks.rust-lang.org) License: MIT OR Apache-2.0 -Files: library/std/src/sys/locks/mutex/fuchsia.rs +Files: library/std/src/sys/sync/mutex/fuchsia.rs Copyright: 2016 The Fuchsia Authors The Rust Project Developers (see https://thanks.rust-lang.org) License: BSD-2-Clause AND (MIT OR Apache-2.0) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 1c6d0495ecfa..3584eea0f149 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -816,15 +816,37 @@ where break; } }; - if let Some(pair) = common_prim { - // This is pretty conservative. We could go fancier - // by conflating things like i32 and u32, or even - // realising that (u8, u8) could just cohabit with - // u16 or even u32. - if pair != (prim, offset) { + if let Some((old_prim, common_offset)) = common_prim { + // All variants must be at the same offset + if offset != common_offset { common_prim = None; break; } + // This is pretty conservative. We could go fancier + // by realising that (u8, u8) could just cohabit with + // u16 or even u32. + let new_prim = match (old_prim, prim) { + // Allow all identical primitives. + (x, y) if x == y => x, + // Allow integers of the same size with differing signedness. + // We arbitrarily choose the signedness of the first variant. + (p @ Primitive::Int(x, _), Primitive::Int(y, _)) if x == y => p, + // Allow integers mixed with pointers of the same layout. + // We must represent this using a pointer, to avoid + // roundtripping pointers through ptrtoint/inttoptr. + (p @ Primitive::Pointer(_), i @ Primitive::Int(..)) + | (i @ Primitive::Int(..), p @ Primitive::Pointer(_)) + if p.size(dl) == i.size(dl) && p.align(dl) == i.align(dl) => + { + p + } + _ => { + common_prim = None; + break; + } + }; + // We may be updating the primitive here, for example from int->ptr. + common_prim = Some((new_prim, common_offset)); } else { common_prim = Some((prim, offset)); } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index d522c285e3eb..d0e8b86b71d3 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1021,7 +1021,7 @@ impl Stmt { #[derive(Clone, Encodable, Decodable, Debug)] pub enum StmtKind { /// A local (let) binding. - Local(P), + Let(P), /// An item definition. Item(P), /// Expr without trailing semi-colon. diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 4dc9c30a2c80..a0486227f2af 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -182,7 +182,7 @@ impl HasTokens for Option { impl HasTokens for StmtKind { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { - StmtKind::Local(local) => local.tokens.as_ref(), + StmtKind::Let(local) => local.tokens.as_ref(), StmtKind::Item(item) => item.tokens(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens(), StmtKind::Empty => return None, @@ -191,7 +191,7 @@ impl HasTokens for StmtKind { } fn tokens_mut(&mut self) -> Option<&mut Option> { match self { - StmtKind::Local(local) => Some(&mut local.tokens), + StmtKind::Let(local) => Some(&mut local.tokens), StmtKind::Item(item) => item.tokens_mut(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens_mut(), StmtKind::Empty => return None, @@ -355,7 +355,7 @@ impl HasAttrs for StmtKind { fn attrs(&self) -> &[Attribute] { match self { - StmtKind::Local(local) => &local.attrs, + StmtKind::Let(local) => &local.attrs, StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(), StmtKind::Item(item) => item.attrs(), StmtKind::Empty => &[], @@ -365,7 +365,7 @@ impl HasAttrs for StmtKind { fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { match self { - StmtKind::Local(local) => f(&mut local.attrs), + StmtKind::Let(local) => f(&mut local.attrs), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), StmtKind::Item(item) => item.visit_attrs(f), StmtKind::Empty => {} diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 9ec92c9d4edf..83468c5f1012 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1567,7 +1567,7 @@ pub fn noop_flat_map_stmt_kind( vis: &mut T, ) -> SmallVec<[StmtKind; 1]> { match kind { - StmtKind::Local(mut local) => smallvec![StmtKind::Local({ + StmtKind::Let(mut local) => smallvec![StmtKind::Let({ vis.visit_local(&mut local); local })], diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 7296e29301f3..d75ff4565e6f 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -787,7 +787,7 @@ pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::R pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { match &statement.kind { - StmtKind::Local(local) => try_visit!(visitor.visit_local(local)), + StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), StmtKind::Empty => {} diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index cef50a70534c..666e7763e627 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -196,7 +196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .get_partial_res(sym.id) .and_then(|res| res.full_res()) .and_then(|res| match res { - Res::Def(DefKind::Static(_), def_id) => Some(def_id), + Res::Def(DefKind::Static { .. }, def_id) => Some(def_id), _ => None, }); diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 865a56b2c1f1..11a66fe87c9a 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -32,11 +32,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut expr = None; while let [s, tail @ ..] = ast_stmts { match &s.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { let hir_id = self.lower_node_id(s.id); let local = self.lower_local(local); self.alias_attrs(hir_id, local.hir_id); - let kind = hir::StmtKind::Local(local); + let kind = hir::StmtKind::Let(local); let span = self.lower_span(s.span); stmts.push(hir::Stmt { hir_id, kind, span }); } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 94e1e06a9545..e8ff64a7fd2c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2356,7 +2356,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: self.lower_span(span), ty: None, }; - self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local))) + self.stmt(span, hir::StmtKind::Let(self.arena.alloc(local))) } fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> &'hir hir::Block<'hir> { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e5d7b8489033..c50878e32a46 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1212,7 +1212,7 @@ impl<'a> State<'a> { fn print_stmt(&mut self, st: &ast::Stmt) { self.maybe_print_comment(st.span.lo()); match &st.kind { - ast::StmtKind::Local(loc) => { + ast::StmtKind::Let(loc) => { self.print_outer_attributes(&loc.attrs); self.space_if_not_bol(); self.ibox(INDENT_UNIT); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 0776f455efd9..5af70937f622 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -616,7 +616,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // FIXME: We make sure that this is a normal top-level binding, // but we could suggest `todo!()` for all uninitalized bindings in the pattern pattern - if let hir::StmtKind::Local(hir::Local { span, ty, init: None, pat, .. }) = + if let hir::StmtKind::Let(hir::Local { span, ty, init: None, pat, .. }) = &ex.kind && let hir::PatKind::Binding(..) = pat.kind && span.contains(self.decl_span) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index ebc9f1d109ee..ee2e3d20fe56 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -558,7 +558,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { hir::intravisit::walk_stmt(self, stmt); let expr = match stmt.kind { hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr, - hir::StmtKind::Local(hir::Local { init: Some(expr), .. }) => expr, + hir::StmtKind::Let(hir::Local { init: Some(expr), .. }) => expr, _ => { return; } @@ -1305,7 +1305,7 @@ struct BindingFinder { impl<'tcx> Visitor<'tcx> for BindingFinder { type Result = ControlFlow; fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result { - if let hir::StmtKind::Local(local) = s.kind + if let hir::StmtKind::Let(local) = s.kind && local.pat.span == self.span { ControlFlow::Break(local.hir_id) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index bc851fadc2e2..62c02817011f 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -5,7 +5,7 @@ use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_errors::PResult; -use rustc_expand::base::{self, *}; +use rustc_expand::base::*; use rustc_index::bit_set::GrowableBitSet; use rustc_parse::parser::Parser; use rustc_parse_format as parse; @@ -443,7 +443,7 @@ fn parse_reg<'a>( fn expand_preparsed_asm( ecx: &mut ExtCtxt<'_>, args: AsmArgs, -) -> Result { +) -> ExpandResult, ()> { let mut template = vec![]; // Register operands are implicitly used since they are not allowed to be // referenced in the template string. @@ -465,16 +465,20 @@ fn expand_preparsed_asm( let msg = "asm template must be a string literal"; let template_sp = template_expr.span; - let (template_str, template_style, template_span) = - match expr_to_spanned_string(ecx, template_expr, msg) { + let (template_str, template_style, template_span) = { + let ExpandResult::Ready(mac) = expr_to_spanned_string(ecx, template_expr, msg) else { + return ExpandResult::Retry(()); + }; + match mac { Ok(template_part) => template_part, Err(err) => { - return Err(match err { + return ExpandResult::Ready(Err(match err { Ok((err, _)) => err.emit(), Err(guar) => guar, - }); + })); } - }; + } + }; let str_style = match template_style { ast::StrStyle::Cooked => None, @@ -562,7 +566,7 @@ fn expand_preparsed_asm( e.span_label(err_sp, label); } let guar = e.emit(); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } curarg = parser.curarg; @@ -729,24 +733,27 @@ fn expand_preparsed_asm( } } - Ok(ast::InlineAsm { + ExpandResult::Ready(Ok(ast::InlineAsm { template, template_strs: template_strs.into_boxed_slice(), operands: args.operands, clobber_abis: args.clobber_abis, options: args.options, line_spans, - }) + })) } pub(super) fn expand_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - match parse_args(ecx, sp, tts, false) { +) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(match parse_args(ecx, sp, tts, false) { Ok(args) => { - let expr = match expand_preparsed_asm(ecx, args) { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + return ExpandResult::Retry(()); + }; + let expr = match mac { Ok(inline_asm) => P(ast::Expr { id: ast::DUMMY_NODE_ID, kind: ast::ExprKind::InlineAsm(P(inline_asm)), @@ -762,34 +769,39 @@ pub(super) fn expand_asm<'cx>( let guar = err.emit(); DummyResult::any(sp, guar) } - } + }) } pub(super) fn expand_global_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - match parse_args(ecx, sp, tts, true) { - Ok(args) => match expand_preparsed_asm(ecx, args) { - Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item { - ident: Ident::empty(), - attrs: ast::AttrVec::new(), - id: ast::DUMMY_NODE_ID, - kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), - vis: ast::Visibility { - span: sp.shrink_to_lo(), - kind: ast::VisibilityKind::Inherited, +) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(match parse_args(ecx, sp, tts, true) { + Ok(args) => { + let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else { + return ExpandResult::Retry(()); + }; + match mac { + Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item { + ident: Ident::empty(), + attrs: ast::AttrVec::new(), + id: ast::DUMMY_NODE_ID, + kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), + vis: ast::Visibility { + span: sp.shrink_to_lo(), + kind: ast::VisibilityKind::Inherited, + tokens: None, + }, + span: sp, tokens: None, - }, - span: sp, - tokens: None, - })]), - Err(guar) => DummyResult::any(sp, guar), - }, + })]), + Err(guar) => DummyResult::any(sp, guar), + } + } Err(err) => { let guar = err.emit(); DummyResult::any(sp, guar) } - } + }) } diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 613ce43dec2d..35a0857fe51c 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -9,7 +9,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp}; use rustc_ast_pretty::pprust; use rustc_errors::PResult; -use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_parse::parser::Parser; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -19,12 +19,12 @@ pub fn expand_assert<'cx>( cx: &'cx mut ExtCtxt<'_>, span: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) { Ok(assert) => assert, Err(err) => { let guar = err.emit(); - return DummyResult::any(span, guar); + return ExpandResult::Ready(DummyResult::any(span, guar)); } }; @@ -92,7 +92,7 @@ pub fn expand_assert<'cx>( expr_if_not(cx, call_site_span, cond_expr, then, None) }; - MacEager::expr(expr) + ExpandResult::Ready(MacEager::expr(expr)) } struct Assert { diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 04bf7dceeff4..9197b9ebdf9f 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -8,17 +8,17 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_attr as attr; use rustc_errors::PResult; -use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::Span; pub fn expand_cfg( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); - match parse_cfg(cx, sp, tts) { + ExpandResult::Ready(match parse_cfg(cx, sp, tts) { Ok(cfg) => { let matches_cfg = attr::cfg_matches( &cfg, @@ -32,7 +32,7 @@ pub fn expand_cfg( let guar = err.emit(); DummyResult::any(sp, guar) } - } + }) } fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> { diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs index b4455d7823f3..2f2a87fc9aa0 100644 --- a/compiler/rustc_builtin_macros/src/compile_error.rs +++ b/compiler/rustc_builtin_macros/src/compile_error.rs @@ -1,22 +1,26 @@ // The compiler code necessary to support the compile_error! extension. use rustc_ast::tokenstream::TokenStream; -use rustc_expand::base::{get_single_str_from_tts, DummyResult, ExtCtxt, MacResult}; +use rustc_expand::base::get_single_str_from_tts; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_span::Span; pub fn expand_compile_error<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { +) -> MacroExpanderResult<'cx> { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "compile_error!") else { + return ExpandResult::Retry(()); + }; + let var = match mac { Ok(var) => var, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; #[expect(rustc::diagnostic_outside_of_impl, reason = "diagnostic message is specified by user")] #[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")] let guar = cx.dcx().span_err(sp, var.to_string()); - DummyResult::any(sp, guar) + ExpandResult::Ready(DummyResult::any(sp, guar)) } diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index 0bfb848859bd..93a7ac05a9be 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -1,6 +1,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ExprKind, LitKind, UnOp}; -use rustc_expand::base::{get_exprs_from_tts, DummyResult, ExtCtxt, MacEager, MacResult}; +use rustc_expand::base::get_exprs_from_tts; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_session::errors::report_lit_error; use rustc_span::symbol::Symbol; @@ -10,10 +11,13 @@ pub fn expand_concat( cx: &mut ExtCtxt<'_>, sp: rustc_span::Span, tts: TokenStream, -) -> Box { - let es = match get_exprs_from_tts(cx, tts) { +) -> MacroExpanderResult<'static> { + let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else { + return ExpandResult::Retry(()); + }; + let es = match mac { Ok(es) => es, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let mut accumulator = String::new(); let mut missing_literal = vec![]; @@ -70,12 +74,13 @@ pub fn expand_concat( } } - if !missing_literal.is_empty() { + ExpandResult::Ready(if !missing_literal.is_empty() { let guar = cx.dcx().emit_err(errors::ConcatMissingLiteral { spans: missing_literal }); - return DummyResult::any(sp, guar); + DummyResult::any(sp, guar) } else if let Some(guar) = guar { - return DummyResult::any(sp, guar); - } - let sp = cx.with_def_site_ctxt(sp); - MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) + DummyResult::any(sp, guar) + } else { + let sp = cx.with_def_site_ctxt(sp); + MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator))) + }) } diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 502bfb4467e5..a2f827c5567d 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -1,5 +1,6 @@ use rustc_ast::{ptr::P, token, tokenstream::TokenStream, ExprKind, LitIntType, LitKind, UintTy}; -use rustc_expand::base::{get_exprs_from_tts, DummyResult, ExtCtxt, MacEager, MacResult}; +use rustc_expand::base::get_exprs_from_tts; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_session::errors::report_lit_error; use rustc_span::{ErrorGuaranteed, Span}; @@ -111,10 +112,13 @@ pub fn expand_concat_bytes( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - let es = match get_exprs_from_tts(cx, tts) { +) -> MacroExpanderResult<'static> { + let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else { + return ExpandResult::Retry(()); + }; + let es = match mac { Ok(es) => es, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let mut accumulator = Vec::new(); let mut missing_literals = vec![]; @@ -170,12 +174,13 @@ pub fn expand_concat_bytes( } } } - if !missing_literals.is_empty() { + ExpandResult::Ready(if !missing_literals.is_empty() { let guar = cx.dcx().emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals }); - return MacEager::expr(DummyResult::raw_expr(sp, Some(guar))); + MacEager::expr(DummyResult::raw_expr(sp, Some(guar))) } else if let Some(guar) = guar { - return MacEager::expr(DummyResult::raw_expr(sp, Some(guar))); - } - let sp = cx.with_def_site_ctxt(sp); - MacEager::expr(cx.expr_byte_str(sp, accumulator)) + MacEager::expr(DummyResult::raw_expr(sp, Some(guar))) + } else { + let sp = cx.with_def_site_ctxt(sp); + MacEager::expr(cx.expr_byte_str(sp, accumulator)) + }) } diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs index fffcddc5325b..3ddb0ae45b51 100644 --- a/compiler/rustc_builtin_macros/src/concat_idents.rs +++ b/compiler/rustc_builtin_macros/src/concat_idents.rs @@ -2,7 +2,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Token}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::{AttrVec, Expr, ExprKind, Path, Ty, TyKind, DUMMY_NODE_ID}; -use rustc_expand::base::{DummyResult, ExtCtxt, MacResult}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult}; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::Span; @@ -12,10 +12,10 @@ pub fn expand_concat_idents<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { if tts.is_empty() { let guar = cx.dcx().emit_err(errors::ConcatIdentsMissingArgs { span: sp }); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } let mut res_str = String::new(); @@ -25,7 +25,7 @@ pub fn expand_concat_idents<'cx>( TokenTree::Token(Token { kind: token::Comma, .. }, _) => {} _ => { let guar = cx.dcx().emit_err(errors::ConcatIdentsMissingComma { span: sp }); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } } } else { @@ -37,7 +37,7 @@ pub fn expand_concat_idents<'cx>( } let guar = cx.dcx().emit_err(errors::ConcatIdentsIdentArgs { span: sp }); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } } @@ -68,5 +68,5 @@ pub fn expand_concat_idents<'cx>( } } - Box::new(ConcatIdentsResult { ident }) + ExpandResult::Ready(Box::new(ConcatIdentsResult { ident })) } diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs index 1e1dadab4806..fa22e9116423 100644 --- a/compiler/rustc_builtin_macros/src/edition_panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -20,7 +20,7 @@ pub fn expand_panic<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let mac = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 }; expand(mac, cx, sp, tts) } @@ -33,7 +33,7 @@ pub fn expand_unreachable<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let mac = if use_panic_2021(sp) { sym::unreachable_2021 } else { sym::unreachable_2015 }; expand(mac, cx, sp, tts) } @@ -43,10 +43,10 @@ fn expand<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let sp = cx.with_call_site_ctxt(sp); - MacEager::expr( + ExpandResult::Ready(MacEager::expr( cx.expr( sp, ExprKind::MacCall(P(MacCall { @@ -66,7 +66,7 @@ fn expand<'cx>( }), })), ), - ) + )) } pub fn use_panic_2021(mut span: Span) -> bool { diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 193b38a83238..bce710e5cab1 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -6,10 +6,8 @@ use rustc_ast::token::{self, LitKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AstDeref, ExprKind, GenericArg, Mutability}; -use rustc_expand::base::{ - expr_to_string, get_exprs_from_tts, get_single_str_from_tts, DummyResult, ExtCtxt, MacEager, - MacResult, -}; +use rustc_expand::base::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::env; @@ -31,10 +29,13 @@ pub fn expand_option_env<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { +) -> MacroExpanderResult<'cx> { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "option_env!") else { + return ExpandResult::Retry(()); + }; + let var = match mac { Ok(var) => var, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let sp = cx.with_def_site_ctxt(sp); @@ -61,35 +62,48 @@ pub fn expand_option_env<'cx>( thin_vec![cx.expr_str(sp, value)], ), }; - MacEager::expr(e) + ExpandResult::Ready(MacEager::expr(e)) } pub fn expand_env<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { - let mut exprs = match get_exprs_from_tts(cx, tts) { +) -> MacroExpanderResult<'cx> { + let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else { + return ExpandResult::Retry(()); + }; + let mut exprs = match mac { Ok(exprs) if exprs.is_empty() || exprs.len() > 2 => { let guar = cx.dcx().emit_err(errors::EnvTakesArgs { span: sp }); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), Ok(exprs) => exprs.into_iter(), }; let var_expr = exprs.next().unwrap(); - let var = match expr_to_string(cx, var_expr.clone(), "expected string literal") { + let ExpandResult::Ready(mac) = expr_to_string(cx, var_expr.clone(), "expected string literal") + else { + return ExpandResult::Retry(()); + }; + let var = match mac { Ok((var, _)) => var, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let custom_msg = match exprs.next() { None => None, - Some(second) => match expr_to_string(cx, second, "expected string literal") { - Ok((s, _)) => Some(s), - Err(guar) => return DummyResult::any(sp, guar), - }, + Some(second) => { + let ExpandResult::Ready(mac) = expr_to_string(cx, second, "expected string literal") + else { + return ExpandResult::Retry(()); + }; + match mac { + Ok((s, _)) => Some(s), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), + } + } }; let span = cx.with_def_site_ctxt(sp); @@ -120,11 +134,11 @@ pub fn expand_env<'cx>( }) }; - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } Some(value) => cx.expr_str(span, value), }; - MacEager::expr(e) + ExpandResult::Ready(MacEager::expr(e)) } /// Returns `true` if an environment variable from `env!` is one used by Cargo. diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 385c90ff14b2..6f031f270cae 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -9,7 +9,7 @@ use rustc_ast::{ }; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans}; -use rustc_expand::base::{self, *}; +use rustc_expand::base::*; use rustc_parse::parser::Recovered; use rustc_parse_format as parse; use rustc_span::symbol::{Ident, Symbol}; @@ -40,6 +40,7 @@ use PositionUsedAs::*; use crate::errors; +#[derive(Debug)] struct MacroInput { fmtstr: P, args: FormatArguments, @@ -160,54 +161,61 @@ fn make_format_args( ecx: &mut ExtCtxt<'_>, input: MacroInput, append_newline: bool, -) -> Result { +) -> ExpandResult, ()> { let msg = "format argument must be a string literal"; let unexpanded_fmt_span = input.fmtstr.span; let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input; - let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt.clone(), msg) { - Ok(mut fmt) if append_newline => { - fmt.0 = Symbol::intern(&format!("{}\n", fmt.0)); - fmt - } - Ok(fmt) => fmt, - Err(err) => { - let guar = match err { - Ok((mut err, suggested)) => { - if !suggested { - if let ExprKind::Block(block, None) = &efmt.kind - && block.stmts.len() == 1 - && let StmtKind::Expr(expr) = &block.stmts[0].kind - && let ExprKind::Path(None, path) = &expr.kind - && path.is_potential_trivial_const_arg() - { - err.multipart_suggestion( - "quote your inlined format argument to use as string literal", - vec![ - (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()), - (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()), - ], - Applicability::MaybeIncorrect, - ); - } else { - let sugg_fmt = match args.explicit_args().len() { - 0 => "{}".to_string(), - _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())), - }; - err.span_suggestion( - unexpanded_fmt_span.shrink_to_lo(), - "you might be missing a string literal to format with", - format!("\"{sugg_fmt}\", "), - Applicability::MaybeIncorrect, - ); + let (fmt_str, fmt_style, fmt_span) = { + let ExpandResult::Ready(mac) = expr_to_spanned_string(ecx, efmt.clone(), msg) else { + return ExpandResult::Retry(()); + }; + match mac { + Ok(mut fmt) if append_newline => { + fmt.0 = Symbol::intern(&format!("{}\n", fmt.0)); + fmt + } + Ok(fmt) => fmt, + Err(err) => { + let guar = match err { + Ok((mut err, suggested)) => { + if !suggested { + if let ExprKind::Block(block, None) = &efmt.kind + && block.stmts.len() == 1 + && let StmtKind::Expr(expr) = &block.stmts[0].kind + && let ExprKind::Path(None, path) = &expr.kind + && path.is_potential_trivial_const_arg() + { + err.multipart_suggestion( + "quote your inlined format argument to use as string literal", + vec![ + (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()), + (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()), + ], + Applicability::MaybeIncorrect, + ); + } else { + let sugg_fmt = match args.explicit_args().len() { + 0 => "{}".to_string(), + _ => { + format!("{}{{}}", "{} ".repeat(args.explicit_args().len())) + } + }; + err.span_suggestion( + unexpanded_fmt_span.shrink_to_lo(), + "you might be missing a string literal to format with", + format!("\"{sugg_fmt}\", "), + Applicability::MaybeIncorrect, + ); + } } + err.emit() } - err.emit() - } - Err(guar) => guar, - }; - return Err(guar); + Err(guar) => guar, + }; + return ExpandResult::Ready(Err(guar)); + } } }; @@ -297,7 +305,7 @@ fn make_format_args( } } let guar = ecx.dcx().emit_err(e); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } let to_span = |inner_span: rustc_parse_format::InnerSpan| { @@ -564,7 +572,7 @@ fn make_format_args( } } - Ok(FormatArgs { span: fmt_span, template, arguments: args }) + ExpandResult::Ready(Ok(FormatArgs { span: fmt_span, template, arguments: args })) } fn invalid_placeholder_type_error( @@ -972,25 +980,32 @@ fn expand_format_args_impl<'cx>( mut sp: Span, tts: TokenStream, nl: bool, -) -> Box { +) -> MacroExpanderResult<'cx> { sp = ecx.with_def_site_ctxt(sp); - match parse_args(ecx, sp, tts) { - Ok(input) => match make_format_args(ecx, input, nl) { - Ok(format_args) => MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args)))), - Err(guar) => MacEager::expr(DummyResult::raw_expr(sp, Some(guar))), - }, + ExpandResult::Ready(match parse_args(ecx, sp, tts) { + Ok(input) => { + let ExpandResult::Ready(mac) = make_format_args(ecx, input, nl) else { + return ExpandResult::Retry(()); + }; + match mac { + Ok(format_args) => { + MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args)))) + } + Err(guar) => MacEager::expr(DummyResult::raw_expr(sp, Some(guar))), + } + } Err(err) => { let guar = err.emit(); DummyResult::any(sp, guar) } - } + }) } pub fn expand_format_args<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { expand_format_args_impl(ecx, sp, tts, false) } @@ -998,6 +1013,6 @@ pub fn expand_format_args_nl<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { expand_format_args_impl(ecx, sp, tts, true) } diff --git a/compiler/rustc_builtin_macros/src/log_syntax.rs b/compiler/rustc_builtin_macros/src/log_syntax.rs index ede34a761258..288a475ac241 100644 --- a/compiler/rustc_builtin_macros/src/log_syntax.rs +++ b/compiler/rustc_builtin_macros/src/log_syntax.rs @@ -1,14 +1,14 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; -use rustc_expand::base; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; pub fn expand_log_syntax<'cx>( - _cx: &'cx mut base::ExtCtxt<'_>, + _cx: &'cx mut ExtCtxt<'_>, sp: rustc_span::Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { println!("{}", pprust::tts_to_string(&tts)); // any so that `log_syntax` can be invoked as an expression and item. - base::DummyResult::any_valid(sp) + ExpandResult::Ready(DummyResult::any_valid(sp)) } diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 2da9bda19e03..dbb86df6811d 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -3,10 +3,9 @@ use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; -use rustc_expand::base::{ - check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path, DummyResult, ExtCtxt, - MacEager, MacResult, -}; +use rustc_expand::base::{check_zero_tts, get_single_str_from_tts, parse_expr, resolve_path}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt}; +use rustc_expand::base::{MacEager, MacResult, MacroExpanderResult}; use rustc_expand::module::DirOwnership; use rustc_parse::new_parser_from_file; use rustc_parse::parser::{ForceCollect, Parser}; @@ -26,14 +25,14 @@ pub fn expand_line( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "line!"); let topmost = cx.expansion_cause().unwrap_or(sp); let loc = cx.source_map().lookup_char_pos(topmost.lo()); - MacEager::expr(cx.expr_u32(topmost, loc.line as u32)) + ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.line as u32))) } /* column!(): expands to the current column number */ @@ -41,14 +40,14 @@ pub fn expand_column( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "column!"); let topmost = cx.expansion_cause().unwrap_or(sp); let loc = cx.source_map().lookup_char_pos(topmost.lo()); - MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1)) + ExpandResult::Ready(MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32 + 1))) } /// file!(): expands to the current filename */ @@ -58,7 +57,7 @@ pub fn expand_file( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "file!"); @@ -66,35 +65,35 @@ pub fn expand_file( let loc = cx.source_map().lookup_char_pos(topmost.lo()); use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt}; - MacEager::expr(cx.expr_str( + ExpandResult::Ready(MacEager::expr(cx.expr_str( topmost, Symbol::intern( &loc.file.name.for_scope(cx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(), ), - )) + ))) } pub fn expand_stringify( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); let s = pprust::tts_to_string(&tts); - MacEager::expr(cx.expr_str(sp, Symbol::intern(&s))) + ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))) } pub fn expand_mod( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); check_zero_tts(cx, sp, tts, "module_path!"); let mod_path = &cx.current_expansion.module.mod_path; let string = mod_path.iter().map(|x| x.to_string()).collect::>().join("::"); - MacEager::expr(cx.expr_str(sp, Symbol::intern(&string))) + ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&string)))) } /// include! : parse the given file as an expr @@ -104,18 +103,21 @@ pub fn expand_include<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'cx> { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include!") { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include!") else { + return ExpandResult::Retry(()); + }; + let file = match mac { Ok(file) => file, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; // The file will be added to the code map by the parser let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { let guar = err.emit(); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; let p = new_parser_from_file(cx.psess(), &file, Some(sp)); @@ -128,12 +130,12 @@ pub fn expand_include<'cx>( cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path)); cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None }; - struct ExpandResult<'a> { + struct ExpandInclude<'a> { p: Parser<'a>, node_id: ast::NodeId, } - impl<'a> MacResult for ExpandResult<'a> { - fn make_expr(mut self: Box>) -> Option> { + impl<'a> MacResult for ExpandInclude<'a> { + fn make_expr(mut self: Box>) -> Option> { let expr = parse_expr(&mut self.p).ok()?; if self.p.token != token::Eof { self.p.psess.buffer_lint( @@ -146,7 +148,7 @@ pub fn expand_include<'cx>( Some(expr) } - fn make_items(mut self: Box>) -> Option; 1]>> { + fn make_items(mut self: Box>) -> Option; 1]>> { let mut ret = SmallVec::new(); loop { match self.p.parse_item(ForceCollect::No) { @@ -170,7 +172,7 @@ pub fn expand_include<'cx>( } } - Box::new(ExpandResult { p, node_id: cx.current_expansion.lint_node_id }) + ExpandResult::Ready(Box::new(ExpandInclude { p, node_id: cx.current_expansion.lint_node_id })) } /// `include_str!`: read the given file, insert it as a literal string expr @@ -178,20 +180,23 @@ pub fn expand_include_str( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include_str!") else { + return ExpandResult::Retry(()); + }; + let file = match mac { Ok(file) => file, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { let guar = err.emit(); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; - match cx.source_map().load_binary_file(&file) { + ExpandResult::Ready(match cx.source_map().load_binary_file(&file) { Ok(bytes) => match std::str::from_utf8(&bytes) { Ok(src) => { let interned_src = Symbol::intern(src); @@ -206,27 +211,30 @@ pub fn expand_include_str( let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e)); DummyResult::any(sp, guar) } - } + }) } pub fn expand_include_bytes( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { + let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else { + return ExpandResult::Retry(()); + }; + let file = match mac { Ok(file) => file, - Err(guar) => return DummyResult::any(sp, guar), + Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)), }; let file = match resolve_path(&cx.sess, file.as_str(), sp) { Ok(f) => f, Err(err) => { let guar = err.emit(); - return DummyResult::any(sp, guar); + return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; - match cx.source_map().load_binary_file(&file) { + ExpandResult::Ready(match cx.source_map().load_binary_file(&file) { Ok(bytes) => { let expr = cx.expr(sp, ast::ExprKind::IncludedBytes(bytes)); MacEager::expr(expr) @@ -235,5 +243,5 @@ pub fn expand_include_bytes( let guar = cx.dcx().span_err(sp, format!("couldn't read {}: {}", file.display(), e)); DummyResult::any(sp, guar) } - } + }) } diff --git a/compiler/rustc_builtin_macros/src/trace_macros.rs b/compiler/rustc_builtin_macros/src/trace_macros.rs index e076aa6da73d..696d99004ba0 100644 --- a/compiler/rustc_builtin_macros/src/trace_macros.rs +++ b/compiler/rustc_builtin_macros/src/trace_macros.rs @@ -1,6 +1,6 @@ use crate::errors; use rustc_ast::tokenstream::{TokenStream, TokenTree}; -use rustc_expand::base::{self, ExtCtxt}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_span::symbol::kw; use rustc_span::Span; @@ -8,7 +8,7 @@ pub fn expand_trace_macros( cx: &mut ExtCtxt<'_>, sp: Span, tt: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let mut cursor = tt.trees(); let mut err = false; let value = match &cursor.next() { @@ -26,5 +26,5 @@ pub fn expand_trace_macros( cx.set_trace_macros(value); } - base::DummyResult::any_valid(sp) + ExpandResult::Ready(DummyResult::any_valid(sp)) } diff --git a/compiler/rustc_builtin_macros/src/type_ascribe.rs b/compiler/rustc_builtin_macros/src/type_ascribe.rs index e8b8fe75338c..f3e66ffc759d 100644 --- a/compiler/rustc_builtin_macros/src/type_ascribe.rs +++ b/compiler/rustc_builtin_macros/src/type_ascribe.rs @@ -2,25 +2,25 @@ use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{token, Expr, ExprKind, Ty}; use rustc_errors::PResult; -use rustc_expand::base::{self, DummyResult, ExtCtxt, MacEager}; +use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::Span; pub fn expand_type_ascribe( cx: &mut ExtCtxt<'_>, span: Span, tts: TokenStream, -) -> Box { +) -> MacroExpanderResult<'static> { let (expr, ty) = match parse_ascribe(cx, tts) { Ok(parsed) => parsed, Err(err) => { let guar = err.emit(); - return DummyResult::any(span, guar); + return ExpandResult::Ready(DummyResult::any(span, guar)); } }; let asc_expr = cx.expr(span, ExprKind::Type(expr, ty)); - return MacEager::expr(asc_expr); + ExpandResult::Ready(MacEager::expr(asc_expr)) } fn parse_ascribe<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P, P)> { diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 327c9bdada92..3d73a60b2550 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -63,7 +63,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { global_value } - fn codegen_static(&self, def_id: DefId, is_mutable: bool) { + fn codegen_static(&self, def_id: DefId) { let attrs = self.tcx.codegen_fn_attrs(def_id); let value = match codegen_static_initializer(&self, def_id) { @@ -92,7 +92,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. - if !is_mutable && self.type_is_freeze(ty) { + if !self.tcx.static_mutability(def_id).unwrap().is_mut() && self.type_is_freeze(ty) { #[cfg(feature = "master")] global.global_set_readonly(); } @@ -349,7 +349,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>( cx.const_struct(&llvals, true) } -pub fn codegen_static_initializer<'gcc, 'tcx>( +fn codegen_static_initializer<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId, ) -> Result<(RValue<'gcc>, ConstAllocation<'tcx>), ErrorHandled> { diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index e56c49686c01..359d3c70b4ca 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -1,7 +1,9 @@ #[cfg(feature = "master")] use gccjit::{FnAttribute, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineMethods; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; @@ -23,7 +25,14 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; + // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out + // the gcc type from the actual evaluated initializer. + let ty = if nested { + self.tcx.types.unit + } else { + instance.ty(self.tcx, ty::ParamEnv::reveal_all()) + }; let gcc_type = self.layout_of(ty).gcc_type(self); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index ca2e2b575805..63e59ea13fc3 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1132,9 +1132,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { &mut self, op: rustc_codegen_ssa::common::AtomicRmwBinOp, dst: &'ll Value, - src: &'ll Value, + mut src: &'ll Value, order: rustc_codegen_ssa::common::AtomicOrdering, ) -> &'ll Value { + // The only RMW operation that LLVM supports on pointers is compare-exchange. + if self.val_ty(src) == self.type_ptr() + && op != rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicXchg + { + src = self.ptrtoint(src, self.type_isize()); + } unsafe { llvm::LLVMBuildAtomicRMW( self.llbuilder, diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 8173e41aff45..25cbd90460f2 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -95,11 +95,13 @@ impl<'ll> BackendTypes for CodegenCx<'ll, '_> { impl<'ll> CodegenCx<'ll, '_> { pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { - unsafe { llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint) } + let len = u64::try_from(elts.len()).expect("LLVMConstArray2 elements len overflow"); + unsafe { llvm::LLVMConstArray2(ty, elts.as_ptr(), len) } } pub fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value { - unsafe { llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint) } + let len = c_uint::try_from(elts.len()).expect("LLVMConstVector elements len overflow"); + unsafe { llvm::LLVMConstVector(elts.as_ptr(), len) } } pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value { @@ -108,8 +110,8 @@ impl<'ll> CodegenCx<'ll, '_> { pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value { unsafe { - assert_eq!(idx as c_uint as u64, idx); - let r = llvm::LLVMGetAggregateElement(v, idx as c_uint).unwrap(); + let idx = c_uint::try_from(idx).expect("LLVMGetAggregateElement index overflow"); + let r = llvm::LLVMGetAggregateElement(v, idx).unwrap(); debug!("const_get_elt(v={:?}, idx={}, r={:?})", v, idx, r); @@ -329,7 +331,7 @@ pub fn val_ty(v: &Value) -> &Type { pub fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; - llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True) + llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), True) } } @@ -338,9 +340,8 @@ pub fn struct_in_context<'ll>( elts: &[&'ll Value], packed: bool, ) -> &'ll Value { - unsafe { - llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), elts.len() as c_uint, packed as Bool) - } + let len = c_uint::try_from(elts.len()).expect("LLVMConstStructInContext elements len overflow"); + unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), len, packed as Bool) } } #[inline] diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index ec2fb2c6e546..4afa230e598b 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -9,6 +9,7 @@ use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; use rustc_codegen_ssa::traits::*; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ @@ -17,7 +18,7 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, Instance, Ty}; +use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_session::config::Lto; use rustc_target::abi::{ @@ -114,7 +115,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation< cx.const_struct(&llvals, true) } -pub fn codegen_static_initializer<'ll, 'tcx>( +fn codegen_static_initializer<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, ) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> { @@ -147,11 +148,10 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: fn check_and_apply_linkage<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, attrs: &CodegenFnAttrs, - ty: Ty<'tcx>, + llty: &'ll Type, sym: &str, def_id: DefId, ) -> &'ll Value { - let llty = cx.layout_of(ty).llvm_type(cx); if let Some(linkage) = attrs.import_linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); @@ -226,9 +226,28 @@ impl<'ll> CodegenCx<'ll, '_> { } } + #[instrument(level = "debug", skip(self))] pub(crate) fn get_static(&self, def_id: DefId) -> &'ll Value { let instance = Instance::mono(self.tcx, def_id); - if let Some(&g) = self.instances.borrow().get(&instance) { + trace!(?instance); + + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; + // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out + // the llvm type from the actual evaluated initializer. + let llty = if nested { + self.type_i8() + } else { + let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + trace!(?ty); + self.layout_of(ty).llvm_type(self) + }; + self.get_static_inner(def_id, llty) + } + + #[instrument(level = "debug", skip(self, llty))] + pub(crate) fn get_static_inner(&self, def_id: DefId, llty: &'ll Type) -> &'ll Value { + if let Some(&g) = self.instances.borrow().get(&Instance::mono(self.tcx, def_id)) { + trace!("used cached value"); return g; } @@ -240,14 +259,12 @@ impl<'ll> CodegenCx<'ll, '_> { statics defined in the same CGU, but did not for `{def_id:?}`" ); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); - let sym = self.tcx.symbol_name(instance).name; + let sym = self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name; let fn_attrs = self.tcx.codegen_fn_attrs(def_id); - debug!("get_static: sym={} instance={:?} fn_attrs={:?}", sym, instance, fn_attrs); + debug!(?sym, ?fn_attrs); let g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) { - let llty = self.layout_of(ty).llvm_type(self); if let Some(g) = self.get_declared_value(sym) { if self.val_ty(g) != self.type_ptr() { span_bug!(self.tcx.def_span(def_id), "Conflicting types for static"); @@ -264,7 +281,7 @@ impl<'ll> CodegenCx<'ll, '_> { g } else { - check_and_apply_linkage(self, fn_attrs, ty, sym, def_id) + check_and_apply_linkage(self, fn_attrs, llty, sym, def_id) }; // Thread-local statics in some other crate need to *always* be linked @@ -332,34 +349,18 @@ impl<'ll> CodegenCx<'ll, '_> { } } - self.instances.borrow_mut().insert(instance, g); + self.instances.borrow_mut().insert(Instance::mono(self.tcx, def_id), g); g } -} -impl<'ll> StaticMethods for CodegenCx<'ll, '_> { - fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value { - if let Some(&gv) = self.const_globals.borrow().get(&cv) { - unsafe { - // Upgrade the alignment in cases where the same constant is used with different - // alignment requirements - let llalign = align.bytes() as u32; - if llalign > llvm::LLVMGetAlignment(gv) { - llvm::LLVMSetAlignment(gv, llalign); - } - } - return gv; - } - let gv = self.static_addr_of_mut(cv, align, kind); - unsafe { - llvm::LLVMSetGlobalConstant(gv, True); - } - self.const_globals.borrow_mut().insert(cv, gv); - gv - } - - fn codegen_static(&self, def_id: DefId, is_mutable: bool) { + fn codegen_static_item(&self, def_id: DefId) { unsafe { + assert!( + llvm::LLVMGetInitializer( + self.instances.borrow().get(&Instance::mono(self.tcx, def_id)).unwrap() + ) + .is_none() + ); let attrs = self.tcx.codegen_fn_attrs(def_id); let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else { @@ -368,13 +369,11 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { }; let alloc = alloc.inner(); - let g = self.get_static(def_id); - let val_llty = self.val_ty(v); - let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); - let llty = self.layout_of(ty).llvm_type(self); + let g = self.get_static_inner(def_id, val_llty); + let llty = self.val_ty(g); + let g = if val_llty == llty { g } else { @@ -409,16 +408,15 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { self.statics_to_rauw.borrow_mut().push((g, new_g)); new_g }; - set_global_alignment(self, g, self.align_of(ty)); + set_global_alignment(self, g, alloc.align); llvm::LLVMSetInitializer(g, v); if self.should_assume_dso_local(g, true) { llvm::LLVMRustSetDSOLocal(g, true); } - // As an optimization, all shared statics which do not have interior - // mutability are placed into read-only memory. - if !is_mutable && self.type_is_freeze(ty) { + // Forward the allocation's mutability (picked by the const interner) to LLVM. + if alloc.mutability.is_not() { llvm::LLVMSetGlobalConstant(g, llvm::True); } @@ -541,6 +539,32 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { } } } +} + +impl<'ll> StaticMethods for CodegenCx<'ll, '_> { + fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value { + if let Some(&gv) = self.const_globals.borrow().get(&cv) { + unsafe { + // Upgrade the alignment in cases where the same constant is used with different + // alignment requirements + let llalign = align.bytes() as u32; + if llalign > llvm::LLVMGetAlignment(gv) { + llvm::LLVMSetAlignment(gv, llalign); + } + } + return gv; + } + let gv = self.static_addr_of_mut(cv, align, kind); + unsafe { + llvm::LLVMSetGlobalConstant(gv, True); + } + self.const_globals.borrow_mut().insert(cv, gv); + gv + } + + fn codegen_static(&self, def_id: DefId) { + self.codegen_static_item(def_id) + } /// Add a global value to a list to be stored in the `llvm.used` variable, an array of ptr. fn add_used_global(&self, global: &'ll Value) { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index c45787f35aae..ee7ea3423016 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -355,21 +355,20 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) { let tcx = cx.tcx; - let ignore_unused_generics = tcx.sess.instrument_coverage_except_unused_generics(); - let eligible_def_ids = tcx.mir_keys(()).iter().filter_map(|local_def_id| { let def_id = local_def_id.to_def_id(); let kind = tcx.def_kind(def_id); // `mir_keys` will give us `DefId`s for all kinds of things, not // just "functions", like consts, statics, etc. Filter those out. - // If `ignore_unused_generics` was specified, filter out any - // generic functions from consideration as well. if !matches!(kind, DefKind::Fn | DefKind::AssocFn | DefKind::Closure) { return None; } - if ignore_unused_generics && tcx.generics_of(def_id).requires_monomorphization(tcx) { - return None; - } + + // FIXME(79651): Consider trying to filter out dummy instantiations of + // unused generic functions from library crates, because they can produce + // "unused instantiation" in coverage reports even when they are actually + // used by some downstream crate in the same binary. + Some(local_def_id.to_def_id()) }); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 660f16473677..5782b156335f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -26,6 +26,7 @@ use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind; use rustc_codegen_ssa::traits::*; use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; @@ -1309,6 +1310,11 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo }; let is_local_to_unit = is_node_local_to_unit(cx, def_id); + + let DefKind::Static { nested, .. } = cx.tcx.def_kind(def_id) else { bug!() }; + if nested { + return; + } let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); let type_di_node = type_di_node(cx, variable_type); let var_name = tcx.item_name(def_id); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 58e980370673..d34c289887e1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -936,10 +936,16 @@ extern "C" { pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value; // Operations on composite constants - pub fn LLVMConstStringInContext( + pub fn LLVMConstArray2<'a>( + ElementTy: &'a Type, + ConstantVals: *const &'a Value, + Length: u64, + ) -> &'a Value; + pub fn LLVMArrayType2(ElementType: &Type, ElementCount: u64) -> &Type; + pub fn LLVMConstStringInContext2( C: &Context, Str: *const c_char, - Length: c_uint, + Length: size_t, DontNullTerminate: Bool, ) -> &Value; pub fn LLVMConstStructInContext<'a>( @@ -948,14 +954,6 @@ extern "C" { Count: c_uint, Packed: Bool, ) -> &'a Value; - - // FIXME: replace with LLVMConstArray2 when bumped minimal version to llvm-17 - // https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc - pub fn LLVMConstArray<'a>( - ElementTy: &'a Type, - ConstantVals: *const &'a Value, - Length: c_uint, - ) -> &'a Value; pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; // Constant expressions @@ -1530,9 +1528,6 @@ extern "C" { /// See llvm::LLVMTypeKind::getTypeID. pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind; - // Operations on array, pointer, and vector types (sequence types) - pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type; - // Operations on all values pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); pub fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool; diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index f76307193683..29100a641712 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -5,7 +5,9 @@ use crate::errors::SymbolAlreadyDefined; use crate::llvm; use crate::type_of::LayoutLlvmExt; use rustc_codegen_ssa::traits::*; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::bug; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; @@ -21,7 +23,14 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { symbol_name: &str, ) { let instance = Instance::mono(self.tcx, def_id); - let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; + // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out + // the llvm type from the actual evaluated initializer. + let ty = if nested { + self.tcx.types.unit + } else { + instance.ty(self.tcx, ty::ParamEnv::reveal_all()) + }; let llty = self.layout_of(ty).llvm_type(self); let g = self.define_global(symbol_name, llty).unwrap_or_else(|| { diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 07a4861ed738..af1bbda4d08a 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -233,7 +233,7 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { - unsafe { llvm::LLVMRustArrayType(ty, len) } + unsafe { llvm::LLVMArrayType2(ty, len) } } } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 72648e5ade49..87b6f0e914c3 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -87,7 +87,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap {} + DefKind::Fn | DefKind::Static { .. } => {} DefKind::AssocFn if tcx.impl_of_method(def_id.to_def_id()).is_some() => {} _ => return None, }; @@ -483,7 +483,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel let target = &tcx.sess.target.llvm_target; // WebAssembly cannot export data symbols, so reduce their export level if target.contains("emscripten") { - if let DefKind::Static(_) = tcx.def_kind(sym_def_id) { + if let DefKind::Static { .. } = tcx.def_kind(sym_def_id) { return SymbolExportLevel::Rust; } } diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 641ac3eb8087..44a2434238da 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -42,7 +42,7 @@ pub enum RealPredicate { RealPredicateTrue, } -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq)] pub enum AtomicRmwBinOp { AtomicXchg, AtomicAdd, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index d3f5de25d9a2..9bb2a5282658 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1237,6 +1237,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + pub fn codegen_block_as_unreachable(&mut self, bb: mir::BasicBlock) { + let llbb = match self.try_llbb(bb) { + Some(llbb) => llbb, + None => return, + }; + let bx = &mut Bx::build(self.cx, llbb); + debug!("codegen_block_as_unreachable({:?})", bb); + bx.unreachable(); + } + fn codegen_terminator( &mut self, bx: &mut Bx, diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 82488829b6e1..1d1826d98447 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -350,14 +350,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { let weak = instruction == "cxchgweak"; let dst = args[0].immediate(); - let mut cmp = args[1].immediate(); - let mut src = args[2].immediate(); - if ty.is_unsafe_ptr() { - // Some platforms do not support atomic operations on pointers, - // so we cast to integer first. - cmp = bx.ptrtoint(cmp, bx.type_isize()); - src = bx.ptrtoint(src, bx.type_isize()); - } + let cmp = args[1].immediate(); + let src = args[2].immediate(); let (val, success) = bx.atomic_cmpxchg( dst, cmp, @@ -385,26 +379,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let layout = bx.layout_of(ty); let size = layout.size; let source = args[0].immediate(); - if ty.is_unsafe_ptr() { - // Some platforms do not support atomic operations on pointers, - // so we cast to integer first... - let llty = bx.type_isize(); - let result = bx.atomic_load( - llty, - source, - parse_ordering(bx, ordering), - size, - ); - // ... and then cast the result back to a pointer - bx.inttoptr(result, bx.backend_type(layout)) - } else { - bx.atomic_load( - bx.backend_type(layout), - source, - parse_ordering(bx, ordering), - size, - ) - } + bx.atomic_load( + bx.backend_type(layout), + source, + parse_ordering(bx, ordering), + size, + ) } else { invalid_monomorphization(ty); return Ok(()); @@ -415,13 +395,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ty = fn_args.type_at(0); if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { let size = bx.layout_of(ty).size; - let mut val = args[1].immediate(); + let val = args[1].immediate(); let ptr = args[0].immediate(); - if ty.is_unsafe_ptr() { - // Some platforms do not support atomic operations on pointers, - // so we cast to integer first. - val = bx.ptrtoint(val, bx.type_isize()); - } bx.atomic_store(val, ptr, parse_ordering(bx, ordering), size); } else { invalid_monomorphization(ty); @@ -465,12 +440,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let ty = fn_args.type_at(0); if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { let ptr = args[0].immediate(); - let mut val = args[1].immediate(); - if ty.is_unsafe_ptr() { - // Some platforms do not support atomic operations on pointers, - // so we cast to integer first. - val = bx.ptrtoint(val, bx.type_isize()); - } + let val = args[1].immediate(); bx.atomic_rmw(atom_op, ptr, val, parse_ordering(bx, ordering)) } else { invalid_monomorphization(ty); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index a6fcf1fd38c1..bac10f313366 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -256,13 +256,22 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut start_bx); + let reachable_blocks = mir.reachable_blocks_in_mono(cx.tcx(), instance); + // The builders will be created separately for each basic block at `codegen_block`. // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); // Codegen the body of each block using reverse postorder for (bb, _) in traversal::reverse_postorder(mir) { - fx.codegen_block(bb); + if reachable_blocks.contains(bb) { + fx.codegen_block(bb); + } else { + // This may have references to things we didn't monomorphize, so we + // don't actually codegen the body. We still create the block so + // terminators in other blocks can reference it without worry. + fx.codegen_block_as_unreachable(bb); + } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 8c6b9faf39d3..8159f76b421b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -306,11 +306,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.bitcast(imm, to_backend_ty) } (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), - (Int(..), Pointer(..)) => bx.inttoptr(imm, to_backend_ty), + (Int(..), Pointer(..)) => bx.ptradd(bx.const_null(bx.type_ptr()), imm), (Pointer(..), Int(..)) => bx.ptrtoint(imm, to_backend_ty), (F16 | F32 | F64 | F128, Pointer(..)) => { let int_imm = bx.bitcast(imm, bx.cx().type_isize()); - bx.inttoptr(int_imm, to_backend_ty) + bx.ptradd(bx.const_null(bx.type_ptr()), int_imm) } (Pointer(..), F16 | F32 | F64 | F128) => { let int_imm = bx.ptrtoint(imm, bx.cx().type_isize()); diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 1a4795c0213a..7b7cdae0ed61 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -30,7 +30,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { match *self { MonoItem::Static(def_id) => { - cx.codegen_static(def_id, cx.tcx().is_mutable_static(def_id)); + cx.codegen_static(def_id); } MonoItem::GlobalAsm(item_id) => { let item = cx.tcx().hir().item(item_id); diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs index 413d31bb9429..737d93fd80ab 100644 --- a/compiler/rustc_codegen_ssa/src/traits/statics.rs +++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs @@ -4,7 +4,7 @@ use rustc_target::abi::Align; pub trait StaticMethods: BackendTypes { fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value; - fn codegen_static(&self, def_id: DefId, is_mutable: bool); + fn codegen_static(&self, def_id: DefId); /// Mark the given global value as "used", to prevent the compiler and linker from potentially /// removing a static variable that may otherwise appear unused. diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 90884adb28c6..5f4408ebbc6c 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -37,7 +37,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( || matches!( ecx.tcx.def_kind(cid.instance.def_id()), DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst @@ -59,7 +59,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( }; let ret = if let InternKind::Static(_) = intern_kind { - create_static_alloc(ecx, cid.instance.def_id(), layout)? + create_static_alloc(ecx, cid.instance.def_id().expect_local(), layout)? } else { ecx.allocate(layout, MemoryKind::Stack)? }; @@ -380,7 +380,11 @@ pub fn eval_in_interpreter<'mir, 'tcx>( } Ok(mplace) => { // Since evaluation had no errors, validate the resulting constant. + + // Temporarily allow access to the static_root_ids for the purpose of validation. + let static_root_ids = ecx.machine.static_root_ids.take(); let res = const_validate_mplace(&ecx, &mplace, cid); + ecx.machine.static_root_ids = static_root_ids; let alloc_id = mplace.ptr().provenance.unwrap().alloc_id(); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index f104b8367161..dd835279df33 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -8,6 +8,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::IndexEntry; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_hir::LangItem; use rustc_middle::mir; use rustc_middle::mir::AssertMessage; @@ -59,8 +60,10 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { /// Whether to check alignment during evaluation. pub(super) check_alignment: CheckAlignment, - /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization. - pub(crate) static_root_alloc_id: Option, + /// If `Some`, we are evaluating the initializer of the static with the given `LocalDefId`, + /// storing the result in the given `AllocId`. + /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops. + pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>, } #[derive(Copy, Clone)] @@ -94,7 +97,7 @@ impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { stack: Vec::new(), can_access_mut_global, check_alignment, - static_root_alloc_id: None, + static_root_ids: None, } } } @@ -749,7 +752,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ecx: &InterpCx<'mir, 'tcx, Self>, alloc_id: AllocId, ) -> InterpResult<'tcx> { - if Some(alloc_id) == ecx.machine.static_root_alloc_id { + if Some(alloc_id) == ecx.machine.static_root_ids.map(|(id, _)| id) { Err(ConstEvalErrKind::RecursiveStatic.into()) } else { Ok(()) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 249c02b75f7d..46790264359b 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -25,10 +25,13 @@ pub(crate) struct DanglingPtrInFinal { pub kind: InternKind, } -#[derive(Diagnostic)] +#[derive(LintDiagnostic)] #[diag(const_eval_mutable_ptr_in_final)] pub(crate) struct MutablePtrInFinal { - #[primary_span] + // rust-lang/rust#122153: This was marked as `#[primary_span]` under + // `derive(Diagnostic)`. Since we expect we may hard-error in future, we are + // keeping the field (and skipping it under `derive(LintDiagnostic)`). + #[skip_arg] pub span: Span, pub kind: InternKind, } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 82ce9ecd21d1..c30a13624178 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -13,12 +13,17 @@ //! but that would require relying on type information, and given how many ways Rust has to lie //! about type information, we want to avoid doing that. +use hir::def::DefKind; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_middle::mir::interpret::{CtfeProvenance, InterpResult}; +use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult}; +use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::TyAndLayout; +use rustc_session::lint; +use rustc_span::def_id::LocalDefId; +use rustc_span::sym; use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy}; use crate::const_eval; @@ -33,7 +38,19 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine< FrameExtra = (), AllocExtra = (), MemoryMap = FxIndexMap, Allocation)>, - >; + > + HasStaticRootDefId; + +pub trait HasStaticRootDefId { + /// Returns the `DefId` of the static item that is currently being evaluated. + /// Used for interning to be able to handle nested allocations. + fn static_def_id(&self) -> Option; +} + +impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_, '_> { + fn static_def_id(&self) -> Option { + Some(self.static_root_ids?.1) + } +} /// Intern an allocation. Returns `Err` if the allocation does not exist in the local memory. /// @@ -67,10 +84,35 @@ fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>( } // link the alloc id to the actual allocation let alloc = ecx.tcx.mk_const_alloc(alloc); - ecx.tcx.set_alloc_id_memory(alloc_id, alloc); + if let Some(static_id) = ecx.machine.static_def_id() { + intern_as_new_static(ecx.tcx, static_id, alloc_id, alloc); + } else { + ecx.tcx.set_alloc_id_memory(alloc_id, alloc); + } Ok(alloc.0.0.provenance().ptrs().iter().map(|&(_, prov)| prov)) } +/// Creates a new `DefId` and feeds all the right queries to make this `DefId` +/// appear as if it were a user-written `static` (though it has no HIR). +fn intern_as_new_static<'tcx>( + tcx: TyCtxtAt<'tcx>, + static_id: LocalDefId, + alloc_id: AllocId, + alloc: ConstAllocation<'tcx>, +) { + let feed = tcx.create_def( + static_id, + sym::nested, + DefKind::Static { mutability: alloc.0.mutability, nested: true }, + ); + tcx.set_nested_alloc_id_static(alloc_id, feed.def_id()); + feed.codegen_fn_attrs(tcx.codegen_fn_attrs(static_id).clone()); + feed.eval_static_initializer(Ok(alloc)); + feed.generics_of(tcx.generics_of(static_id).clone()); + feed.def_ident_span(tcx.def_ident_span(static_id)); + feed.explicit_predicates_of(tcx.explicit_predicates_of(static_id)); +} + /// How a constant value should be interned. #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)] pub enum InternKind { @@ -221,10 +263,13 @@ pub fn intern_const_alloc_recursive< })?); } if found_bad_mutable_pointer { - return Err(ecx - .tcx - .dcx() - .emit_err(MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind })); + let err_diag = MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }; + ecx.tcx.emit_node_span_lint( + lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, + ecx.best_lint_scope(), + err_diag.span, + err_diag, + ) } Ok(()) diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 305f7ade101e..b260112c7830 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -443,7 +443,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, _prov: (AllocId, Self::ProvenanceExtra), - _range: AllocRange, + _size: Size, + _align: Align, ) -> InterpResult<'tcx> { Ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index cf7f165b87c4..86aad2e1642d 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -15,6 +15,7 @@ use std::ptr; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_hir::def::DefKind; use rustc_middle::mir::display_allocation; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; use rustc_target::abi::{Align, HasDataLayout, Size}; @@ -352,7 +353,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self.machine, &mut alloc.extra, (alloc_id, prov), - alloc_range(Size::ZERO, size), + size, + alloc.align, )?; // Don't forget to remember size and align of this now-dead allocation @@ -761,19 +763,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // be held throughout the match. match self.tcx.try_get_global_alloc(id) { Some(GlobalAlloc::Static(def_id)) => { - assert!(self.tcx.is_static(def_id)); // Thread-local statics do not have a constant address. They *must* be accessed via // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value. assert!(!self.tcx.is_thread_local_static(def_id)); - // Use size and align of the type. - let ty = self - .tcx - .type_of(def_id) - .no_bound_vars() - .expect("statics should not have generic parameters"); - let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); - assert!(layout.is_sized()); - (layout.size, layout.align.abi, AllocKind::LiveData) + + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { + bug!("GlobalAlloc::Static is not a static") + }; + + let (size, align) = if nested { + // Nested anonymous statics are untyped, so let's get their + // size and alignment from the allocaiton itself. This always + // succeeds, as the query is fed at DefId creation time, so no + // evaluation actually occurs. + let alloc = self.tcx.eval_static_initializer(def_id).unwrap(); + (alloc.0.size(), alloc.0.align) + } else { + // Use size and align of the type for everything else. We need + // to do that to + // * avoid cycle errors in case of self-referential statics, + // * be able to get information on extern statics. + let ty = self + .tcx + .type_of(def_id) + .no_bound_vars() + .expect("statics should not have generic parameters"); + let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); + assert!(layout.is_sized()); + (layout.size, layout.align.abi) + }; + (size, align, AllocKind::LiveData) } Some(GlobalAlloc::Memory(alloc)) => { // Need to duplicate the logic here, because the global allocations have diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index a15e52d07e60..2ed879ca72b5 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -22,7 +22,7 @@ pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup}; pub use self::intern::{ - intern_const_alloc_for_constprop, intern_const_alloc_recursive, InternKind, + intern_const_alloc_for_constprop, intern_const_alloc_recursive, HasStaticRootDefId, InternKind, }; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump}; pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 3427368421f8..086475f72c5d 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,11 +1,11 @@ use crate::const_eval::CompileTimeEvalContext; use crate::interpret::{MemPlaceMeta, MemoryKind}; +use rustc_hir::def_id::LocalDefId; use rustc_middle::mir::interpret::{AllocId, Allocation, InterpResult, Pointer}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_span::def_id::DefId; use std::ops::ControlFlow; use super::MPlaceTy; @@ -89,13 +89,13 @@ pub(crate) fn take_static_root_alloc<'mir, 'tcx: 'mir>( pub(crate) fn create_static_alloc<'mir, 'tcx: 'mir>( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, - static_def_id: DefId, + static_def_id: LocalDefId, layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { let alloc = Allocation::try_uninit(layout.size, layout.align.abi)?; - let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id); - assert_eq!(ecx.machine.static_root_alloc_id, None); - ecx.machine.static_root_alloc_id = Some(alloc_id); + let alloc_id = ecx.tcx.reserve_and_set_static_alloc(static_def_id.into()); + assert_eq!(ecx.machine.static_root_ids, None); + ecx.machine.static_root_ids = Some((alloc_id, static_def_id)); assert!(ecx.memory.alloc_map.insert(alloc_id, (MemoryKind::Stack, alloc)).is_none()); Ok(ecx.ptr_with_meta_to_mplace(Pointer::from(alloc_id).into(), MemPlaceMeta::None, layout)) } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 972424bccfa0..d18600ce7d75 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -457,15 +457,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Special handling for pointers to statics (irrespective of their type). assert!(!self.ecx.tcx.is_thread_local_static(did)); assert!(self.ecx.tcx.is_static(did)); - let is_mut = - matches!(self.ecx.tcx.def_kind(did), DefKind::Static(Mutability::Mut)) - || !self - .ecx - .tcx - .type_of(did) - .no_bound_vars() - .expect("statics should not have generic parameters") - .is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()); // Mode-specific checks match self.ctfe_mode { Some( @@ -490,8 +481,28 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } None => {} } - // Return alloc mutability - if is_mut { Mutability::Mut } else { Mutability::Not } + // Return alloc mutability. For "root" statics we look at the type to account for interior + // mutability; for nested statics we have no type and directly use the annotated mutability. + let DefKind::Static { mutability, nested } = self.ecx.tcx.def_kind(did) + else { + bug!() + }; + match (mutability, nested) { + (Mutability::Mut, _) => Mutability::Mut, + (Mutability::Not, true) => Mutability::Not, + (Mutability::Not, false) + if !self + .ecx + .tcx + .type_of(did) + .no_bound_vars() + .expect("statics should not have generic parameters") + .is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()) => + { + Mutability::Mut + } + (Mutability::Not, false) => Mutability::Not, + } } GlobalAlloc::Memory(alloc) => alloc.inner().mutability, GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 7b1070f309b0..c44883541357 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1327,6 +1327,9 @@ pub fn install_ice_hook( panic::update_hook(Box::new( move |default_hook: &(dyn Fn(&PanicInfo<'_>) + Send + Sync + 'static), info: &PanicInfo<'_>| { + // Lock stderr to prevent interleaving of concurrent panics. + let _guard = io::stderr().lock(); + // If the error was caused by a broken pipe then this is not a bug. // Write the error and return immediately. See #98700. #[cfg(windows)] diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index c0c6201f73d4..c9bbe45b2127 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -336,8 +336,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { ThirTree => { let tcx = ex.tcx(); let mut out = String::new(); - rustc_hir_analysis::check_crate(tcx); - if tcx.dcx().has_errors().is_some() { + if rustc_hir_analysis::check_crate(tcx).is_err() { FatalError.raise(); } debug!("pretty printing THIR tree"); @@ -349,8 +348,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { ThirFlat => { let tcx = ex.tcx(); let mut out = String::new(); - rustc_hir_analysis::check_crate(tcx); - if tcx.dcx().has_errors().is_some() { + if rustc_hir_analysis::check_crate(tcx).is_err() { FatalError.raise(); } debug!("pretty printing THIR flat"); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index d4f884d49ea5..286d4621850e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -769,13 +769,10 @@ impl DiagCtxt { format!("invalid level in `stash_diagnostic`: {:?}", diag.level), ); } - Error => { - // This `unchecked_error_guaranteed` is valid. It is where the - // `ErrorGuaranteed` for stashed errors originates. See - // `DiagCtxtInner::drop`. - #[allow(deprecated)] - Some(ErrorGuaranteed::unchecked_error_guaranteed()) - } + // We delay a bug here so that `-Ztreat-err-as-bug -Zeagerly-emit-delayed-bugs` + // can be used to create a backtrace at the stashing site insted of whenever the + // diagnostic context is dropped and thus delayed bugs are emitted. + Error => Some(self.span_delayed_bug(span, "stashing {key:?}")), DelayedBug => return self.inner.borrow_mut().emit_diagnostic(diag), ForceWarning(_) | Warning | Note | OnceNote | Help | OnceHelp | FailureNote | Allow | Expect(_) => None, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 69dfb48919cd..30ee02ea3c0a 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -245,6 +245,15 @@ pub enum ExpandResult { Retry(U), } +impl ExpandResult { + pub fn map E>(self, f: F) -> ExpandResult { + match self { + ExpandResult::Ready(t) => ExpandResult::Ready(f(t)), + ExpandResult::Retry(u) => ExpandResult::Retry(u), + } + } +} + pub trait MultiItemModifier { /// `meta_item` is the attribute, and `item` is the item being modified. fn expand( @@ -330,22 +339,24 @@ pub trait TTMacroExpander { ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> Box; + ) -> MacroExpanderResult<'cx>; } +pub type MacroExpanderResult<'cx> = ExpandResult, ()>; + pub type MacroExpanderFn = - for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box; + for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>; impl TTMacroExpander for F where - F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> Box, + F: for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, TokenStream) -> MacroExpanderResult<'cx>, { fn expand<'cx>( &self, ecx: &'cx mut ExtCtxt<'_>, span: Span, input: TokenStream, - ) -> Box { + ) -> MacroExpanderResult<'cx> { self(ecx, span, input) } } @@ -904,8 +915,11 @@ impl SyntaxExtension { cx: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream, - ) -> Box { - DummyResult::any(span, cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro")) + ) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(DummyResult::any( + span, + cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"), + )) } SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition) } @@ -1008,6 +1022,11 @@ pub trait ResolverExpand { expn_id: LocalExpnId, path: &ast::Path, ) -> Result; + fn macro_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + ) -> Result; /// Decodes the proc-macro quoted span in the specified crate, with the specified id. /// No caching is performed. @@ -1253,6 +1272,15 @@ pub fn resolve_path(sess: &Session, path: impl Into, span: Span) -> PRe } } +/// `Ok` represents successfully retrieving the string literal at the correct +/// position, e.g., `println("abc")`. +type ExprToSpannedStringResult<'a> = Result<(Symbol, ast::StrStyle, Span), UnexpectedExprKind<'a>>; + +/// - `Ok` is returned when the conversion to a string literal is unsuccessful, +/// but another type of expression is obtained instead. +/// - `Err` is returned when the conversion process fails. +type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>; + /// Extracts a string literal from the macro expanded version of `expr`, /// returning a diagnostic error of `err_msg` if `expr` is not a string literal. /// The returned bool indicates whether an applicable suggestion has already been @@ -1264,17 +1292,23 @@ pub fn expr_to_spanned_string<'a>( cx: &'a mut ExtCtxt<'_>, expr: P, err_msg: &'static str, -) -> Result< - (Symbol, ast::StrStyle, Span), - Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>, -> { +) -> ExpandResult, ()> { + if !cx.force_mode + && let ast::ExprKind::MacCall(m) = &expr.kind + && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() + { + return ExpandResult::Retry(()); + } + // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); - Err(match expr.kind { + ExpandResult::Ready(Err(match expr.kind { ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { - Ok(ast::LitKind::Str(s, style)) => return Ok((s, style, expr.span)), + Ok(ast::LitKind::Str(s, style)) => { + return ExpandResult::Ready(Ok((s, style, expr.span))); + } Ok(ast::LitKind::ByteStr(..)) => { let mut err = cx.dcx().struct_span_err(expr.span, err_msg); let span = expr.span.shrink_to_lo(); @@ -1295,7 +1329,7 @@ pub fn expr_to_spanned_string<'a>( cx.dcx().span_bug(expr.span, "tried to get a string literal from `ExprKind::Dummy`") } _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)), - }) + })) } /// Extracts a string literal from the macro expanded version of `expr`, @@ -1305,13 +1339,14 @@ pub fn expr_to_string( cx: &mut ExtCtxt<'_>, expr: P, err_msg: &'static str, -) -> Result<(Symbol, ast::StrStyle), ErrorGuaranteed> { - expr_to_spanned_string(cx, expr, err_msg) - .map_err(|err| match err { +) -> ExpandResult, ()> { + expr_to_spanned_string(cx, expr, err_msg).map(|res| { + res.map_err(|err| match err { Ok((err, _)) => err.emit(), Err(guar) => guar, }) .map(|(symbol, style, _)| (symbol, style)) + }) } /// Non-fatally assert that `tts` is empty. Note that this function @@ -1343,19 +1378,22 @@ pub fn get_single_str_from_tts( span: Span, tts: TokenStream, name: &str, -) -> Result { +) -> ExpandResult, ()> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } - let ret = parse_expr(&mut p)?; + let ret = match parse_expr(&mut p) { + Ok(ret) => ret, + Err(guar) => return ExpandResult::Ready(Err(guar)), + }; let _ = p.eat(&token::Comma); if p.token != token::Eof { cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); } - expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s) + expr_to_string(cx, ret, "argument must be a string literal").map(|s| s.map(|(s, _)| s)) } /// Extracts comma-separated expressions from `tts`. @@ -1363,11 +1401,20 @@ pub fn get_single_str_from_tts( pub fn get_exprs_from_tts( cx: &mut ExtCtxt<'_>, tts: TokenStream, -) -> Result>, ErrorGuaranteed> { +) -> ExpandResult>, ErrorGuaranteed>, ()> { let mut p = cx.new_parser_from_tts(tts); let mut es = Vec::new(); while p.token != token::Eof { - let expr = parse_expr(&mut p)?; + let expr = match parse_expr(&mut p) { + Ok(expr) => expr, + Err(guar) => return ExpandResult::Ready(Err(guar)), + }; + if !cx.force_mode + && let ast::ExprKind::MacCall(m) = &expr.kind + && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() + { + return ExpandResult::Retry(()); + } // Perform eager expansion on the expression. // We want to be able to handle e.g., `concat!("foo", "bar")`. @@ -1379,10 +1426,10 @@ pub fn get_exprs_from_tts( } if p.token != token::Eof { let guar = cx.dcx().emit_err(errors::ExpectedCommaInList { span: p.token.span }); - return Err(guar); + return ExpandResult::Ready(Err(guar)); } } - Ok(es) + ExpandResult::Ready(Ok(es)) } pub fn parse_macro_name_and_helper_attrs( diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 989b7b485c99..e71047f94fa9 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -218,7 +218,7 @@ impl<'a> ExtCtxt<'a> { } pub fn stmt_local(&self, local: P, span: Span) -> ast::Stmt { - ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span } + ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span } } pub fn stmt_item(&self, sp: Span, item: P) -> ast::Stmt { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index fcc439e71f95..cac1e8f80e32 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -659,7 +659,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); ExpandResult::Ready(match invoc.kind { - InvocationKind::Bang { mac, .. } => match ext { + InvocationKind::Bang { mac, span } => match ext { SyntaxExtensionKind::Bang(expander) => { match expander.expand(self.cx, span, mac.args.tokens.clone()) { Ok(tok_result) => { @@ -669,7 +669,16 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } SyntaxExtensionKind::LegacyBang(expander) => { - let tok_result = expander.expand(self.cx, span, mac.args.tokens.clone()); + let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) { + ExpandResult::Ready(tok_result) => tok_result, + ExpandResult::Retry(_) => { + // retry the original + return ExpandResult::Retry(Invocation { + kind: InvocationKind::Bang { mac, span }, + ..invoc + }); + } + }; let result = if let Some(result) = fragment_kind.make_from(tok_result) { result } else { @@ -1380,7 +1389,7 @@ impl InvocationCollectorNode for ast::Stmt { StmtKind::Item(item) => matches!(item.kind, ItemKind::MacCall(..)), StmtKind::Semi(expr) => matches!(expr.kind, ExprKind::MacCall(..)), StmtKind::Expr(..) => unreachable!(), - StmtKind::Local(..) | StmtKind::Empty => false, + StmtKind::Let(..) | StmtKind::Empty => false, } } fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 8903fc45defb..3f29d7f74659 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1,5 +1,5 @@ -use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; -use crate::base::{SyntaxExtension, SyntaxExtensionKind}; +use crate::base::{DummyResult, SyntaxExtension, SyntaxExtensionKind}; +use crate::base::{ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, TTMacroExpander}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; use crate::mbe::diagnostics::{annotate_doc_comment, parse_failure_msg}; @@ -111,8 +111,8 @@ impl TTMacroExpander for MacroRulesMacroExpander { cx: &'cx mut ExtCtxt<'_>, sp: Span, input: TokenStream, - ) -> Box { - expand_macro( + ) -> MacroExpanderResult<'cx> { + ExpandResult::Ready(expand_macro( cx, sp, self.span, @@ -122,7 +122,7 @@ impl TTMacroExpander for MacroRulesMacroExpander { input, &self.lhses, &self.rhses, - ) + )) } } @@ -134,8 +134,8 @@ impl TTMacroExpander for DummyExpander { _: &'cx mut ExtCtxt<'_>, span: Span, _: TokenStream, - ) -> Box { - DummyResult::any(span, self.0) + ) -> ExpandResult, ()> { + ExpandResult::Ready(DummyResult::any(span, self.0)) } } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 23943ee28e2e..1810193c16bd 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -75,7 +75,12 @@ pub enum DefKind { Const, /// Constant generic parameter: `struct Foo { ... }` ConstParam, - Static(ast::Mutability), + Static { + /// Whether it's a `static mut` or just a `static`. + mutability: ast::Mutability, + /// Whether it's an anonymous static generated for nested allocations. + nested: bool, + }, /// Refers to the struct or enum variant's constructor. /// /// The reason `Ctor` exists in addition to [`DefKind::Struct`] and @@ -136,7 +141,7 @@ impl DefKind { DefKind::Fn => "function", DefKind::Mod if def_id.is_crate_root() && !def_id.is_local() => "crate", DefKind::Mod => "module", - DefKind::Static(..) => "static", + DefKind::Static { .. } => "static", DefKind::Enum => "enum", DefKind::Variant => "variant", DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant", @@ -209,7 +214,7 @@ impl DefKind { DefKind::Fn | DefKind::Const | DefKind::ConstParam - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst => Some(Namespace::ValueNS), @@ -245,10 +250,13 @@ impl DefKind { | DefKind::AssocTy | DefKind::TyParam | DefKind::ExternCrate => DefPathData::TypeNs(name), + // It's not exactly an anon const, but wrt DefPathData, there + // is no difference. + DefKind::Static { nested: true, .. } => DefPathData::AnonConst, DefKind::Fn | DefKind::Const | DefKind::ConstParam - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::AssocFn | DefKind::AssocConst | DefKind::Field => DefPathData::ValueNs(name), @@ -278,7 +286,7 @@ impl DefKind { | DefKind::AssocFn | DefKind::Ctor(..) | DefKind::Closure - | DefKind::Static(_) => true, + | DefKind::Static { .. } => true, DefKind::Mod | DefKind::Struct | DefKind::Union diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 18dabe67dae8..7006c90e17b7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1209,7 +1209,7 @@ pub struct Stmt<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum StmtKind<'hir> { /// A local (`let`) binding. - Local(&'hir Local<'hir>), + Let(&'hir Local<'hir>), /// An item binding. Item(ItemId), @@ -1253,11 +1253,11 @@ pub struct Arm<'hir> { pub body: &'hir Expr<'hir>, } -/// Represents a `let [: ] = ` expression (not a Local), occurring in an `if-let` or -/// `let-else`, evaluating to a boolean. Typically the pattern is refutable. +/// Represents a `let [: ] = ` expression (not a [`Local`]), occurring in an `if-let` +/// or `let-else`, evaluating to a boolean. Typically the pattern is refutable. /// -/// In an if-let, imagine it as `if (let = ) { ... }`; in a let-else, it is part of the -/// desugaring to if-let. Only let-else supports the type annotation at present. +/// In an `if let`, imagine it as `if (let = ) { ... }`; in a let-else, it is part of +/// the desugaring to if-let. Only let-else supports the type annotation at present. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Let<'hir> { pub span: Span, @@ -1616,7 +1616,7 @@ impl Expr<'_> { pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool { match self.kind { ExprKind::Path(QPath::Resolved(_, ref path)) => { - matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static(_), _) | Res::Err) + matches!(path.res, Res::Local(..) | Res::Def(DefKind::Static { .. }, _) | Res::Err) } // Type ascription inherits its place expression kind from its diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 32b4bf38fa96..fbbad38d17f1 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -627,7 +627,7 @@ pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) -> pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) -> V::Result { try_visit!(visitor.visit_id(statement.hir_id)); match statement.kind { - StmtKind::Local(ref local) => visitor.visit_local(local), + StmtKind::Let(ref local) => visitor.visit_local(local), StmtKind::Item(item) => visitor.visit_nested_item(item), StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => { visitor.visit_expr(expression) diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 8948a03e4a6f..e448d29e55fb 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -107,7 +107,7 @@ impl Target { match item.kind { ItemKind::ExternCrate(..) => Target::ExternCrate, ItemKind::Use(..) => Target::Use, - ItemKind::Static(..) => Target::Static, + ItemKind::Static { .. } => Target::Static, ItemKind::Const(..) => Target::Const, ItemKind::Fn(..) => Target::Fn, ItemKind::Macro(..) => Target::MacroDef, @@ -130,7 +130,7 @@ impl Target { match def_kind { DefKind::ExternCrate => Target::ExternCrate, DefKind::Use => Target::Use, - DefKind::Static(..) => Target::Static, + DefKind::Static { .. } => Target::Static, DefKind::Const => Target::Const, DefKind::Fn => Target::Fn, DefKind::Macro(..) => Target::MacroDef, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 325342d653dd..25df76359a88 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1934,7 +1934,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Case 3. Reference to a top-level value. - DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static(_) => { + DefKind::Fn | DefKind::Const | DefKind::ConstParam | DefKind::Static { .. } => { path_segs.push(PathSeg(def_id, last)); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index cb739ac48a8b..d1fed13ee9fe 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -226,7 +226,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { Ok(l) => l, // Foreign statics that overflow their allowed size should emit an error Err(LayoutError::SizeOverflow(_)) - if matches!(tcx.def_kind(def_id), DefKind::Static(_) + if matches!(tcx.def_kind(def_id), DefKind::Static{ .. } if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) => { tcx.dcx().emit_err(errors::TooLargeStatic { span }); @@ -381,11 +381,17 @@ fn check_opaque_meets_bounds<'tcx>( match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { Ok(()) => {} Err(ty_err) => { + // Some types may be left "stranded" if they can't be reached + // from an astconv'd bound but they're mentioned in the HIR. This + // will happen, e.g., when a nested opaque is inside of a non- + // existent associated type, like `impl Trait`. + // See . let ty_err = ty_err.to_string(tcx); - tcx.dcx().span_bug( + let guar = tcx.dcx().span_delayed_bug( span, format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"), ); + return Err(guar); } } @@ -505,7 +511,7 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) { pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { let _indenter = indenter(); match tcx.def_kind(def_id) { - DefKind::Static(..) => { + DefKind::Static { .. } => { tcx.ensure().typeck(def_id); maybe_check_static_with_link_section(tcx, def_id); check_static_inhabited(tcx, def_id); diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index 3d32fdd89c86..f0c15a070b48 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -27,7 +27,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { /// Check for shared or mutable references of `static mut` inside statement pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { - if let hir::StmtKind::Local(loc) = stmt.kind + if let hir::StmtKind::Let(loc) = stmt.kind && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind && matches!(ba.0, rustc_ast::ByRef::Yes) && let Some(init) = loc.init @@ -48,8 +48,7 @@ fn is_path_static_mut(expr: hir::Expr<'_>) -> Option { if let hir::ExprKind::Path(qpath) = expr.kind && let hir::QPath::Resolved(_, path) = qpath && let hir::def::Res::Def(def_kind, _) = path.res - && let hir::def::DefKind::Static(mt) = def_kind - && matches!(mt, Mutability::Mut) + && let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind { return Some(qpath_to_string(&qpath)); } diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 2a4dd6b0e0ef..3c26729eff8a 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -123,7 +123,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h for (i, statement) in blk.stmts.iter().enumerate() { match statement.kind { - hir::StmtKind::Local(hir::Local { els: Some(els), .. }) => { + hir::StmtKind::Let(hir::Local { els: Some(els), .. }) => { // Let-else has a special lexical structure for variables. // First we take a checkpoint of the current scope context here. let mut prev_cx = visitor.cx; @@ -146,7 +146,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h // From now on, we continue normally. visitor.cx = prev_cx; } - hir::StmtKind::Local(..) => { + hir::StmtKind::Let(..) => { // Each declaration introduces a subscope for bindings // introduced by the declaration; this subscope covers a // suffix of the block. Each subscope in a block has the diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index d370efc9d0ef..dcb01a117b04 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -5,20 +5,22 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP}; use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType}; -pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) { +pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { let type_of = tcx.type_of(id.owner_id).instantiate_identity(); - tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of }); + res = Err(tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of })); } } } + res } /// Checks "defining uses" of opaque `impl Trait` in associated types. diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 696c47710c23..8cf70fe46aa3 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -98,6 +98,7 @@ mod outlives; pub mod structured_errors; mod variance; +use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_middle::middle; use rustc_middle::query::Providers; @@ -155,13 +156,11 @@ pub fn provide(providers: &mut Providers) { hir_wf_check::provide(providers); } -pub fn check_crate(tcx: TyCtxt<'_>) { +pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { let _prof_timer = tcx.sess.timer("type_check_crate"); if tcx.features().rustc_attrs { - tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx)); - tcx.sess.time("variance_testing", || variance::test::test_variance(tcx)); - collect::test_opaque_hidden_types(tcx); + tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?; } tcx.sess.time("coherence_checking", || { @@ -177,12 +176,20 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let _ = tcx.ensure().crate_inherent_impls_overlap_check(()); }); + if tcx.features().rustc_attrs { + tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?; + } + + if tcx.features().rustc_attrs { + collect::test_opaque_hidden_types(tcx)?; + } + // Make sure we evaluate all static and (non-associated) const items, even if unused. // If any of these fail to evaluate, we do not want this crate to pass compilation. tcx.hir().par_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); match def_kind { - DefKind::Static(_) => tcx.ensure().eval_static_initializer(item_def_id), + DefKind::Static { .. } => tcx.ensure().eval_static_initializer(item_def_id), DefKind::Const => tcx.ensure().const_eval_poly(item_def_id.into()), _ => (), } @@ -191,6 +198,21 @@ pub fn check_crate(tcx: TyCtxt<'_>) { // Freeze definitions as we don't add new ones at this point. This improves performance by // allowing lock-free access to them. tcx.untracked().definitions.freeze(); + + // FIXME: Remove this when we implement creating `DefId`s + // for anon constants during their parents' typeck. + // Typeck all body owners in parallel will produce queries + // cycle errors because it may typeck on anon constants directly. + tcx.hir().par_body_owners(|item_def_id| { + let def_kind = tcx.def_kind(item_def_id); + if !matches!(def_kind, DefKind::AnonConst) { + tcx.ensure().typeck(item_def_id); + } + }); + + tcx.ensure().check_unused_traits(()); + + Ok(()) } /// A quasi-deprecated helper used in rustdoc and clippy to get diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs index dea3f1a99308..60cd8c39fa02 100644 --- a/compiler/rustc_hir_analysis/src/outlives/test.rs +++ b/compiler/rustc_hir_analysis/src/outlives/test.rs @@ -1,7 +1,8 @@ use rustc_middle::ty::{self, TyCtxt}; -use rustc_span::symbol::sym; +use rustc_span::{symbol::sym, ErrorGuaranteed}; -pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { +pub fn test_inferred_outlives(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); for id in tcx.hir().items() { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. @@ -22,7 +23,8 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { for p in pred { err.note(p); } - err.emit(); + res = Err(err.emit()); } } + res } diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs index 5264d5aa26f2..c211e1af046a 100644 --- a/compiler/rustc_hir_analysis/src/variance/test.rs +++ b/compiler/rustc_hir_analysis/src/variance/test.rs @@ -2,19 +2,21 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::sym; +use rustc_span::ErrorGuaranteed; use crate::errors; -pub fn test_variance(tcx: TyCtxt<'_>) { +pub fn test_variance(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { + let mut res = Ok(()); if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) { for id in tcx.hir().items() { if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { let variances_of = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(errors::VariancesOf { + res = Err(tcx.dcx().emit_err(errors::VariancesOf { span: tcx.def_span(id.owner_id), variances_of: format!("{variances_of:?}"), - }); + })); } } } @@ -25,10 +27,11 @@ pub fn test_variance(tcx: TyCtxt<'_>) { if tcx.has_attr(id.owner_id, sym::rustc_variance) { let variances_of = tcx.variances_of(id.owner_id); - tcx.dcx().emit_err(errors::VariancesOf { + res = Err(tcx.dcx().emit_err(errors::VariancesOf { span: tcx.def_span(id.owner_id), variances_of: format!("{variances_of:?}"), - }); + })); } } + res } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b5bb063c5ed8..7d303d989c79 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -863,7 +863,7 @@ impl<'a> State<'a> { fn print_stmt(&mut self, st: &hir::Stmt<'_>) { self.maybe_print_comment(st.span.lo()); match st.kind { - hir::StmtKind::Local(loc) => { + hir::StmtKind::Let(loc) => { self.print_local(loc.init, loc.els, |this| this.print_local_decl(loc)); } hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)), @@ -2306,7 +2306,7 @@ fn expr_requires_semi_to_be_stmt(e: &hir::Expr<'_>) -> bool { /// seen the semicolon, and thus don't need another. fn stmt_ends_with_semi(stmt: &hir::StmtKind<'_>) -> bool { match *stmt { - hir::StmtKind::Local(_) => true, + hir::StmtKind::Let(_) => true, hir::StmtKind::Item(_) => false, hir::StmtKind::Expr(e) => expr_requires_semi_to_be_stmt(e), hir::StmtKind::Semi(..) => false, diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0c5c80ea8907..71da65543403 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -699,7 +699,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Path { res: hir::def::Res::Def( - hir::def::DefKind::Static(_) | hir::def::DefKind::Const, + hir::def::DefKind::Static { .. } | hir::def::DefKind::Const, def_id, ), .. diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ba0383d19b92..43e955445943 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -371,11 +371,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn walk_stmt(&mut self, stmt: &hir::Stmt<'_>) { match stmt.kind { - hir::StmtKind::Local(hir::Local { pat, init: Some(expr), els, .. }) => { + hir::StmtKind::Let(hir::Local { pat, init: Some(expr), els, .. }) => { self.walk_local(expr, pat, *els, |_| {}) } - hir::StmtKind::Local(_) => {} + hir::StmtKind::Let(_) => {} hir::StmtKind::Item(_) => { // We don't visit nested items in this visitor, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index a08582a67d94..0bf81f8bae27 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1593,7 +1593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Don't do all the complex logic below for `DeclItem`. match stmt.kind { hir::StmtKind::Item(..) => return, - hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} + hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} } self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement"); @@ -1602,7 +1602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let old_diverges = self.diverges.replace(Diverges::Maybe); match stmt.kind { - hir::StmtKind::Local(l) => { + hir::StmtKind::Let(l) => { self.check_decl_local(l); } // Ignore for now. @@ -1765,7 +1765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [ hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { + hir::StmtKind::Let(hir::Local { source: hir::LocalSource::AssignDesugar(_), .. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5a1c7b056118..3f6f4cccba79 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1599,7 +1599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_local_statement(&self, id: hir::HirId) -> bool { let node = self.tcx.hir_node(id); - matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) + matches!(node, Node::Stmt(Stmt { kind: StmtKind::Let(..), .. })) } /// Suggest that `&T` was cloned instead of `T` because `T` does not implement `Clone`, diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 1a860aa40679..9307cccf092c 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -398,7 +398,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ) | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, expr_ty)), - Res::Def(DefKind::Static(_), _) => { + Res::Def(DefKind::Static { .. }, _) => { Ok(PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::StaticItem, Vec::new())) } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4c413e4d1c6a..c5bbcc56f86a 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2221,7 +2221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'v> Visitor<'v> for LetVisitor { type Result = ControlFlow>>; fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result { - if let hir::StmtKind::Local(&hir::Local { pat, init, .. }) = ex.kind + if let hir::StmtKind::Let(&hir::Local { pat, init, .. }) = ex.kind && let Binding(_, _, ident, ..) = pat.kind && ident.name == self.ident_name { diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 211109b59417..be14f5bf0d8b 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -217,7 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bug!(); }; for stmt in block.stmts { - let hir::StmtKind::Local(hir::Local { + let hir::StmtKind::Let(hir::Local { init: Some(init), source: hir::LocalSource::AsyncFn, pat, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 222c0a395425..6fb2aa8b1b91 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2139,7 +2139,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // the same span as the error and the type is specified. if let hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { + hir::StmtKind::Let(hir::Local { init: Some(hir::Expr { span: init_span, .. }), ty: Some(array_ty), .. diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 1cbb4b2b23d6..d14cabfc429b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -372,7 +372,7 @@ impl Trait for X { && matches!( tcx.def_kind(body_owner_def_id), DefKind::Fn - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Const | DefKind::AssocFn | DefKind::AssocConst diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 8cdf39b17398..9081fbaa2dc2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -585,7 +585,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result { - if let hir::StmtKind::Local(hir::Local { + if let hir::StmtKind::Let(hir::Local { span, pat: hir::Pat { .. }, ty: None, @@ -824,7 +824,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let hir = self.tcx.hir(); for stmt in blk.stmts.iter().rev() { - let hir::StmtKind::Local(local) = &stmt.kind else { + let hir::StmtKind::Let(local) = &stmt.kind else { continue; }; local.pat.walk(&mut find_compatible_candidates); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 4cc9ffdbb2fa..4b4c1d6cf672 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -734,22 +734,19 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); // passes are timed inside typeck - rustc_hir_analysis::check_crate(tcx); + rustc_hir_analysis::check_crate(tcx)?; - sess.time("typeck_and_mir_analyses", || { + sess.time("MIR_borrow_checking", || { tcx.hir().par_body_owners(|def_id| { - let def_kind = tcx.def_kind(def_id); - // FIXME: Remove this when we implement creating `DefId`s - // for anon constants during their parents' typeck. - // Typeck all body owners in parallel will produce queries - // cycle errors because it may typeck on anon constants directly. - if !matches!(def_kind, rustc_hir::def::DefKind::AnonConst) { - tcx.ensure().typeck(def_id); - } // Run unsafety check because it's responsible for stealing and // deallocating THIR. tcx.ensure().check_unsafety(def_id); - tcx.ensure().mir_borrowck(def_id); + tcx.ensure().mir_borrowck(def_id) + }); + }); + + sess.time("MIR_effect_checking", || { + for def_id in tcx.hir().body_owners() { if !tcx.sess.opts.unstable_opts.thir_unsafeck { rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id); } @@ -764,15 +761,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { tcx.ensure().mir_drops_elaborated_and_const_checked(def_id); tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id())); } - - if tcx.is_coroutine(def_id.to_def_id()) { - tcx.ensure().mir_coroutine_witnesses(def_id); - tcx.ensure().check_coroutine_obligations(def_id); - } - }) + } }); - tcx.ensure().check_unused_traits(()); + tcx.hir().par_body_owners(|def_id| { + if tcx.is_coroutine(def_id.to_def_id()) { + tcx.ensure().mir_coroutine_witnesses(def_id); + tcx.ensure().check_coroutine_obligations(def_id); + } + }); sess.time("layout_testing", || layout_test::test_layout(tcx)); sess.time("abi_testing", || abi_test::test_abi(tcx)); diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index da11d090b749..c22188226961 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -321,6 +321,8 @@ impl Compiler { } self.sess.time("serialize_dep_graph", || gcx.enter(rustc_incremental::save_dep_graph)); + + gcx.enter(rustc_query_impl::query_key_hash_verify_all); } // The timer's lifetime spans the dropping of `queries`, which contains diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 42fff01c11c9..4d8e749d1da7 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,11 +4,12 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::{ build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg, - CollapseMacroDebuginfo, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, - ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, - InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, - OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, - ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, + CollapseMacroDebuginfo, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, + ExternEntry, ExternLocation, Externs, FunctionReturn, InliningThreshold, Input, + InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, + NextSolverConfig, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, + Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, + WasiExecModel, }; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; @@ -750,6 +751,7 @@ fn test_unstable_options_tracking_hash() { ); tracked!(codegen_backend, Some("abc".to_string())); tracked!(collapse_macro_debuginfo, CollapseMacroDebuginfo::Yes); + tracked!(coverage_options, CoverageOptions { branch: true }); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); tracked!(debug_info_for_profiling, true); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 595dc08b081e..d1343e3b4bae 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -989,7 +989,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & impl EarlyLintPass for UnusedDocComment { fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) { let kind = match stmt.kind { - ast::StmtKind::Local(..) => "statements", + ast::StmtKind::Let(..) => "statements", // Disabled pending discussion in #78306 ast::StmtKind::Item(..) => return, // expressions will be reported by `check_expr`. diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index f84d1c6c2d0a..3e10879e2411 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -914,7 +914,7 @@ trait UnusedDelimLint { fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { match s.kind { - StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { + StmtKind::Let(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { if let Some((init, els)) = local.kind.init_else_opt() { let ctx = match els { None => UnusedDelimsCtx::AssignedValue, @@ -1189,7 +1189,7 @@ impl EarlyLintPass for UnusedParens { } fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { - if let StmtKind::Local(ref local) = s.kind { + if let StmtKind::Let(ref local) = s.kind { self.check_unused_parens_pat(cx, &local.pat, true, false, (true, false)); } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index f2560b35aa2e..20e492dbd8a7 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -30,6 +30,7 @@ declare_lint_pass! { CENUM_IMPL_DROP_CAST, COHERENCE_LEAK_CHECK, CONFLICTING_REPR_HINTS, + CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, CONST_EVALUATABLE_UNCHECKED, CONST_ITEM_MUTATION, DEAD_CODE, @@ -2796,6 +2797,51 @@ declare_lint! { @feature_gate = sym::strict_provenance; } +declare_lint! { + /// The `const_eval_mutable_ptr_in_final_value` lint detects if a mutable pointer + /// has leaked into the final value of a const expression. + /// + /// ### Example + /// + /// ```rust + /// pub enum JsValue { + /// Undefined, + /// Object(std::cell::Cell), + /// } + /// + /// impl ::std::ops::Drop for JsValue { + /// fn drop(&mut self) {} + /// } + /// + /// const UNDEFINED: &JsValue = &JsValue::Undefined; + /// + /// fn main() { + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// In the 1.77 release, the const evaluation machinery adopted some + /// stricter rules to reject expressions with values that could + /// end up holding mutable references to state stored in static memory + /// (which is inherently immutable). + /// + /// This is a [future-incompatible] lint to ease the transition to an error. + /// See [issue #122153] for more details. + /// + /// [issue #122153]: https://github.com/rust-lang/rust/issues/122153 + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, + Warn, + "detects a mutable pointer that has leaked into final value of a const expression", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #122153 ", + }; +} + declare_lint! { /// The `const_evaluatable_unchecked` lint detects a generic constant used /// in a type. diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 3e998d428ee9..1632b9e12490 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -10,6 +10,7 @@ #include "llvm/IR/IntrinsicsARM.h" #include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/Mangler.h" +#include "llvm/IR/Value.h" #include "llvm/Remarks/RemarkStreamer.h" #include "llvm/Remarks/RemarkSerializer.h" #include "llvm/Remarks/RemarkFormat.h" @@ -1111,11 +1112,16 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo, uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL, LLVMBasicBlockRef InsertAtEnd) { - return wrap(Builder->insertDeclare( + auto Result = Builder->insertDeclare( unwrap(V), unwrap(VarInfo), Builder->createExpression(llvm::ArrayRef(AddrOps, AddrOpsCount)), DebugLoc(cast(unwrap(DL))), - unwrap(InsertAtEnd))); + unwrap(InsertAtEnd)); +#if LLVM_VERSION_GE(19, 0) + return wrap(Result.get()); +#else + return wrap(Result); +#endif } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator( @@ -1223,14 +1229,6 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V, } } -// LLVMArrayType function does not support 64-bit ElementCount -// FIXME: replace with LLVMArrayType2 when bumped minimal version to llvm-17 -// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc -extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy, - uint64_t ElementCount) { - return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); -} - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef) extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) { @@ -2114,3 +2112,36 @@ extern "C" bool LLVMRustLLVMHasZlibCompressionForDebugSymbols() { extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() { return llvm::compression::zstd::isAvailable(); } + +// Operations on composite constants. +// These are clones of LLVM api functions that will become available in future releases. +// They can be removed once Rust's minimum supported LLVM version supports them. +// See https://github.com/rust-lang/rust/issues/121868 +// See https://llvm.org/doxygen/group__LLVMCCoreValueConstantComposite.html + +// FIXME: Remove when Rust's minimum supported LLVM version reaches 19. +// https://github.com/llvm/llvm-project/commit/e1405e4f71c899420ebf8262d5e9745598419df8 +#if LLVM_VERSION_LT(19, 0) +extern "C" LLVMValueRef LLVMConstStringInContext2(LLVMContextRef C, + const char *Str, + size_t Length, + bool DontNullTerminate) { + return wrap(ConstantDataArray::getString(*unwrap(C), StringRef(Str, Length), !DontNullTerminate)); +} +#endif + +// FIXME: Remove when Rust's minimum supported LLVM version reaches 17. +// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc +#if LLVM_VERSION_LT(17, 0) +extern "C" LLVMValueRef LLVMConstArray2(LLVMTypeRef ElementTy, + LLVMValueRef *ConstantVals, + uint64_t Length) { + ArrayRef V(unwrap(ConstantVals, Length), Length); + return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length), V)); +} + +extern "C" LLVMTypeRef LLVMArrayType2(LLVMTypeRef ElementTy, + uint64_t ElementCount) { + return wrap(ArrayType::get(unwrap(ElementTy), ElementCount)); +} +#endif diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 6e9cbfdcfee2..26226386ef72 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -863,7 +863,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::LifetimeParam | DefKind::Fn | DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -894,7 +894,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::AssocTy | DefKind::Fn | DefKind::Const - | DefKind::Static(_) + | DefKind::Static { nested: false, .. } | DefKind::AssocFn | DefKind::AssocConst | DefKind::Macro(_) @@ -915,6 +915,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::InlineConst | DefKind::OpaqueTy | DefKind::LifetimeParam + | DefKind::Static { nested: true, .. } | DefKind::GlobalAsm => false, } } @@ -936,7 +937,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Fn | DefKind::Const | DefKind::ConstParam - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -968,7 +969,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::AssocTy | DefKind::Fn | DefKind::Const - | DefKind::Static(..) + | DefKind::Static { nested: false, .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -981,6 +982,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::LifetimeParam | DefKind::AnonConst | DefKind::InlineConst + | DefKind::Static { nested: true, .. } | DefKind::OpaqueTy | DefKind::GlobalAsm | DefKind::Impl { .. } @@ -1001,7 +1003,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::AssocConst | DefKind::TyParam | DefKind::ConstParam - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Const | DefKind::Fn | DefKind::ForeignMod @@ -1099,7 +1101,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::AssocConst | DefKind::TyParam | DefKind::ConstParam - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Const | DefKind::ForeignMod | DefKind::Impl { .. } @@ -1131,7 +1133,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::AssocTy | DefKind::Fn | DefKind::Const - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::AssocFn | DefKind::AssocConst @@ -1163,7 +1165,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Field | DefKind::Fn | DefKind::Const - | DefKind::Static(..) + | DefKind::Static { nested: false, .. } | DefKind::TyAlias | DefKind::ForeignTy | DefKind::Impl { .. } @@ -1205,6 +1207,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Mod | DefKind::ForeignMod | DefKind::Macro(..) + | DefKind::Static { nested: true, .. } | DefKind::Use | DefKind::LifetimeParam | DefKind::GlobalAsm @@ -1222,7 +1225,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Variant | DefKind::Field | DefKind::Const - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::Ctor(..) | DefKind::TyAlias | DefKind::OpaqueTy @@ -1263,7 +1266,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::Impl { of_trait: false } @@ -1295,7 +1298,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Ctor(..) | DefKind::Field | DefKind::Fn - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::ForeignTy @@ -1469,7 +1472,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { .coroutine_for_closure .set_some(def_id.index, self.tcx.coroutine_for_closure(def_id).into()); } - if let DefKind::Static(_) = def_kind { + if let DefKind::Static { .. } = def_kind { if !self.tcx.is_foreign_item(def_id) { let data = self.tcx.eval_static_initializer(def_id).unwrap(); record!(self.tables.eval_static_initializer[def_id] <- data); diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index c5f281964df0..019cb91c765e 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -155,8 +155,10 @@ fixed_size_enum! { ( Impl { of_trait: false } ) ( Impl { of_trait: true } ) ( Closure ) - ( Static(ast::Mutability::Not) ) - ( Static(ast::Mutability::Mut) ) + ( Static { mutability: ast::Mutability::Not, nested: false } ) + ( Static { mutability: ast::Mutability::Mut, nested: false } ) + ( Static { mutability: ast::Mutability::Not, nested: true } ) + ( Static { mutability: ast::Mutability::Mut, nested: true } ) ( Ctor(CtorOf::Struct, CtorKind::Fn) ) ( Ctor(CtorOf::Struct, CtorKind::Const) ) ( Ctor(CtorOf::Variant, CtorKind::Fn) ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4960369a0a7a..142988dee747 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -343,7 +343,7 @@ impl<'hir> Map<'hir> { DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, DefKind::Closure => BodyOwnerKind::Closure, - DefKind::Static(mt) => BodyOwnerKind::Static(mt), + DefKind::Static { mutability, nested: false } => BodyOwnerKind::Static(mutability), dk => bug!("{:?} is not a body node: {:?}", def_id, dk), } } @@ -359,7 +359,7 @@ impl<'hir> Map<'hir> { let def_id = def_id.into(); let ccx = match self.body_owner_kind(def_id) { BodyOwnerKind::Const { inline } => ConstContext::Const { inline }, - BodyOwnerKind::Static(mt) => ConstContext::Static(mt), + BodyOwnerKind::Static(mutability) => ConstContext::Static(mutability), BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None, BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id) => { @@ -655,7 +655,7 @@ impl<'hir> Map<'hir> { | Node::ForeignItem(_) | Node::TraitItem(_) | Node::ImplItem(_) - | Node::Stmt(Stmt { kind: StmtKind::Local(_), .. }) => break, + | Node::Stmt(Stmt { kind: StmtKind::Let(_), .. }) => break, Node::Expr(expr @ Expr { kind: ExprKind::If(..) | ExprKind::Match(..), .. }) => { return Some(expr); } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 94b9afa1deef..f9edbb3c5ae2 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -130,7 +130,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{HashMapExt, Lock}; use rustc_data_structures::tiny_list::TinyList; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; @@ -627,6 +627,16 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Freezes an `AllocId` created with `reserve` by pointing it at a static item. Trying to + /// call this function twice, even with the same `DefId` will ICE the compiler. + pub fn set_nested_alloc_id_static(self, id: AllocId, def_id: LocalDefId) { + if let Some(old) = + self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Static(def_id.to_def_id())) + { + bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}"); + } + } + /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called /// twice for the same `(AllocId, Allocation)` pair. fn set_alloc_id_same_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4b5a08d6af3c..b71c614dc4fe 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -10,7 +10,7 @@ use crate::ty::print::{pretty_print_const, with_no_trimmed_paths}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; -use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex}; +use crate::ty::{AdtDef, Instance, InstanceDef, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, GenericArgsRef}; use rustc_data_structures::captures::Captures; @@ -27,6 +27,8 @@ pub use rustc_ast::Mutability; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_index::bit_set::BitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_serialize::{Decodable, Encodable}; use rustc_span::symbol::Symbol; @@ -640,6 +642,129 @@ impl<'tcx> Body<'tcx> { self.injection_phase.is_some() } + /// Finds which basic blocks are actually reachable for a specific + /// monomorphization of this body. + /// + /// This is allowed to have false positives; just because this says a block + /// is reachable doesn't mean that's necessarily true. It's thus always + /// legal for this to return a filled set. + /// + /// Regardless, the [`BitSet::domain_size`] of the returned set will always + /// exactly match the number of blocks in the body so that `contains` + /// checks can be done without worrying about panicking. + /// + /// This is mostly useful because it lets us skip lowering the `false` side + /// of `if ::CONST`, as well as `intrinsics::debug_assertions`. + pub fn reachable_blocks_in_mono( + &self, + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + ) -> BitSet { + let mut set = BitSet::new_empty(self.basic_blocks.len()); + self.reachable_blocks_in_mono_from(tcx, instance, &mut set, START_BLOCK); + set + } + + fn reachable_blocks_in_mono_from( + &self, + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + set: &mut BitSet, + bb: BasicBlock, + ) { + if !set.insert(bb) { + return; + } + + let data = &self.basic_blocks[bb]; + + if let Some((bits, targets)) = Self::try_const_mono_switchint(tcx, instance, data) { + let target = targets.target_for_value(bits); + ensure_sufficient_stack(|| { + self.reachable_blocks_in_mono_from(tcx, instance, set, target) + }); + return; + } + + for target in data.terminator().successors() { + ensure_sufficient_stack(|| { + self.reachable_blocks_in_mono_from(tcx, instance, set, target) + }); + } + } + + /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the + /// dimscriminant in monomorphization, we return the discriminant bits and the + /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator. + fn try_const_mono_switchint<'a>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + block: &'a BasicBlockData<'tcx>, + ) -> Option<(u128, &'a SwitchTargets)> { + // There are two places here we need to evaluate a constant. + let eval_mono_const = |constant: &ConstOperand<'tcx>| { + let env = ty::ParamEnv::reveal_all(); + let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( + tcx, + env, + crate::ty::EarlyBinder::bind(constant.const_), + ); + let Some(bits) = mono_literal.try_eval_bits(tcx, env) else { + bug!("Couldn't evaluate constant {:?} in mono {:?}", constant, instance); + }; + bits + }; + + let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else { + return None; + }; + + // If this is a SwitchInt(const _), then we can just evaluate the constant and return. + let discr = match discr { + Operand::Constant(constant) => { + let bits = eval_mono_const(constant); + return Some((bits, targets)); + } + Operand::Move(place) | Operand::Copy(place) => place, + }; + + // MIR for `if false` actually looks like this: + // _1 = const _ + // SwitchInt(_1) + // + // And MIR for if intrinsics::debug_assertions() looks like this: + // _1 = cfg!(debug_assertions) + // SwitchInt(_1) + // + // So we're going to try to recognize this pattern. + // + // If we have a SwitchInt on a non-const place, we find the most recent statement that + // isn't a storage marker. If that statement is an assignment of a const to our + // discriminant place, we evaluate and return the const, as if we've const-propagated it + // into the SwitchInt. + + let last_stmt = block.statements.iter().rev().find(|stmt| { + !matches!(stmt.kind, StatementKind::StorageDead(_) | StatementKind::StorageLive(_)) + })?; + + let (place, rvalue) = last_stmt.kind.as_assign()?; + + if discr != place { + return None; + } + + match rvalue { + Rvalue::NullaryOp(NullOp::UbCheck(_), _) => { + Some((tcx.sess.opts.debug_assertions as u128, targets)) + } + Rvalue::Use(Operand::Constant(constant)) => { + let bits = eval_mono_const(constant); + Some((bits, targets)) + } + _ => None, + } + } + /// For a `Location` in this scope, determine what the "caller location" at that point is. This /// is interesting because of inlining: the `#[track_caller]` attribute of inlined functions /// must be honored. Falls back to the `tracked_caller` value for `#[track_caller]` functions, diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 090b84ff08fd..8ae65f3832fd 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -498,8 +498,12 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: match (kind, body.source.promoted) { (_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?, - (DefKind::Static(hir::Mutability::Not), _) => write!(w, "static ")?, - (DefKind::Static(hir::Mutability::Mut), _) => write!(w, "static mut ")?, + (DefKind::Static { mutability: hir::Mutability::Not, nested: false }, _) => { + write!(w, "static ")? + } + (DefKind::Static { mutability: hir::Mutability::Mut, nested: false }, _) => { + write!(w, "static mut ")? + } (_, _) if is_function => write!(w, "fn ")?, (DefKind::AnonConst | DefKind::InlineConst, _) => {} // things like anon const, not an item _ => bug!("Unexpected def kind {:?}", kind), diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index a1ff8410eac4..0a938bcd3156 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -1,5 +1,3 @@ -use rustc_index::bit_set::BitSet; - use super::*; /// Preorder traversal of a graph. diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 332ebdbdd944..83ded5859c67 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1062,6 +1062,7 @@ rustc_queries! { } cache_on_disk_if { key.is_local() } separate_provide_extern + feedable } /// Evaluates const items or anonymous constants @@ -1220,6 +1221,7 @@ rustc_queries! { arena_cache cache_on_disk_if { def_id.is_local() } separate_provide_extern + feedable } query asm_target_features(def_id: DefId) -> &'tcx FxIndexSet { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 5c2d3973d61d..8565f90957f2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1708,7 +1708,7 @@ impl<'tcx> TyCtxt<'tcx> { debug!("returned from def_kind: {:?}", def_kind); match def_kind { DefKind::Const - | DefKind::Static(..) + | DefKind::Static { .. } | DefKind::AssocConst | DefKind::Ctor(..) | DefKind::AnonConst diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 33d63c2a5053..802953867ac1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -359,7 +359,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { | DefKind::TyAlias | DefKind::Fn | DefKind::Const - | DefKind::Static(_) = kind + | DefKind::Static { .. } = kind { } else { // If not covered above, like for example items out of `impl` blocks, fallback. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 4bb0d2c7d1c2..a6526b068517 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -616,12 +616,16 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns `true` if the node pointed to by `def_id` is a `static` item. #[inline] pub fn is_static(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Static(_)) + matches!(self.def_kind(def_id), DefKind::Static { .. }) } #[inline] pub fn static_mutability(self, def_id: DefId) -> Option { - if let DefKind::Static(mt) = self.def_kind(def_id) { Some(mt) } else { None } + if let DefKind::Static { mutability, .. } = self.def_kind(def_id) { + Some(mutability) + } else { + None + } } /// Returns `true` if this is a `static` item with the `#[thread_local]` attribute. diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 48c3ee1ba0ff..4d5ed65c8416 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -14,7 +14,6 @@ use rustc_data_structures::{ fx::{FxHashSet, FxIndexMap, FxIndexSet}, stack::ensure_sufficient_stack, }; -use rustc_index::bit_set::BitSet; use rustc_middle::middle::region; use rustc_middle::mir::{self, *}; use rustc_middle::thir::{self, *}; @@ -1084,6 +1083,12 @@ enum TestCase<'pat, 'tcx> { Or { pats: Box<[FlatPat<'pat, 'tcx>]> }, } +impl<'pat, 'tcx> TestCase<'pat, 'tcx> { + fn as_range(&self) -> Option<&'pat PatRange<'tcx>> { + if let Self::Range(v) = self { Some(*v) } else { None } + } +} + #[derive(Debug, Clone)] pub(crate) struct MatchPair<'pat, 'tcx> { /// This place... @@ -1108,19 +1113,10 @@ enum TestKind<'tcx> { Switch { /// The enum type being tested. adt_def: ty::AdtDef<'tcx>, - /// The set of variants that we should create a branch for. We also - /// create an additional "otherwise" case. - variants: BitSet, }, /// Test what value an integer or `char` has. - SwitchInt { - /// The (ordered) set of values that we test for. - /// - /// We create a branch to each of the values in `options`, as well as an "otherwise" branch - /// for all other values, even in the (rare) case that `options` is exhaustive. - options: FxIndexMap, u128>, - }, + SwitchInt, /// Test what value a `bool` has. If, @@ -1152,6 +1148,25 @@ pub(crate) struct Test<'tcx> { kind: TestKind<'tcx>, } +/// The branch to be taken after a test. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum TestBranch<'tcx> { + /// Success branch, used for tests with two possible outcomes. + Success, + /// Branch corresponding to this constant. + Constant(Const<'tcx>, u128), + /// Branch corresponding to this variant. + Variant(VariantIdx), + /// Failure branch for tests with two possible outcomes, and "otherwise" branch for other tests. + Failure, +} + +impl<'tcx> TestBranch<'tcx> { + fn as_constant(&self) -> Option<&Const<'tcx>> { + if let Self::Constant(v, _) = self { Some(v) } else { None } + } +} + /// `ArmHasGuard` is a wrapper around a boolean flag. It indicates whether /// a match arm has a guard expression attached to it. #[derive(Copy, Clone, Debug)] @@ -1561,30 +1576,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> (PlaceBuilder<'tcx>, Test<'tcx>) { // Extract the match-pair from the highest priority candidate let match_pair = &candidates.first().unwrap().match_pairs[0]; - let mut test = self.test(match_pair); + let test = self.test(match_pair); let match_place = match_pair.place.clone(); - debug!(?test, ?match_pair); - // Most of the time, the test to perform is simply a function of the main candidate; but for - // a test like SwitchInt, we may want to add cases based on the candidates that are - // available - match test.kind { - TestKind::SwitchInt { ref mut options } => { - for candidate in candidates.iter() { - if !self.add_cases_to_switch(&match_place, candidate, options) { - break; - } - } - } - TestKind::Switch { adt_def: _, ref mut variants } => { - for candidate in candidates.iter() { - if !self.add_variants_to_switch(&match_place, candidate, variants) { - break; - } - } - } - _ => {} - } (match_place, test) } @@ -1627,11 +1621,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_place: &PlaceBuilder<'tcx>, test: &Test<'tcx>, mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], - ) -> (&'b mut [&'c mut Candidate<'pat, 'tcx>], Vec>>) { - // For each of the N possible outcomes, create a (initially empty) vector of candidates. - // Those are the candidates that apply if the test has that particular outcome. - let mut target_candidates: Vec>> = vec![]; - target_candidates.resize_with(test.targets(), Default::default); + ) -> ( + &'b mut [&'c mut Candidate<'pat, 'tcx>], + FxIndexMap, Vec<&'b mut Candidate<'pat, 'tcx>>>, + ) { + // For each of the possible outcomes, collect vector of candidates that apply if the test + // has that particular outcome. + let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_, '_>>> = Default::default(); let total_candidate_count = candidates.len(); @@ -1639,11 +1635,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // point we may encounter a candidate where the test is not relevant; at that point, we stop // sorting. while let Some(candidate) = candidates.first_mut() { - let Some(idx) = self.sort_candidate(&match_place, &test, candidate) else { + let Some(branch) = + self.sort_candidate(&match_place, test, candidate, &target_candidates) + else { break; }; let (candidate, rest) = candidates.split_first_mut().unwrap(); - target_candidates[idx].push(candidate); + target_candidates.entry(branch).or_insert_with(Vec::new).push(candidate); candidates = rest; } @@ -1784,31 +1782,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { otherwise_block }; - // For each outcome of test, process the candidates that still - // apply. Collect a list of blocks where control flow will - // branch if one of the `target_candidate` sets is not - // exhaustive. - let target_blocks: Vec<_> = target_candidates + // For each outcome of test, process the candidates that still apply. + let target_blocks: FxIndexMap<_, _> = target_candidates .into_iter() - .map(|mut candidates| { - if !candidates.is_empty() { - let candidate_start = self.cfg.start_new_block(); - self.match_candidates( - span, - scrutinee_span, - candidate_start, - remainder_start, - &mut *candidates, - ); - candidate_start - } else { - remainder_start - } + .map(|(branch, mut candidates)| { + let candidate_start = self.cfg.start_new_block(); + self.match_candidates( + span, + scrutinee_span, + candidate_start, + remainder_start, + &mut *candidates, + ); + (branch, candidate_start) }) .collect(); // Perform the test, branching to one of N blocks. - self.perform_test(span, scrutinee_span, start_block, &match_place, &test, target_blocks); + self.perform_test( + span, + scrutinee_span, + start_block, + remainder_start, + &match_place, + &test, + target_blocks, + ); } /// Determine the fake borrows that are needed from a set of places that diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 8ce7461747b4..9d77bd063e11 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -6,13 +6,11 @@ // the candidates based on the result. use crate::build::expr::as_place::PlaceBuilder; -use crate::build::matches::{Candidate, MatchPair, Test, TestCase, TestKind}; +use crate::build::matches::{Candidate, MatchPair, Test, TestBranch, TestCase, TestKind}; use crate::build::Builder; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::{LangItem, RangeEnd}; -use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; -use rustc_middle::thir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, adjustment::PointerCoercion, Ty, TyCtxt}; @@ -20,7 +18,6 @@ use rustc_span::def_id::DefId; use rustc_span::source_map::Spanned; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; -use rustc_target::abi::VariantIdx; use std::cmp::Ordering; @@ -30,22 +27,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// It is a bug to call this with a not-fully-simplified pattern. pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { let kind = match match_pair.test_case { - TestCase::Variant { adt_def, variant_index: _ } => { - TestKind::Switch { adt_def, variants: BitSet::new_empty(adt_def.variants().len()) } - } + TestCase::Variant { adt_def, variant_index: _ } => TestKind::Switch { adt_def }, TestCase::Constant { .. } if match_pair.pattern.ty.is_bool() => TestKind::If, - - TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => { - // For integers, we use a `SwitchInt` match, which allows - // us to handle more cases. - TestKind::SwitchInt { - // these maps are empty to start; cases are - // added below in add_cases_to_switch - options: Default::default(), - } - } - + TestCase::Constant { .. } if is_switch_ty(match_pair.pattern.ty) => TestKind::SwitchInt, TestCase::Constant { value } => TestKind::Eq { value, ty: match_pair.pattern.ty }, TestCase::Range(range) => { @@ -70,101 +55,38 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Test { span: match_pair.pattern.span, kind } } - pub(super) fn add_cases_to_switch<'pat>( - &mut self, - test_place: &PlaceBuilder<'tcx>, - candidate: &Candidate<'pat, 'tcx>, - options: &mut FxIndexMap, u128>, - ) -> bool { - let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) - else { - return false; - }; - - match match_pair.test_case { - TestCase::Constant { value } => { - options.entry(value).or_insert_with(|| value.eval_bits(self.tcx, self.param_env)); - true - } - TestCase::Variant { .. } => { - panic!("you should have called add_variants_to_switch instead!"); - } - TestCase::Range(ref range) => { - // Check that none of the switch values are in the range. - self.values_not_contained_in_range(&*range, options).unwrap_or(false) - } - // don't know how to add these patterns to a switch - _ => false, - } - } - - pub(super) fn add_variants_to_switch<'pat>( - &mut self, - test_place: &PlaceBuilder<'tcx>, - candidate: &Candidate<'pat, 'tcx>, - variants: &mut BitSet, - ) -> bool { - let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) - else { - return false; - }; - - match match_pair.test_case { - TestCase::Variant { variant_index, .. } => { - // We have a pattern testing for variant `variant_index` - // set the corresponding index to true - variants.insert(variant_index); - true - } - // don't know how to add these patterns to a switch - _ => false, - } - } - #[instrument(skip(self, target_blocks, place_builder), level = "debug")] pub(super) fn perform_test( &mut self, match_start_span: Span, scrutinee_span: Span, block: BasicBlock, + otherwise_block: BasicBlock, place_builder: &PlaceBuilder<'tcx>, test: &Test<'tcx>, - target_blocks: Vec, + target_blocks: FxIndexMap, BasicBlock>, ) { let place = place_builder.to_place(self); let place_ty = place.ty(&self.local_decls, self.tcx); - debug!(?place, ?place_ty,); + debug!(?place, ?place_ty); + let target_block = |branch| target_blocks.get(&branch).copied().unwrap_or(otherwise_block); let source_info = self.source_info(test.span); match test.kind { - TestKind::Switch { adt_def, ref variants } => { - // Variants is a BitVec of indexes into adt_def.variants. - let num_enum_variants = adt_def.variants().len(); - debug_assert_eq!(target_blocks.len(), num_enum_variants + 1); - let otherwise_block = *target_blocks.last().unwrap(); - let tcx = self.tcx; + TestKind::Switch { adt_def } => { + let otherwise_block = target_block(TestBranch::Failure); let switch_targets = SwitchTargets::new( - adt_def.discriminants(tcx).filter_map(|(idx, discr)| { - if variants.contains(idx) { - debug_assert_ne!( - target_blocks[idx.index()], - otherwise_block, - "no candidates for tested discriminant: {discr:?}", - ); - Some((discr.val, target_blocks[idx.index()])) + adt_def.discriminants(self.tcx).filter_map(|(idx, discr)| { + if let Some(&block) = target_blocks.get(&TestBranch::Variant(idx)) { + Some((discr.val, block)) } else { - debug_assert_eq!( - target_blocks[idx.index()], - otherwise_block, - "found candidates for untested discriminant: {discr:?}", - ); None } }), otherwise_block, ); - debug!("num_enum_variants: {}, variants: {:?}", num_enum_variants, variants); - let discr_ty = adt_def.repr().discr_type().to_ty(tcx); + debug!("num_enum_variants: {}", adt_def.variants().len()); + let discr_ty = adt_def.repr().discr_type().to_ty(self.tcx); let discr = self.temp(discr_ty, test.span); self.cfg.push_assign( block, @@ -182,12 +104,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); } - TestKind::SwitchInt { ref options } => { + TestKind::SwitchInt => { // The switch may be inexhaustive so we have a catch-all block - debug_assert_eq!(options.len() + 1, target_blocks.len()); - let otherwise_block = *target_blocks.last().unwrap(); + let otherwise_block = target_block(TestBranch::Failure); let switch_targets = SwitchTargets::new( - options.values().copied().zip(target_blocks), + target_blocks.iter().filter_map(|(&branch, &block)| { + if let TestBranch::Constant(_, bits) = branch { + Some((bits, block)) + } else { + None + } + }), otherwise_block, ); let terminator = TerminatorKind::SwitchInt { @@ -198,18 +125,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } TestKind::If => { - let [false_bb, true_bb] = *target_blocks else { - bug!("`TestKind::If` should have two targets") - }; - let terminator = TerminatorKind::if_(Operand::Copy(place), true_bb, false_bb); + let success_block = target_block(TestBranch::Success); + let fail_block = target_block(TestBranch::Failure); + let terminator = + TerminatorKind::if_(Operand::Copy(place), success_block, fail_block); self.cfg.terminate(block, self.source_info(match_start_span), terminator); } TestKind::Eq { value, ty } => { let tcx = self.tcx; - let [success_block, fail_block] = *target_blocks else { - bug!("`TestKind::Eq` should have two target blocks") - }; + let success_block = target_block(TestBranch::Success); + let fail_block = target_block(TestBranch::Failure); if let ty::Adt(def, _) = ty.kind() && Some(def.did()) == tcx.lang_items().string() { @@ -286,9 +212,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } TestKind::Range(ref range) => { - let [success, fail] = *target_blocks else { - bug!("`TestKind::Range` should have two target blocks"); - }; + let success = target_block(TestBranch::Success); + let fail = target_block(TestBranch::Failure); // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. let val = Operand::Copy(place); @@ -333,15 +258,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // expected = let expected = self.push_usize(block, source_info, len); - let [true_bb, false_bb] = *target_blocks else { - bug!("`TestKind::Len` should have two target blocks"); - }; + let success_block = target_block(TestBranch::Success); + let fail_block = target_block(TestBranch::Failure); // result = actual == expected OR result = actual < expected // branch based on result self.compare( block, - true_bb, - false_bb, + success_block, + fail_block, source_info, op, Operand::Move(actual), @@ -526,10 +450,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Given that we are performing `test` against `test_place`, this job /// sorts out what the status of `candidate` will be after the test. See - /// `test_candidates` for the usage of this function. The returned index is - /// the index that this candidate should be placed in the - /// `target_candidates` vec. The candidate may be modified to update its - /// `match_pairs`. + /// `test_candidates` for the usage of this function. The candidate may + /// be modified to update its `match_pairs`. /// /// So, for example, if this candidate is `x @ Some(P0)` and the `Test` is /// a variant test, then we would modify the candidate to be `(x as @@ -551,12 +473,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// that it *doesn't* apply. For now, we return false, indicate that the /// test does not apply to this candidate, but it might be we can get /// tighter match code if we do something a bit different. - pub(super) fn sort_candidate<'pat>( + pub(super) fn sort_candidate( &mut self, test_place: &PlaceBuilder<'tcx>, test: &Test<'tcx>, - candidate: &mut Candidate<'pat, 'tcx>, - ) -> Option { + candidate: &mut Candidate<'_, 'tcx>, + sorted_candidates: &FxIndexMap, Vec<&mut Candidate<'_, 'tcx>>>, + ) -> Option> { // Find the match_pair for this place (if any). At present, // afaik, there can be at most one. (In the future, if we // adopted a more general `@` operator, there might be more @@ -571,12 +494,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // If we are performing a variant switch, then this // informs variant patterns, but nothing else. ( - &TestKind::Switch { adt_def: tested_adt_def, .. }, + &TestKind::Switch { adt_def: tested_adt_def }, &TestCase::Variant { adt_def, variant_index }, ) => { assert_eq!(adt_def, tested_adt_def); fully_matched = true; - Some(variant_index.as_usize()) + Some(TestBranch::Variant(variant_index)) } // If we are performing a switch over integers, then this informs integer @@ -584,35 +507,54 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // // FIXME(#29623) we could use PatKind::Range to rule // things out here, in some cases. - (TestKind::SwitchInt { options }, TestCase::Constant { value }) + (TestKind::SwitchInt, &TestCase::Constant { value }) if is_switch_ty(match_pair.pattern.ty) => { - fully_matched = true; - let index = options.get_index_of(value).unwrap(); - Some(index) + // Beware: there might be some ranges sorted into the failure case; we must not add + // a success case that could be matched by one of these ranges. + let is_covering_range = |test_case: &TestCase<'_, 'tcx>| { + test_case.as_range().is_some_and(|range| { + matches!(range.contains(value, self.tcx, self.param_env), None | Some(true)) + }) + }; + let is_conflicting_candidate = |candidate: &&mut Candidate<'_, 'tcx>| { + candidate + .match_pairs + .iter() + .any(|mp| mp.place == *test_place && is_covering_range(&mp.test_case)) + }; + if sorted_candidates + .get(&TestBranch::Failure) + .is_some_and(|candidates| candidates.iter().any(is_conflicting_candidate)) + { + fully_matched = false; + None + } else { + fully_matched = true; + let bits = value.eval_bits(self.tcx, self.param_env); + Some(TestBranch::Constant(value, bits)) + } } - (TestKind::SwitchInt { options }, TestCase::Range(range)) => { + (TestKind::SwitchInt, TestCase::Range(range)) => { fully_matched = false; let not_contained = - self.values_not_contained_in_range(&*range, options).unwrap_or(false); + sorted_candidates.keys().filter_map(|br| br.as_constant()).copied().all( + |val| matches!(range.contains(val, self.tcx, self.param_env), Some(false)), + ); not_contained.then(|| { // No switch values are contained in the pattern range, // so the pattern can be matched only if this test fails. - options.len() + TestBranch::Failure }) } - (&TestKind::If, TestCase::Constant { value }) => { + (TestKind::If, TestCase::Constant { value }) => { fully_matched = true; let value = value.try_eval_bool(self.tcx, self.param_env).unwrap_or_else(|| { span_bug!(test.span, "expected boolean value but got {value:?}") }); - Some(value as usize) - } - (&TestKind::If, _) => { - fully_matched = false; - None + Some(if value { TestBranch::Success } else { TestBranch::Failure }) } ( @@ -624,14 +566,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // on true, min_len = len = $actual_length, // on false, len != $actual_length fully_matched = true; - Some(0) + Some(TestBranch::Success) } (Ordering::Less, _) => { // test_len < pat_len. If $actual_len = test_len, // then $actual_len < pat_len and we don't have // enough elements. fully_matched = false; - Some(1) + Some(TestBranch::Failure) } (Ordering::Equal | Ordering::Greater, true) => { // This can match both if $actual_len = test_len >= pat_len, @@ -643,7 +585,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // test_len != pat_len, so if $actual_len = test_len, then // $actual_len != pat_len. fully_matched = false; - Some(1) + Some(TestBranch::Failure) } } } @@ -657,20 +599,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // $actual_len >= test_len = pat_len, // so we can match. fully_matched = true; - Some(0) + Some(TestBranch::Success) } (Ordering::Less, _) | (Ordering::Equal, false) => { // test_len <= pat_len. If $actual_len < test_len, // then it is also < pat_len, so the test passing is // necessary (but insufficient). fully_matched = false; - Some(0) + Some(TestBranch::Success) } (Ordering::Greater, false) => { // test_len > pat_len. If $actual_len >= test_len > pat_len, // then we know we won't have a match. fully_matched = false; - Some(1) + Some(TestBranch::Failure) } (Ordering::Greater, true) => { // test_len < pat_len, and is therefore less @@ -684,12 +626,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { (TestKind::Range(test), &TestCase::Range(pat)) => { if test.as_ref() == pat { fully_matched = true; - Some(0) + Some(TestBranch::Success) } else { fully_matched = false; // If the testing range does not overlap with pattern range, // the pattern can be matched only if this test fails. - if !test.overlaps(pat, self.tcx, self.param_env)? { Some(1) } else { None } + if !test.overlaps(pat, self.tcx, self.param_env)? { + Some(TestBranch::Failure) + } else { + None + } } } (TestKind::Range(range), &TestCase::Constant { value }) => { @@ -697,7 +643,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if !range.contains(value, self.tcx, self.param_env)? { // `value` is not contained in the testing range, // so `value` can be matched only if this test fails. - Some(1) + Some(TestBranch::Failure) } else { None } @@ -708,12 +654,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if test_val == case_val => { fully_matched = true; - Some(0) + Some(TestBranch::Success) } ( TestKind::Switch { .. } | TestKind::SwitchInt { .. } + | TestKind::If | TestKind::Len { .. } | TestKind::Range { .. } | TestKind::Eq { .. }, @@ -734,36 +681,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ret } - - fn values_not_contained_in_range( - &self, - range: &PatRange<'tcx>, - options: &FxIndexMap, u128>, - ) -> Option { - for &val in options.keys() { - if range.contains(val, self.tcx, self.param_env)? { - return Some(false); - } - } - - Some(true) - } -} - -impl Test<'_> { - pub(super) fn targets(&self) -> usize { - match self.kind { - TestKind::Eq { .. } | TestKind::Range(_) | TestKind::Len { .. } | TestKind::If => 2, - TestKind::Switch { adt_def, .. } => { - // While the switch that we generate doesn't test for all - // variants, we have a target for each variant and the - // otherwise case, and we make sure that all of the cases not - // specified have the same block. - adt_def.variants().len() + 1 - } - TestKind::SwitchInt { ref options } => options.len() + 1, - } - } } fn is_switch_ty(ty: Ty<'_>) -> bool { diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 294b27def165..45954bdb114f 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -631,7 +631,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - | DefKind::AssocConst | DefKind::AnonConst | DefKind::InlineConst - | DefKind::Static(_) => (vec![], tcx.type_of(def_id).instantiate_identity(), None), + | DefKind::Static { .. } => (vec![], tcx.type_of(def_id).instantiate_identity(), None), DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => { let sig = tcx.liberate_late_bound_regions( def_id.to_def_id(), diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 2b4c65418577..848da56f9816 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -6,7 +6,7 @@ use rustc_errors::{ }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; -use rustc_pattern_analysis::{errors::Uncovered, rustc::RustcMatchCheckCtxt}; +use rustc_pattern_analysis::{errors::Uncovered, rustc::RustcPatCtxt}; use rustc_span::symbol::Symbol; use rustc_span::Span; @@ -455,7 +455,7 @@ pub enum UnusedUnsafeEnclosing { } pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { - pub cx: &'m RustcMatchCheckCtxt<'p, 'tcx>, + pub cx: &'m RustcPatCtxt<'p, 'tcx>, pub expr_span: Span, pub span: Span, pub ty: Ty<'tcx>, diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 1e93e126b706..d4a347975dba 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -63,7 +63,7 @@ impl<'tcx> Cx<'tcx> { // ignore for purposes of the MIR None } - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { let remainder_scope = region::Scope { id: block_id, data: region::ScopeData::Remainder(region::FirstStatementIndex::new( diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 2318e84292b8..52d32a3b6266 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -942,7 +942,7 @@ impl<'tcx> Cx<'tcx> { // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is // a constant reference (or constant raw pointer for `static mut`) in MIR - Res::Def(DefKind::Static(_), id) => { + Res::Def(DefKind::Static { .. }, id) => { let ty = self.tcx.static_ptr_ty(id); let temp_lifetime = self .rvalue_scopes diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 2685bae4d09c..20d3b3f98ce3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1,7 +1,7 @@ use rustc_pattern_analysis::errors::Uncovered; use rustc_pattern_analysis::rustc::{ - Constructor, DeconstructedPat, MatchArm, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness, - UsefulnessReport, WitnessPat, + Constructor, DeconstructedPat, MatchArm, RustcPatCtxt as PatCtxt, Usefulness, UsefulnessReport, + WitnessPat, }; use crate::errors::*; @@ -276,7 +276,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { fn lower_pattern( &mut self, - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, pat: &'p Pat<'tcx>, ) -> Result<&'p DeconstructedPat<'p, 'tcx>, ErrorGuaranteed> { if let Err(err) = pat.pat_error_reported() { @@ -375,7 +375,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { whole_match_span: Option, scrutinee: Option<&Expr<'tcx>>, scrut_span: Span, - ) -> MatchCheckCtxt<'p, 'tcx> { + ) -> PatCtxt<'p, 'tcx> { let refutable = match refutability { Irrefutable => false, Refutable => true, @@ -384,7 +384,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // require validity. let known_valid_scrutinee = scrutinee.map(|scrut| self.is_known_valid_scrutinee(scrut)).unwrap_or(true); - MatchCheckCtxt { + PatCtxt { tcx: self.tcx, typeck_results: self.typeck_results, param_env: self.param_env, @@ -400,7 +400,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { fn analyze_patterns( &mut self, - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, arms: &[MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, ) -> Result, ErrorGuaranteed> { @@ -420,9 +420,9 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { { let mut redundant_subpats = redundant_subpats.clone(); // Emit lints in the order in which they occur in the file. - redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span); + redundant_subpats.sort_unstable_by_key(|pat| pat.data().span); for pat in redundant_subpats { - report_unreachable_pattern(cx, arm.arm_data, pat.data().unwrap().span, None) + report_unreachable_pattern(cx, arm.arm_data, pat.data().span, None) } } } @@ -584,7 +584,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { pat: &'p Pat<'tcx>, refutability: RefutableFlag, scrut: Option<&Expr<'tcx>>, - ) -> Result<(MatchCheckCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> { + ) -> Result<(PatCtxt<'p, 'tcx>, UsefulnessReport<'p, 'tcx>), ErrorGuaranteed> { let cx = self.new_cx(refutability, None, scrut, pat.span); let pat = self.lower_pattern(&cx, pat)?; let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }]; @@ -849,7 +849,7 @@ fn check_for_bindings_named_same_as_variants( /// Check that never patterns are only used on inhabited types. fn check_never_pattern<'tcx>( - cx: &MatchCheckCtxt<'_, 'tcx>, + cx: &PatCtxt<'_, 'tcx>, pat: &Pat<'tcx>, ) -> Result<(), ErrorGuaranteed> { if let PatKind::Never = pat.kind { @@ -884,7 +884,7 @@ fn report_irrefutable_let_patterns( /// Report unreachable arms, if any. fn report_unreachable_pattern<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, hir_id: HirId, span: Span, catchall: Option, @@ -898,17 +898,14 @@ fn report_unreachable_pattern<'p, 'tcx>( } /// Report unreachable arms, if any. -fn report_arm_reachability<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, - report: &UsefulnessReport<'p, 'tcx>, -) { +fn report_arm_reachability<'p, 'tcx>(cx: &PatCtxt<'p, 'tcx>, report: &UsefulnessReport<'p, 'tcx>) { let mut catchall = None; for (arm, is_useful) in report.arm_usefulness.iter() { if matches!(is_useful, Usefulness::Redundant) { - report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().unwrap().span, catchall) + report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().span, catchall) } if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) { - catchall = Some(arm.pat.data().unwrap().span); + catchall = Some(arm.pat.data().span); } } } @@ -917,14 +914,16 @@ fn report_arm_reachability<'p, 'tcx>( fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool { match pat.ctor() { Constructor::Wildcard => true, - Constructor::Struct | Constructor::Ref => pat.iter_fields().all(|pat| pat_is_catchall(pat)), + Constructor::Struct | Constructor::Ref => { + pat.iter_fields().all(|ipat| pat_is_catchall(&ipat.pat)) + } _ => false, } } /// Report that a match is not exhaustive. fn report_non_exhaustive_match<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, thir: &Thir<'tcx>, scrut_ty: Ty<'tcx>, sp: Span, @@ -1124,7 +1123,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( } fn joined_uncovered_patterns<'p, 'tcx>( - cx: &MatchCheckCtxt<'p, 'tcx>, + cx: &PatCtxt<'p, 'tcx>, witnesses: &[WitnessPat<'p, 'tcx>], ) -> String { const LIMIT: usize = 3; @@ -1145,7 +1144,7 @@ fn joined_uncovered_patterns<'p, 'tcx>( } fn collect_non_exhaustive_tys<'tcx>( - cx: &MatchCheckCtxt<'_, 'tcx>, + cx: &PatCtxt<'_, 'tcx>, pat: &WitnessPat<'_, 'tcx>, non_exhaustive_tys: &mut FxIndexSet>, ) { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 0b03cb52373a..ac3043afcff0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -453,7 +453,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { Res::Def(DefKind::ConstParam, _) => { self.tcx.dcx().emit_err(ConstParamInPattern { span }) } - Res::Def(DefKind::Static(_), _) => { + Res::Def(DefKind::Static { .. }, _) => { self.tcx.dcx().emit_err(StaticInPattern { span }) } _ => self.tcx.dcx().emit_err(NonConstPath { span }), diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 19109735d487..c3e932fe1872 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -3,7 +3,7 @@ //! Currently, this pass only propagates scalar values. use rustc_const_eval::interpret::{ - ImmTy, Immediate, InterpCx, OpTy, PlaceTy, PointerArithmetic, Projectable, + HasStaticRootDefId, ImmTy, Immediate, InterpCx, OpTy, PlaceTy, PointerArithmetic, Projectable, }; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; @@ -889,6 +889,12 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { pub(crate) struct DummyMachine; +impl HasStaticRootDefId for DummyMachine { + fn static_def_id(&self) -> Option { + None + } +} + impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine { rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>); type MemoryKind = !; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index cd9b98e4f32c..0491de782659 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -333,7 +333,7 @@ fn mir_promoted( } DefKind::AssocConst | DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::InlineConst | DefKind::AnonConst => tcx.mir_const_qualif(def), _ => ConstQualifs::default(), diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index a18448eabf33..33a446eb55a1 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -380,8 +380,12 @@ fn collect_items_rec<'tcx>( // Sanity check whether this ended up being collected accidentally debug_assert!(should_codegen_locally(tcx, &instance)); - let ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); - visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items); + let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() }; + // Nested statics have no type. + if !nested { + let ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items); + } recursion_depth_reset = None; @@ -1037,7 +1041,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> return false; } - if let DefKind::Static(_) = tcx.def_kind(def_id) { + if let DefKind::Static { .. } = tcx.def_kind(def_id) { // We cannot monomorphize statics from upstream crates. return false; } @@ -1254,7 +1258,7 @@ impl<'v> RootCollector<'_, 'v> { ); self.output.push(dummy_spanned(MonoItem::GlobalAsm(id))); } - DefKind::Static(..) => { + DefKind::Static { .. } => { let def_id = id.owner_id.to_def_id(); debug!("RootCollector: ItemKind::Static({})", self.tcx.def_path_str(def_id)); self.output.push(dummy_spanned(MonoItem::Static(def_id))); diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 8bebc30e4356..296eb3120ee4 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -175,9 +175,7 @@ where } // Mark one CGU for dead code, if necessary. - let instrument_dead_code = - tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions(); - if instrument_dead_code { + if tcx.sess.instrument_coverage() { mark_code_coverage_dead_code_cgu(&mut codegen_units); } diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 1070d1a1380d..6d237df073f8 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -150,7 +150,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::Fn | DefKind::Const | DefKind::ConstParam - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Ctor(_, _) | DefKind::AssocFn | DefKind::AssocConst diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 2edf2111de73..163d10d03f03 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -449,9 +449,13 @@ impl<'a> Parser<'a> { prev_token_before_parsing: Token, error: &mut Diag<'_>, ) { - if ((style == PathStyle::Expr && self.parse_paren_comma_seq(|p| p.parse_expr()).is_ok()) - || (style == PathStyle::Pat - && self + match style { + PathStyle::Expr + if let Ok(_) = self + .parse_paren_comma_seq(|p| p.parse_expr()) + .map_err(|error| error.cancel()) => {} + PathStyle::Pat + if let Ok(_) = self .parse_paren_comma_seq(|p| { p.parse_pat_allow_top_alt( None, @@ -460,25 +464,31 @@ impl<'a> Parser<'a> { CommaRecoveryMode::LikelyTuple, ) }) - .is_ok())) - && !matches!(self.token.kind, token::ModSep | token::RArrow) - { - error.span_suggestion_verbose( - prev_token_before_parsing.span, - format!( - "consider removing the `::` here to {}", - match style { - PathStyle::Expr => "call the expression", - PathStyle::Pat => "turn this into a tuple struct pattern", - _ => { - return; - } - } - ), - "", - Applicability::MaybeIncorrect, - ); + .map_err(|error| error.cancel()) => {} + _ => { + return; + } } + + if let token::ModSep | token::RArrow = self.token.kind { + return; + } + + error.span_suggestion_verbose( + prev_token_before_parsing.span, + format!( + "consider removing the `::` here to {}", + match style { + PathStyle::Expr => "call the expression", + PathStyle::Pat => "turn this into a tuple struct pattern", + _ => { + return; + } + } + ), + "", + Applicability::MaybeIncorrect, + ); } /// Parses generic args (within a path segment) with recovery for extra leading angle brackets. diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 73f5829adec6..fc907760531f 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -254,7 +254,7 @@ impl<'a> Parser<'a> { let local = this.parse_local(attrs)?; // FIXME - maybe capture semicolon in recovery? Ok(( - this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), TrailingToken::None, )) })?; @@ -278,7 +278,7 @@ impl<'a> Parser<'a> { } else { TrailingToken::None }; - Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), trailing)) + Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) }) } @@ -764,7 +764,7 @@ impl<'a> Parser<'a> { } } StmtKind::Expr(_) | StmtKind::MacCall(_) => {} - StmtKind::Local(local) if let Err(mut e) = self.expect_semi() => { + StmtKind::Let(local) if let Err(mut e) = self.expect_semi() => { // We might be at the `,` in `let x = foo;`. Try to recover. match &mut local.kind { LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => { @@ -820,7 +820,7 @@ impl<'a> Parser<'a> { } eat_semi = false; } - StmtKind::Empty | StmtKind::Item(_) | StmtKind::Local(_) | StmtKind::Semi(_) => { + StmtKind::Empty | StmtKind::Item(_) | StmtKind::Let(_) | StmtKind::Semi(_) => { eat_semi = false } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 91ab5b30dea3..eb2399f7a64f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2444,7 +2444,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { // When checking statements ignore expressions, they will be checked later. - if let hir::StmtKind::Local(l) = stmt.kind { + if let hir::StmtKind::Let(l) = stmt.kind { self.check_attributes(l.hir_id, stmt.span, Target::Statement, None); } intravisit::walk_stmt(self, stmt) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index cdfde2b94052..0371bab83c04 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -801,7 +801,7 @@ fn check_foreign_item( worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>, id: hir::ForeignItemId, ) { - if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn) + if matches!(tcx.def_kind(id.owner_id), DefKind::Static { .. } | DefKind::Fn) && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id) { worklist.push((id.owner_id.def_id, comes_from_allow)); @@ -1058,7 +1058,7 @@ impl<'tcx> DeadVisitor<'tcx> { DefKind::AssocConst | DefKind::AssocFn | DefKind::Fn - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Const | DefKind::TyAlias | DefKind::Enum diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index be6ba585d200..d742ffc69e45 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -277,7 +277,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) { record_variants!( (self, s, s.kind, Id::Node(s.hir_id), hir, Stmt, StmtKind), - [Local, Item, Expr, Semi] + [Let, Item, Expr, Semi] ); hir_visit::walk_stmt(self, s) } @@ -539,7 +539,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_stmt(&mut self, s: &'v ast::Stmt) { record_variants!( (self, s, s.kind, Id::None, ast, Stmt, StmtKind), - [Local, Item, Expr, Semi, Empty, MacCall] + [Let, Item, Expr, Semi, Empty, MacCall] ); ast_visit::walk_stmt(self, s) } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index e5033e1f51f2..f0c3f7a385d6 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -771,7 +771,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn propagate_through_stmt(&mut self, stmt: &hir::Stmt<'_>, succ: LiveNode) -> LiveNode { match stmt.kind { - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { // Note: we mark the variable as defined regardless of whether // there is an initializer. Initially I had thought to only mark // the live variable as defined if it was initialized, and then we diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 27c9c1306e6a..bd34b0597e25 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -280,7 +280,7 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { match stmt.kind { StmtKind::Item(..) => {} - StmtKind::Local(..) => { + StmtKind::Let(..) => { self.items.push((ItemKind::NonAsm, stmt.span)); } StmtKind::Expr(expr) | StmtKind::Semi(expr) => { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index f46f831ddd7c..e86c0522b3cd 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -13,6 +13,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::privacy::{self, Level}; +use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::CrateType; @@ -73,7 +74,7 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> { match res { // Reachable constants and reachable statics can have their contents inlined // into other crates. Mark them as reachable and recurse into their body. - Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static(_), _) => { + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static { .. }, _) => { self.worklist.push(def_id); } _ => { @@ -197,10 +198,23 @@ impl<'tcx> ReachableContext<'tcx> { // Reachable constants will be inlined into other crates // unconditionally, so we need to make sure that their // contents are also reachable. - hir::ItemKind::Const(_, _, init) | hir::ItemKind::Static(_, _, init) => { + hir::ItemKind::Const(_, _, init) => { self.visit_nested_body(init); } + // Reachable statics are inlined if read from another constant or static + // in other crates. Additionally anonymous nested statics may be created + // when evaluating a static, so preserve those, too. + hir::ItemKind::Static(_, _, init) => { + // FIXME(oli-obk): remove this body walking and instead walk the evaluated initializer + // to find nested items that end up in the final value instead of also marking symbols + // as reachable that are only needed for evaluation. + self.visit_nested_body(init); + if let Ok(alloc) = self.tcx.eval_static_initializer(item.owner_id.def_id) { + self.propagate_statics_from_alloc(item.owner_id.def_id, alloc); + } + } + // These are normal, nothing reachable about these // inherently and their children are already in the // worklist, as determined by the privacy pass @@ -266,6 +280,29 @@ impl<'tcx> ReachableContext<'tcx> { } } } + + /// Finds anonymous nested statics created for nested allocations and adds them to `reachable_symbols`. + fn propagate_statics_from_alloc(&mut self, root: LocalDefId, alloc: ConstAllocation<'tcx>) { + if !self.any_library { + return; + } + for (_, prov) in alloc.0.provenance().ptrs().iter() { + match self.tcx.global_alloc(prov.alloc_id()) { + GlobalAlloc::Static(def_id) => { + if let Some(def_id) = def_id.as_local() + && self.tcx.local_parent(def_id) == root + // This is the main purpose of this function: add the def_id we find + // to `reachable_symbols`. + && self.reachable_symbols.insert(def_id) + && let Ok(alloc) = self.tcx.eval_static_initializer(def_id) + { + self.propagate_statics_from_alloc(root, alloc); + } + } + GlobalAlloc::Function(_) | GlobalAlloc::VTable(_, _) | GlobalAlloc::Memory(_) => {} + } + } + } } fn check_item<'tcx>( diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 69e294e47a56..bbb89576ef7e 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -40,7 +40,7 @@ //! - That have no non-trivial intersection with any of the constructors in the column (i.e. they're //! each either disjoint with or covered by any given column constructor). //! -//! We compute this in two steps: first [`TypeCx::ctors_for_ty`] determines the +//! We compute this in two steps: first [`PatCx::ctors_for_ty`] determines the //! set of all possible constructors for the type. Then [`ConstructorSet::split`] looks at the //! column of constructors and splits the set into groups accordingly. The precise invariants of //! [`ConstructorSet::split`] is described in [`SplitConstructorSet`]. @@ -136,7 +136,7 @@ //! the algorithm can't distinguish them from a nonempty constructor. The only known case where this //! could happen is the `[..]` pattern on `[!; N]` with `N > 0` so we must take care to not emit it. //! -//! This is all handled by [`TypeCx::ctors_for_ty`] and +//! This is all handled by [`PatCx::ctors_for_ty`] and //! [`ConstructorSet::split`]. The invariants of [`SplitConstructorSet`] are also of interest. //! //! @@ -162,7 +162,7 @@ use self::MaybeInfiniteInt::*; use self::SliceKind::*; use crate::index; -use crate::TypeCx; +use crate::PatCx; /// Whether we have seen a constructor in the column or not. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] @@ -195,8 +195,6 @@ pub enum MaybeInfiniteInt { /// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite_{int,uint}`. #[non_exhaustive] Finite(u128), - /// The integer after `u128::MAX`. We need it to represent `x..=u128::MAX` as an exclusive range. - JustAfterMax, PosInfinity, } @@ -232,18 +230,18 @@ impl MaybeInfiniteInt { pub fn minus_one(self) -> Option { match self { Finite(n) => n.checked_sub(1).map(Finite), - JustAfterMax => Some(Finite(u128::MAX)), x => Some(x), } } - /// Note: this will not turn a finite value into an infinite one or vice-versa. + /// Note: this will turn `u128::MAX` into `PosInfinity`. This means `plus_one` and `minus_one` + /// are not strictly inverses, but that poses no problem in our use of them. + /// this will not turn a finite value into an infinite one or vice-versa. pub fn plus_one(self) -> Option { match self { Finite(n) => match n.checked_add(1) { Some(m) => Some(Finite(m)), - None => Some(JustAfterMax), + None => Some(PosInfinity), }, - JustAfterMax => None, x => Some(x), } } @@ -277,8 +275,7 @@ impl IntRange { } /// Construct a range with these boundaries. - /// `lo` must not be `PosInfinity` or `JustAfterMax`. `hi` must not be `NegInfinity`. - /// If `end` is `Included`, `hi` must also not be `JustAfterMax`. + /// `lo` must not be `PosInfinity`. `hi` must not be `NegInfinity`. #[inline] pub fn from_range(lo: MaybeInfiniteInt, mut hi: MaybeInfiniteInt, end: RangeEnd) -> IntRange { if end == RangeEnd::Included { @@ -423,7 +420,7 @@ pub enum SliceKind { } impl SliceKind { - fn arity(self) -> usize { + pub fn arity(self) -> usize { match self { FixedLen(length) => length, VarLen(prefix, suffix) => prefix + suffix, @@ -462,7 +459,7 @@ impl Slice { Slice { array_len, kind } } - pub(crate) fn arity(self) -> usize { + pub fn arity(self) -> usize { self.kind.arity() } @@ -651,7 +648,7 @@ impl OpaqueId { /// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and /// `Fields`. #[derive(Debug)] -pub enum Constructor { +pub enum Constructor { /// Tuples and structs. Struct, /// Enum variants. @@ -696,7 +693,7 @@ pub enum Constructor { PrivateUninhabited, } -impl Clone for Constructor { +impl Clone for Constructor { fn clone(&self) -> Self { match self { Constructor::Struct => Constructor::Struct, @@ -720,7 +717,7 @@ impl Clone for Constructor { } } -impl Constructor { +impl Constructor { pub(crate) fn is_non_exhaustive(&self) -> bool { matches!(self, NonExhaustive) } @@ -838,7 +835,7 @@ pub enum VariantVisibility { /// In terms of division of responsibility, [`ConstructorSet::split`] handles all of the /// `exhaustive_patterns` feature. #[derive(Debug)] -pub enum ConstructorSet { +pub enum ConstructorSet { /// The type is a tuple or struct. `empty` tracks whether the type is empty. Struct { empty: bool }, /// This type has the following list of constructors. If `variants` is empty and @@ -889,13 +886,13 @@ pub enum ConstructorSet { /// of the `ConstructorSet` for the type, yet if we forgot to include them in `present` we would be /// ignoring any row with `Opaque`s in the algorithm. Hence the importance of point 4. #[derive(Debug)] -pub struct SplitConstructorSet { +pub struct SplitConstructorSet { pub present: SmallVec<[Constructor; 1]>, pub missing: Vec>, pub missing_empty: Vec>, } -impl ConstructorSet { +impl ConstructorSet { /// This analyzes a column of constructors to 1/ determine which constructors of the type (if /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 21a61d46ccb7..75b7b7c8f678 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -4,7 +4,7 @@ use rustc_middle::thir::Pat; use rustc_middle::ty::Ty; use rustc_span::Span; -use crate::rustc::{RustcMatchCheckCtxt, WitnessPat}; +use crate::rustc::{RustcPatCtxt, WitnessPat}; #[derive(Subdiagnostic)] #[label(pattern_analysis_uncovered)] @@ -21,7 +21,7 @@ pub struct Uncovered<'tcx> { impl<'tcx> Uncovered<'tcx> { pub fn new<'p>( span: Span, - cx: &RustcMatchCheckCtxt<'p, 'tcx>, + cx: &RustcPatCtxt<'p, 'tcx>, witnesses: Vec>, ) -> Self where diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index f632eaf7ea4f..5c57c990323c 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -84,7 +84,7 @@ pub struct PrivateUninhabitedField(pub bool); /// Context that provides type information about constructors. /// /// Most of the crate is parameterized on a type that implements this trait. -pub trait TypeCx: Sized + fmt::Debug { +pub trait PatCx: Sized + fmt::Debug { /// The type of a pattern. type Ty: Clone + fmt::Debug; /// Errors that can abort analysis. @@ -155,34 +155,34 @@ pub trait TypeCx: Sized + fmt::Debug { /// The arm of a match expression. #[derive(Debug)] -pub struct MatchArm<'p, Cx: TypeCx> { +pub struct MatchArm<'p, Cx: PatCx> { pub pat: &'p DeconstructedPat, pub has_guard: bool, pub arm_data: Cx::ArmData, } -impl<'p, Cx: TypeCx> Clone for MatchArm<'p, Cx> { +impl<'p, Cx: PatCx> Clone for MatchArm<'p, Cx> { fn clone(&self) -> Self { Self { pat: self.pat, has_guard: self.has_guard, arm_data: self.arm_data } } } -impl<'p, Cx: TypeCx> Copy for MatchArm<'p, Cx> {} +impl<'p, Cx: PatCx> Copy for MatchArm<'p, Cx> {} /// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are /// useful, and runs some lints. #[cfg(feature = "rustc")] pub fn analyze_match<'p, 'tcx>( - tycx: &rustc::RustcMatchCheckCtxt<'p, 'tcx>, + tycx: &rustc::RustcPatCtxt<'p, 'tcx>, arms: &[rustc::MatchArm<'p, 'tcx>], scrut_ty: Ty<'tcx>, pattern_complexity_limit: Option, ) -> Result, ErrorGuaranteed> { use lints::lint_nonexhaustive_missing_variants; - use usefulness::{compute_match_usefulness, ValidityConstraint}; + use usefulness::{compute_match_usefulness, PlaceValidity}; let scrut_ty = tycx.reveal_opaque_ty(scrut_ty); - let scrut_validity = ValidityConstraint::from_bool(tycx.known_valid_scrutinee); + let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee); let report = compute_match_usefulness(tycx, arms, scrut_ty, scrut_validity, pattern_complexity_limit)?; diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 16530960656f..3ca5ebdb0dd1 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -4,15 +4,15 @@ use rustc_span::ErrorGuaranteed; use crate::constructor::Constructor; use crate::errors::{NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered}; use crate::pat_column::PatternColumn; -use crate::rustc::{RevealedTy, RustcMatchCheckCtxt, WitnessPat}; +use crate::rustc::{RevealedTy, RustcPatCtxt, WitnessPat}; use crate::MatchArm; /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned /// in a given column. #[instrument(level = "debug", skip(cx), ret)] fn collect_nonexhaustive_missing_variants<'p, 'tcx>( - cx: &RustcMatchCheckCtxt<'p, 'tcx>, - column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, + cx: &RustcPatCtxt<'p, 'tcx>, + column: &PatternColumn<'p, RustcPatCtxt<'p, 'tcx>>, ) -> Result>, ErrorGuaranteed> { let Some(&ty) = column.head_ty() else { return Ok(Vec::new()); @@ -57,9 +57,9 @@ fn collect_nonexhaustive_missing_variants<'p, 'tcx>( } pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( - rcx: &RustcMatchCheckCtxt<'p, 'tcx>, - arms: &[MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>], - pat_column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, + rcx: &RustcPatCtxt<'p, 'tcx>, + arms: &[MatchArm<'p, RustcPatCtxt<'p, 'tcx>>], + pat_column: &PatternColumn<'p, RustcPatCtxt<'p, 'tcx>>, scrut_ty: RevealedTy<'tcx>, ) -> Result<(), ErrorGuaranteed> { if !matches!( @@ -98,7 +98,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>( }; use rustc_errors::LintDiagnostic; - let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().unwrap().span, ""); + let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().span, ""); err.primary_message(decorator.msg()); decorator.decorate_lint(&mut err); err.emit(); diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index decbfa5c0cf4..e3667d44bc97 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -5,7 +5,7 @@ use std::fmt; use smallvec::{smallvec, SmallVec}; use crate::constructor::{Constructor, Slice, SliceKind}; -use crate::{PrivateUninhabitedField, TypeCx}; +use crate::{PatCx, PrivateUninhabitedField}; use self::Constructor::*; @@ -20,32 +20,42 @@ impl PatId { } } +/// A pattern with an index denoting which field it corresponds to. +pub struct IndexedPat { + pub idx: usize, + pub pat: DeconstructedPat, +} + /// Values and patterns can be represented as a constructor applied to some fields. This represents /// a pattern in this form. A `DeconstructedPat` will almost always come from user input; the only /// exception are some `Wildcard`s introduced during pattern lowering. -pub struct DeconstructedPat { +pub struct DeconstructedPat { ctor: Constructor, - fields: Vec>, + fields: Vec>, + /// The number of fields in this pattern. E.g. if the pattern is `SomeStruct { field12: true, .. + /// }` this would be the total number of fields of the struct. + /// This is also the same as `self.ctor.arity(self.ty)`. + arity: usize, ty: Cx::Ty, - /// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not - /// correspond to a user-supplied pattern. - data: Option, + /// Extra data to store in a pattern. + data: Cx::PatData, /// Globally-unique id used to track usefulness at the level of subpatterns. pub(crate) uid: PatId, } -impl DeconstructedPat { - pub fn wildcard(ty: Cx::Ty) -> Self { - DeconstructedPat { ctor: Wildcard, fields: Vec::new(), ty, data: None, uid: PatId::new() } - } - +impl DeconstructedPat { pub fn new( ctor: Constructor, - fields: Vec>, + fields: Vec>, + arity: usize, ty: Cx::Ty, data: Cx::PatData, ) -> Self { - DeconstructedPat { ctor, fields, ty, data: Some(data), uid: PatId::new() } + DeconstructedPat { ctor, fields, arity, ty, data, uid: PatId::new() } + } + + pub fn at_index(self, idx: usize) -> IndexedPat { + IndexedPat { idx, pat: self } } pub(crate) fn is_or_pat(&self) -> bool { @@ -58,13 +68,15 @@ impl DeconstructedPat { pub fn ty(&self) -> &Cx::Ty { &self.ty } - /// Returns the extra data stored in a pattern. Returns `None` if the pattern is a wildcard that - /// does not correspond to a user-supplied pattern. - pub fn data(&self) -> Option<&Cx::PatData> { - self.data.as_ref() + /// Returns the extra data stored in a pattern. + pub fn data(&self) -> &Cx::PatData { + &self.data + } + pub fn arity(&self) -> usize { + self.arity } - pub fn iter_fields<'a>(&'a self) -> impl Iterator> { + pub fn iter_fields<'a>(&'a self) -> impl Iterator> { self.fields.iter() } @@ -73,36 +85,40 @@ impl DeconstructedPat { pub(crate) fn specialize<'a>( &'a self, other_ctor: &Constructor, - ctor_arity: usize, + other_ctor_arity: usize, ) -> SmallVec<[PatOrWild<'a, Cx>; 2]> { - let wildcard_sub_tys = || (0..ctor_arity).map(|_| PatOrWild::Wild).collect(); - match (&self.ctor, other_ctor) { - // Return a wildcard for each field of `other_ctor`. - (Wildcard, _) => wildcard_sub_tys(), + if matches!(other_ctor, PrivateUninhabited) { // Skip this column. - (_, PrivateUninhabited) => smallvec![], - // The only non-trivial case: two slices of different arity. `other_slice` is - // guaranteed to have a larger arity, so we fill the middle part with enough - // wildcards to reach the length of the new, larger slice. - ( - &Slice(self_slice @ Slice { kind: SliceKind::VarLen(prefix, suffix), .. }), - &Slice(other_slice), - ) if self_slice.arity() != other_slice.arity() => { - // Start with a slice of wildcards of the appropriate length. - let mut fields: SmallVec<[_; 2]> = wildcard_sub_tys(); - // Fill in the fields from both ends. - let new_arity = fields.len(); - for i in 0..prefix { - fields[i] = PatOrWild::Pat(&self.fields[i]); - } - for i in 0..suffix { - fields[new_arity - 1 - i] = - PatOrWild::Pat(&self.fields[self.fields.len() - 1 - i]); - } - fields - } - _ => self.fields.iter().map(PatOrWild::Pat).collect(), + return smallvec![]; } + + // Start with a slice of wildcards of the appropriate length. + let mut fields: SmallVec<[_; 2]> = (0..other_ctor_arity).map(|_| PatOrWild::Wild).collect(); + // Fill `fields` with our fields. The arities are known to be compatible. + match self.ctor { + // The only non-trivial case: two slices of different arity. `other_ctor` is guaranteed + // to have a larger arity, so we adjust the indices of the patterns in the suffix so + // that they are correctly positioned in the larger slice. + Slice(Slice { kind: SliceKind::VarLen(prefix, _), .. }) + if self.arity != other_ctor_arity => + { + for ipat in &self.fields { + let new_idx = if ipat.idx < prefix { + ipat.idx + } else { + // Adjust the indices in the suffix. + ipat.idx + other_ctor_arity - self.arity + }; + fields[new_idx] = PatOrWild::Pat(&ipat.pat); + } + } + _ => { + for ipat in &self.fields { + fields[ipat.idx] = PatOrWild::Pat(&ipat.pat); + } + } + } + fields } /// Walk top-down and call `it` in each place where a pattern occurs @@ -114,13 +130,13 @@ impl DeconstructedPat { } for p in self.iter_fields() { - p.walk(it) + p.pat.walk(it) } } } /// This is best effort and not good enough for a `Display` impl. -impl fmt::Debug for DeconstructedPat { +impl fmt::Debug for DeconstructedPat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let pat = self; let mut first = true; @@ -134,6 +150,11 @@ impl fmt::Debug for DeconstructedPat { }; let mut start_or_comma = || start_or_continue(", "); + let mut fields: Vec<_> = (0..self.arity).map(|_| PatOrWild::Wild).collect(); + for ipat in self.iter_fields() { + fields[ipat.idx] = PatOrWild::Pat(&ipat.pat); + } + match pat.ctor() { Struct | Variant(_) | UnionField => { Cx::write_variant_name(f, pat)?; @@ -141,7 +162,7 @@ impl fmt::Debug for DeconstructedPat { // get the names of the fields. Instead we just display everything as a tuple // struct, which should be good enough. write!(f, "(")?; - for p in pat.iter_fields() { + for p in fields { write!(f, "{}", start_or_comma())?; write!(f, "{p:?}")?; } @@ -151,25 +172,23 @@ impl fmt::Debug for DeconstructedPat { // be careful to detect strings here. However a string literal pattern will never // be reported as a non-exhaustiveness witness, so we can ignore this issue. Ref => { - let subpattern = pat.iter_fields().next().unwrap(); - write!(f, "&{:?}", subpattern) + write!(f, "&{:?}", &fields[0]) } Slice(slice) => { - let mut subpatterns = pat.iter_fields(); write!(f, "[")?; match slice.kind { SliceKind::FixedLen(_) => { - for p in subpatterns { + for p in fields { write!(f, "{}{:?}", start_or_comma(), p)?; } } SliceKind::VarLen(prefix_len, _) => { - for p in subpatterns.by_ref().take(prefix_len) { + for p in &fields[..prefix_len] { write!(f, "{}{:?}", start_or_comma(), p)?; } write!(f, "{}", start_or_comma())?; write!(f, "..")?; - for p in subpatterns { + for p in &fields[prefix_len..] { write!(f, "{}{:?}", start_or_comma(), p)?; } } @@ -184,7 +203,7 @@ impl fmt::Debug for DeconstructedPat { Str(value) => write!(f, "{value:?}"), Opaque(..) => write!(f, ""), Or => { - for pat in pat.iter_fields() { + for pat in fields { write!(f, "{}{:?}", start_or_continue(" | "), pat)?; } Ok(()) @@ -200,14 +219,14 @@ impl fmt::Debug for DeconstructedPat { /// algorithm. Do not use `Wild` to represent a wildcard pattern comping from user input. /// /// This is morally `Option<&'p DeconstructedPat>` where `None` is interpreted as a wildcard. -pub(crate) enum PatOrWild<'p, Cx: TypeCx> { +pub(crate) enum PatOrWild<'p, Cx: PatCx> { /// A non-user-provided wildcard, created during specialization. Wild, /// A user-provided pattern. Pat(&'p DeconstructedPat), } -impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { +impl<'p, Cx: PatCx> Clone for PatOrWild<'p, Cx> { fn clone(&self) -> Self { match self { PatOrWild::Wild => PatOrWild::Wild, @@ -216,9 +235,9 @@ impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { } } -impl<'p, Cx: TypeCx> Copy for PatOrWild<'p, Cx> {} +impl<'p, Cx: PatCx> Copy for PatOrWild<'p, Cx> {} -impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { +impl<'p, Cx: PatCx> PatOrWild<'p, Cx> { pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat> { match self { PatOrWild::Wild => None, @@ -242,9 +261,10 @@ impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { /// Expand this (possibly-nested) or-pattern into its alternatives. pub(crate) fn flatten_or_pat(self) -> SmallVec<[Self; 1]> { match self { - PatOrWild::Pat(pat) if pat.is_or_pat() => { - pat.iter_fields().flat_map(|p| PatOrWild::Pat(p).flatten_or_pat()).collect() - } + PatOrWild::Pat(pat) if pat.is_or_pat() => pat + .iter_fields() + .flat_map(|ipat| PatOrWild::Pat(&ipat.pat).flatten_or_pat()) + .collect(), _ => smallvec![self], } } @@ -263,7 +283,7 @@ impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { } } -impl<'p, Cx: TypeCx> fmt::Debug for PatOrWild<'p, Cx> { +impl<'p, Cx: PatCx> fmt::Debug for PatOrWild<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { PatOrWild::Wild => write!(f, "_"), @@ -275,19 +295,19 @@ impl<'p, Cx: TypeCx> fmt::Debug for PatOrWild<'p, Cx> { /// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics /// purposes. As such they don't use interning and can be cloned. #[derive(Debug)] -pub struct WitnessPat { +pub struct WitnessPat { ctor: Constructor, pub(crate) fields: Vec>, ty: Cx::Ty, } -impl Clone for WitnessPat { +impl Clone for WitnessPat { fn clone(&self) -> Self { Self { ctor: self.ctor.clone(), fields: self.fields.clone(), ty: self.ty.clone() } } } -impl WitnessPat { +impl WitnessPat { pub(crate) fn new(ctor: Constructor, fields: Vec, ty: Cx::Ty) -> Self { Self { ctor, fields, ty } } diff --git a/compiler/rustc_pattern_analysis/src/pat_column.rs b/compiler/rustc_pattern_analysis/src/pat_column.rs index ce14fdc364f7..eb4e095c1c66 100644 --- a/compiler/rustc_pattern_analysis/src/pat_column.rs +++ b/compiler/rustc_pattern_analysis/src/pat_column.rs @@ -1,6 +1,6 @@ use crate::constructor::{Constructor, SplitConstructorSet}; use crate::pat::{DeconstructedPat, PatOrWild}; -use crate::{Captures, MatchArm, TypeCx}; +use crate::{Captures, MatchArm, PatCx}; /// A column of patterns in a match, where a column is the intuitive notion of "subpatterns that /// inspect the same subvalue/place". @@ -11,12 +11,12 @@ use crate::{Captures, MatchArm, TypeCx}; /// /// This is not used in the usefulness algorithm; only in lints. #[derive(Debug)] -pub struct PatternColumn<'p, Cx: TypeCx> { +pub struct PatternColumn<'p, Cx: PatCx> { /// This must not contain an or-pattern. `expand_and_push` takes care to expand them. patterns: Vec<&'p DeconstructedPat>, } -impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { +impl<'p, Cx: PatCx> PatternColumn<'p, Cx> { pub fn new(arms: &[MatchArm<'p, Cx>]) -> Self { let patterns = Vec::with_capacity(arms.len()); let mut column = PatternColumn { patterns }; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 0085f0ab6566..fd51fbedeef9 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -18,20 +18,19 @@ use rustc_target::abi::{FieldIdx, Integer, VariantIdx, FIRST_VARIANT}; use crate::constructor::{ IntRange, MaybeInfiniteInt, OpaqueId, RangeEnd, Slice, SliceKind, VariantVisibility, }; -use crate::{errors, Captures, PrivateUninhabitedField, TypeCx}; +use crate::{errors, Captures, PatCx, PrivateUninhabitedField}; use crate::constructor::Constructor::*; // Re-export rustc-specific versions of all these types. -pub type Constructor<'p, 'tcx> = crate::constructor::Constructor>; -pub type ConstructorSet<'p, 'tcx> = - crate::constructor::ConstructorSet>; -pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat>; -pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; +pub type Constructor<'p, 'tcx> = crate::constructor::Constructor>; +pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet>; +pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat>; +pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcPatCtxt<'p, 'tcx>>; +pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcPatCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = - crate::usefulness::UsefulnessReport<'p, RustcMatchCheckCtxt<'p, 'tcx>>; -pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat>; + crate::usefulness::UsefulnessReport<'p, RustcPatCtxt<'p, 'tcx>>; +pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat>; /// A type which has gone through `cx.reveal_opaque_ty`, i.e. if it was opaque it was replaced by /// the hidden type if allowed in the current body. This ensures we consistently inspect the hidden @@ -62,7 +61,7 @@ impl<'tcx> RevealedTy<'tcx> { } #[derive(Clone)] -pub struct RustcMatchCheckCtxt<'p, 'tcx: 'p> { +pub struct RustcPatCtxt<'p, 'tcx: 'p> { pub tcx: TyCtxt<'tcx>, pub typeck_results: &'tcx ty::TypeckResults<'tcx>, /// The module in which the match occurs. This is necessary for @@ -87,22 +86,19 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx: 'p> { pub known_valid_scrutinee: bool, } -impl<'p, 'tcx: 'p> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> fmt::Debug for RustcPatCtxt<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("RustcMatchCheckCtxt").finish() + f.debug_struct("RustcPatCtxt").finish() } } -impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Type inference occasionally gives us opaque types in places where corresponding patterns /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited /// types, we use the corresponding concrete type if possible. #[inline] pub fn reveal_opaque_ty(&self, ty: Ty<'tcx>) -> RevealedTy<'tcx> { - fn reveal_inner<'tcx>( - cx: &RustcMatchCheckCtxt<'_, 'tcx>, - ty: Ty<'tcx>, - ) -> RevealedTy<'tcx> { + fn reveal_inner<'tcx>(cx: &RustcPatCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> RevealedTy<'tcx> { let ty::Alias(ty::Opaque, alias_ty) = *ty.kind() else { bug!() }; if let Some(local_def_id) = alias_ty.def_id.as_local() { let key = ty::OpaqueTypeKey { def_id: local_def_id, args: alias_ty.args }; @@ -199,7 +195,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { + ExactSizeIterator + Captures<'a> { fn reveal_and_alloc<'a, 'tcx>( - cx: &'a RustcMatchCheckCtxt<'_, 'tcx>, + cx: &'a RustcPatCtxt<'_, 'tcx>, iter: impl Iterator>, ) -> &'a [(RevealedTy<'tcx>, PrivateUninhabitedField)] { cx.dropless_arena.alloc_from_iter( @@ -218,7 +214,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { reveal_and_alloc(cx, once(args.type_at(0))) } else { let variant = - &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt)); + &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt)); // In the cases of either a `#[non_exhaustive]` field list or a non-public // field, we skip uninhabited fields in order not to reveal the @@ -270,7 +266,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // patterns. If we're here we can assume this is a box pattern. 1 } else { - let variant_idx = RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt); + let variant_idx = RustcPatCtxt::variant_index_for_adt(&ctor, *adt); adt.variant(variant_idx).fields.len() } } @@ -445,7 +441,8 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { let cx = self; let ty = cx.reveal_opaque_ty(pat.ty); let ctor; - let mut fields: Vec<_>; + let arity; + let fields: Vec<_>; match &pat.kind { PatKind::AscribeUserType { subpattern, .. } | PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern), @@ -453,9 +450,11 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; fields = vec![]; + arity = 0; } PatKind::Deref { subpattern } => { - fields = vec![self.lower_pat(subpattern)]; + fields = vec![self.lower_pat(subpattern).at_index(0)]; + arity = 1; ctor = match ty.kind() { // This is a box pattern. ty::Adt(adt, ..) if adt.is_box() => Struct, @@ -467,16 +466,13 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { match ty.kind() { ty::Tuple(fs) => { ctor = Struct; - fields = fs + arity = fs.len(); + fields = subpatterns .iter() - .map(|ty| cx.reveal_opaque_ty(ty)) - .map(|ty| DeconstructedPat::wildcard(ty)) + .map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index())) .collect(); - for pat in subpatterns { - fields[pat.field.index()] = self.lower_pat(&pat.pattern); - } } - ty::Adt(adt, args) if adt.is_box() => { + ty::Adt(adt, _) if adt.is_box() => { // The only legal patterns of type `Box` (outside `std`) are `_` and box // patterns. If we're here we can assume this is a box pattern. // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_, @@ -490,13 +486,13 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // solution when we introduce generalized deref patterns. Also need to // prevent mixing of those two options. let pattern = subpatterns.into_iter().find(|pat| pat.field.index() == 0); - let pat = if let Some(pat) = pattern { - self.lower_pat(&pat.pattern) + if let Some(pat) = pattern { + fields = vec![self.lower_pat(&pat.pattern).at_index(0)]; } else { - DeconstructedPat::wildcard(self.reveal_opaque_ty(args.type_at(0))) - }; + fields = vec![]; + } ctor = Struct; - fields = vec![pat]; + arity = 1; } ty::Adt(adt, _) => { ctor = match pat.kind { @@ -506,14 +502,12 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { _ => bug!(), }; let variant = - &adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt)); - fields = cx - .variant_sub_tys(ty, variant) - .map(|(_, ty)| DeconstructedPat::wildcard(ty)) + &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt)); + arity = variant.fields.len(); + fields = subpatterns + .iter() + .map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index())) .collect(); - for pat in subpatterns { - fields[pat.field.index()] = self.lower_pat(&pat.pattern); - } } _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty), } @@ -526,6 +520,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => Opaque(OpaqueId::new()), }; fields = vec![]; + arity = 0; } ty::Char | ty::Int(_) | ty::Uint(_) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -542,6 +537,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => Opaque(OpaqueId::new()), }; fields = vec![]; + arity = 0; } ty::Float(ty::FloatTy::F32) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -553,6 +549,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => Opaque(OpaqueId::new()), }; fields = vec![]; + arity = 0; } ty::Float(ty::FloatTy::F64) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -564,6 +561,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => Opaque(OpaqueId::new()), }; fields = vec![]; + arity = 0; } ty::Ref(_, t, _) if t.is_str() => { // We want a `&str` constant to behave like a `Deref` pattern, to be compatible @@ -574,9 +572,10 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // subfields. // Note: `t` is `str`, not `&str`. let ty = self.reveal_opaque_ty(*t); - let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), ty, pat); + let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), 0, ty, pat); ctor = Ref; - fields = vec![subpattern] + fields = vec![subpattern.at_index(0)]; + arity = 1; } // All constants that can be structurally matched have already been expanded // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are @@ -584,6 +583,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { _ => { ctor = Opaque(OpaqueId::new()); fields = vec![]; + arity = 0; } } } @@ -623,6 +623,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { _ => bug!("invalid type for range pattern: {}", ty.inner()), }; fields = vec![]; + arity = 0; } PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { let array_len = match ty.kind() { @@ -638,12 +639,25 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { SliceKind::FixedLen(prefix.len() + suffix.len()) }; ctor = Slice(Slice::new(array_len, kind)); - fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect(); + fields = prefix + .iter() + .chain(suffix.iter()) + .map(|p| self.lower_pat(&*p)) + .enumerate() + .map(|(i, p)| p.at_index(i)) + .collect(); + arity = kind.arity(); } PatKind::Or { .. } => { ctor = Or; let pats = expand_or_pat(pat); - fields = pats.into_iter().map(|p| self.lower_pat(p)).collect(); + fields = pats + .into_iter() + .map(|p| self.lower_pat(p)) + .enumerate() + .map(|(i, p)| p.at_index(i)) + .collect(); + arity = fields.len(); } PatKind::Never => { // A never pattern matches all the values of its type (namely none). Moreover it @@ -651,13 +665,15 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { // `Result` which has other constructors. Hence we lower it as a wildcard. ctor = Wildcard; fields = vec![]; + arity = 0; } PatKind::Error(_) => { ctor = Opaque(OpaqueId::new()); fields = vec![]; + arity = 0; } } - DeconstructedPat::new(ctor, fields, ty, pat) + DeconstructedPat::new(ctor, fields, arity, ty, pat) } /// Convert back to a `thir::PatRangeBoundary` for diagnostic purposes. @@ -690,7 +706,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { None => PatRangeBoundary::PosInfinity, } } - JustAfterMax | PosInfinity => PatRangeBoundary::PosInfinity, + PosInfinity => PatRangeBoundary::PosInfinity, } } @@ -754,8 +770,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { PatKind::Deref { subpattern: subpatterns.next().unwrap() } } ty::Adt(adt_def, args) => { - let variant_index = - RustcMatchCheckCtxt::variant_index_for_adt(&pat.ctor(), *adt_def); + let variant_index = RustcPatCtxt::variant_index_for_adt(&pat.ctor(), *adt_def); let subpatterns = subpatterns .enumerate() .map(|(i, pattern)| FieldPat { field: FieldIdx::new(i), pattern }) @@ -823,7 +838,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { } } -impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> { type Ty = RevealedTy<'tcx>; type Error = ErrorGuaranteed; type VariantIdx = VariantIdx; @@ -884,10 +899,10 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); let overlaps: Vec<_> = overlaps_with .iter() - .map(|pat| pat.data().unwrap().span) + .map(|pat| pat.data().span) .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span }) .collect(); - let pat_span = pat.data().unwrap().span; + let pat_span = pat.data().span; self.tcx.emit_node_span_lint( lint::builtin::OVERLAPPING_RANGE_ENDPOINTS, self.match_lint_level, @@ -907,7 +922,7 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { gap: IntRange, gapped_with: &[&crate::pat::DeconstructedPat], ) { - let Some(&thir_pat) = pat.data() else { return }; + let &thir_pat = pat.data(); let thir::PatKind::Range(range) = &thir_pat.kind else { return }; // Only lint when the left range is an exclusive range. if range.end != rustc_hir::RangeEnd::Excluded { @@ -955,7 +970,7 @@ impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { gap_with: gapped_with .iter() .map(|pat| errors::GappedRange { - span: pat.data().unwrap().span, + span: pat.data().span, gap: gap_as_pat.clone(), first_range: thir_pat.clone(), }) diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index a067bf1f0c23..3760db8b6889 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -242,7 +242,7 @@ //! Therefore `usefulness(tp_1, tp_2, tq)` returns the single witness-tuple `[Variant2(Some(true), 0)]`. //! //! -//! Computing the set of constructors for a type is done in [`TypeCx::ctors_for_ty`]. See +//! Computing the set of constructors for a type is done in [`PatCx::ctors_for_ty`]. See //! the following sections for more accurate versions of the algorithm and corresponding links. //! //! @@ -540,8 +540,8 @@ //! We track in the algorithm whether a given place is known to contain valid data. This is done //! first by inspecting the scrutinee syntactically (which gives us `cx.known_valid_scrutinee`), and //! then by tracking validity of each column of the matrix (which correspond to places) as we -//! recurse into subpatterns. That second part is done through [`ValidityConstraint`], most notably -//! [`ValidityConstraint::specialize`]. +//! recurse into subpatterns. That second part is done through [`PlaceValidity`], most notably +//! [`PlaceValidity::specialize`]. //! //! Having said all that, in practice we don't fully follow what's been presented in this section. //! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or @@ -716,9 +716,9 @@ use std::fmt; use crate::constructor::{Constructor, ConstructorSet, IntRange}; use crate::pat::{DeconstructedPat, PatId, PatOrWild, WitnessPat}; -use crate::{Captures, MatchArm, PrivateUninhabitedField, TypeCx}; +use crate::{Captures, MatchArm, PatCx, PrivateUninhabitedField}; -use self::ValidityConstraint::*; +use self::PlaceValidity::*; #[cfg(feature = "rustc")] use rustc_data_structures::stack::ensure_sufficient_stack; @@ -728,7 +728,7 @@ pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { } /// Context that provides information for usefulness checking. -struct UsefulnessCtxt<'a, Cx: TypeCx> { +struct UsefulnessCtxt<'a, Cx: PatCx> { /// The context for type information. tycx: &'a Cx, /// Collect the patterns found useful during usefulness checking. This is used to lint @@ -738,7 +738,7 @@ struct UsefulnessCtxt<'a, Cx: TypeCx> { complexity_level: usize, } -impl<'a, Cx: TypeCx> UsefulnessCtxt<'a, Cx> { +impl<'a, Cx: PatCx> UsefulnessCtxt<'a, Cx> { fn increase_complexity_level(&mut self, complexity_add: usize) -> Result<(), Cx::Error> { self.complexity_level += complexity_add; if self @@ -752,26 +752,26 @@ impl<'a, Cx: TypeCx> UsefulnessCtxt<'a, Cx> { } /// Context that provides information local to a place under investigation. -struct PlaceCtxt<'a, Cx: TypeCx> { +struct PlaceCtxt<'a, Cx: PatCx> { cx: &'a Cx, /// Type of the place under investigation. ty: &'a Cx::Ty, } -impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {} -impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> { +impl<'a, Cx: PatCx> Copy for PlaceCtxt<'a, Cx> {} +impl<'a, Cx: PatCx> Clone for PlaceCtxt<'a, Cx> { fn clone(&self) -> Self { Self { cx: self.cx, ty: self.ty } } } -impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> { +impl<'a, Cx: PatCx> fmt::Debug for PlaceCtxt<'a, Cx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("PlaceCtxt").field("ty", self.ty).finish() } } -impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { +impl<'a, Cx: PatCx> PlaceCtxt<'a, Cx> { fn ctor_arity(&self, ctor: &Constructor) -> usize { self.cx.ctor_arity(ctor, self.ty) } @@ -780,18 +780,14 @@ impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { } } -/// Serves two purposes: -/// - in a wildcard, tracks whether the wildcard matches only valid values (i.e. is a binding `_a`) -/// or also invalid values (i.e. is a true `_` pattern). -/// - in the matrix, track whether a given place (aka column) is known to contain a valid value or -/// not. +/// Track whether a given place (aka column) is known to contain a valid value or not. #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum ValidityConstraint { +pub enum PlaceValidity { ValidOnly, MaybeInvalid, } -impl ValidityConstraint { +impl PlaceValidity { pub fn from_bool(is_valid_only: bool) -> Self { if is_valid_only { ValidOnly } else { MaybeInvalid } } @@ -806,7 +802,7 @@ impl ValidityConstraint { /// /// Pending further opsem decisions, the current behavior is: validity is preserved, except /// inside `&` and union fields where validity is reset to `MaybeInvalid`. - fn specialize(self, ctor: &Constructor) -> Self { + fn specialize(self, ctor: &Constructor) -> Self { // We preserve validity except when we go inside a reference or a union field. if matches!(ctor, Constructor::Ref | Constructor::UnionField) { // Validity of `x: &T` does not imply validity of `*x: T`. @@ -817,7 +813,7 @@ impl ValidityConstraint { } } -impl fmt::Display for ValidityConstraint { +impl fmt::Display for PlaceValidity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { ValidOnly => "✓", @@ -829,19 +825,19 @@ impl fmt::Display for ValidityConstraint { /// Data about a place under investigation. Its methods contain a lot of the logic used to analyze /// the constructors in the matrix. -struct PlaceInfo { +struct PlaceInfo { /// The type of the place. ty: Cx::Ty, /// Whether the place is a private uninhabited field. If so we skip this field during analysis /// so that we don't observe its emptiness. private_uninhabited: bool, /// Whether the place is known to contain valid data. - validity: ValidityConstraint, + validity: PlaceValidity, /// Whether the place is the scrutinee itself or a subplace of it. is_scrutinee: bool, } -impl PlaceInfo { +impl PlaceInfo { /// Given a constructor for the current place, we return one `PlaceInfo` for each field of the /// constructor. fn specialize<'a>( @@ -936,7 +932,7 @@ impl PlaceInfo { } } -impl Clone for PlaceInfo { +impl Clone for PlaceInfo { fn clone(&self) -> Self { Self { ty: self.ty.clone(), @@ -951,7 +947,7 @@ impl Clone for PlaceInfo { // The three lifetimes are: // - 'p coming from the input // - Cx global compilation context -struct PatStack<'p, Cx: TypeCx> { +struct PatStack<'p, Cx: PatCx> { // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well. pats: SmallVec<[PatOrWild<'p, Cx>; 2]>, /// Sometimes we know that as far as this row is concerned, the current case is already handled @@ -960,13 +956,13 @@ struct PatStack<'p, Cx: TypeCx> { relevant: bool, } -impl<'p, Cx: TypeCx> Clone for PatStack<'p, Cx> { +impl<'p, Cx: PatCx> Clone for PatStack<'p, Cx> { fn clone(&self) -> Self { Self { pats: self.pats.clone(), relevant: self.relevant } } } -impl<'p, Cx: TypeCx> PatStack<'p, Cx> { +impl<'p, Cx: PatCx> PatStack<'p, Cx> { fn from_pattern(pat: &'p DeconstructedPat) -> Self { PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true } } @@ -1006,15 +1002,17 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> { ctor_arity: usize, ctor_is_relevant: bool, ) -> Result, Cx::Error> { - // We pop the head pattern and push the new fields extracted from the arguments of - // `self.head()`. - let mut new_pats = self.head().specialize(ctor, ctor_arity); - if new_pats.len() != ctor_arity { + let head_pat = self.head(); + if head_pat.as_pat().is_some_and(|pat| pat.arity() > ctor_arity) { + // Arity can be smaller in case of variable-length slices, but mustn't be larger. return Err(cx.bug(format_args!( - "uncaught type error: pattern {:?} has inconsistent arity (expected arity {ctor_arity})", - self.head().as_pat().unwrap() + "uncaught type error: pattern {:?} has inconsistent arity (expected arity <= {ctor_arity})", + head_pat.as_pat().unwrap() ))); } + // We pop the head pattern and push the new fields extracted from the arguments of + // `self.head()`. + let mut new_pats = head_pat.specialize(ctor, ctor_arity); new_pats.extend_from_slice(&self.pats[1..]); // `ctor` is relevant for this row if it is the actual constructor of this row, or if the // row has a wildcard and `ctor` is relevant for wildcards. @@ -1024,7 +1022,7 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> { } } -impl<'p, Cx: TypeCx> fmt::Debug for PatStack<'p, Cx> { +impl<'p, Cx: PatCx> fmt::Debug for PatStack<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // We pretty-print similarly to the `Debug` impl of `Matrix`. write!(f, "+")?; @@ -1037,7 +1035,7 @@ impl<'p, Cx: TypeCx> fmt::Debug for PatStack<'p, Cx> { /// A row of the matrix. #[derive(Clone)] -struct MatrixRow<'p, Cx: TypeCx> { +struct MatrixRow<'p, Cx: PatCx> { // The patterns in the row. pats: PatStack<'p, Cx>, /// Whether the original arm had a guard. This is inherited when specializing. @@ -1057,7 +1055,7 @@ struct MatrixRow<'p, Cx: TypeCx> { intersects: BitSet, } -impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> { +impl<'p, Cx: PatCx> MatrixRow<'p, Cx> { fn is_empty(&self) -> bool { self.pats.is_empty() } @@ -1106,7 +1104,7 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> { } } -impl<'p, Cx: TypeCx> fmt::Debug for MatrixRow<'p, Cx> { +impl<'p, Cx: PatCx> fmt::Debug for MatrixRow<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.pats.fmt(f) } @@ -1123,7 +1121,7 @@ impl<'p, Cx: TypeCx> fmt::Debug for MatrixRow<'p, Cx> { /// specializing `(,)` and `Some` on a pattern of type `(Option, bool)`, the first column of /// the matrix will correspond to `scrutinee.0.Some.0` and the second column to `scrutinee.1`. #[derive(Clone)] -struct Matrix<'p, Cx: TypeCx> { +struct Matrix<'p, Cx: PatCx> { /// Vector of rows. The rows must form a rectangular 2D array. Moreover, all the patterns of /// each column must have the same type. Each column corresponds to a place within the /// scrutinee. @@ -1136,7 +1134,7 @@ struct Matrix<'p, Cx: TypeCx> { wildcard_row_is_relevant: bool, } -impl<'p, Cx: TypeCx> Matrix<'p, Cx> { +impl<'p, Cx: PatCx> Matrix<'p, Cx> { /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively /// expands it. Internal method, prefer [`Matrix::new`]. fn expand_and_push(&mut self, mut row: MatrixRow<'p, Cx>) { @@ -1153,11 +1151,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { } /// Build a new matrix from an iterator of `MatchArm`s. - fn new( - arms: &[MatchArm<'p, Cx>], - scrut_ty: Cx::Ty, - scrut_validity: ValidityConstraint, - ) -> Self { + fn new(arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, scrut_validity: PlaceValidity) -> Self { let place_info = PlaceInfo { ty: scrut_ty, private_uninhabited: false, @@ -1262,7 +1256,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { /// + _ + [_, _, tail @ ..] + /// | ✓ | ? | // column validity /// ``` -impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { +impl<'p, Cx: PatCx> fmt::Debug for Matrix<'p, Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "\n")?; @@ -1353,15 +1347,15 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { /// /// See the top of the file for more detailed explanations and examples. #[derive(Debug)] -struct WitnessStack(Vec>); +struct WitnessStack(Vec>); -impl Clone for WitnessStack { +impl Clone for WitnessStack { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl WitnessStack { +impl WitnessStack { /// Asserts that the witness contains a single pattern, and returns it. fn single_pattern(self) -> WitnessPat { assert_eq!(self.0.len(), 1); @@ -1406,15 +1400,15 @@ impl WitnessStack { /// Just as the `Matrix` starts with a single column, by the end of the algorithm, this has a single /// column, which contains the patterns that are missing for the match to be exhaustive. #[derive(Debug)] -struct WitnessMatrix(Vec>); +struct WitnessMatrix(Vec>); -impl Clone for WitnessMatrix { +impl Clone for WitnessMatrix { fn clone(&self) -> Self { Self(self.0.clone()) } } -impl WitnessMatrix { +impl WitnessMatrix { /// New matrix with no witnesses. fn empty() -> Self { WitnessMatrix(Vec::new()) @@ -1488,7 +1482,7 @@ impl WitnessMatrix { /// /// We can however get false negatives because exhaustiveness does not explore all cases. See the /// section on relevancy at the top of the file. -fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( +fn collect_overlapping_range_endpoints<'p, Cx: PatCx>( cx: &Cx, overlap_range: IntRange, matrix: &Matrix<'p, Cx>, @@ -1547,7 +1541,7 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( } /// Collect ranges that have a singleton gap between them. -fn collect_non_contiguous_range_endpoints<'p, Cx: TypeCx>( +fn collect_non_contiguous_range_endpoints<'p, Cx: PatCx>( cx: &Cx, gap_range: &IntRange, matrix: &Matrix<'p, Cx>, @@ -1588,7 +1582,7 @@ fn collect_non_contiguous_range_endpoints<'p, Cx: TypeCx>( /// (using `apply_constructor` and by updating `row.useful` for each parent row). /// This is all explained at the top of the file. #[instrument(level = "debug", skip(mcx), ret)] -fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( +fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: PatCx>( mcx: &mut UsefulnessCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, ) -> Result, Cx::Error> { @@ -1685,7 +1679,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( /// Indicates whether or not a given arm is useful. #[derive(Clone, Debug)] -pub enum Usefulness<'p, Cx: TypeCx> { +pub enum Usefulness<'p, Cx: PatCx> { /// The arm is useful. This additionally carries a set of or-pattern branches that have been /// found to be redundant despite the overall arm being useful. Used only in the presence of /// or-patterns, otherwise it stays empty. @@ -1696,17 +1690,18 @@ pub enum Usefulness<'p, Cx: TypeCx> { } /// Report whether this pattern was found useful, and its subpatterns that were not useful if any. -fn collect_pattern_usefulness<'p, Cx: TypeCx>( +fn collect_pattern_usefulness<'p, Cx: PatCx>( useful_subpatterns: &FxHashSet, pat: &'p DeconstructedPat, ) -> Usefulness<'p, Cx> { - fn pat_is_useful<'p, Cx: TypeCx>( + fn pat_is_useful<'p, Cx: PatCx>( useful_subpatterns: &FxHashSet, pat: &'p DeconstructedPat, ) -> bool { if useful_subpatterns.contains(&pat.uid) { true - } else if pat.is_or_pat() && pat.iter_fields().any(|f| pat_is_useful(useful_subpatterns, f)) + } else if pat.is_or_pat() + && pat.iter_fields().any(|f| pat_is_useful(useful_subpatterns, &f.pat)) { // We always expand or patterns in the matrix, so we will never see the actual // or-pattern (the one with constructor `Or`) in the column. As such, it will not be @@ -1737,7 +1732,7 @@ fn collect_pattern_usefulness<'p, Cx: TypeCx>( } /// The output of checking a match for exhaustiveness and arm usefulness. -pub struct UsefulnessReport<'p, Cx: TypeCx> { +pub struct UsefulnessReport<'p, Cx: PatCx> { /// For each arm of the input, whether that arm is useful after the arms above it. pub arm_usefulness: Vec<(MatchArm<'p, Cx>, Usefulness<'p, Cx>)>, /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of @@ -1747,11 +1742,11 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> { /// Computes whether a match is exhaustive and which of its arms are useful. #[instrument(skip(tycx, arms), level = "debug")] -pub fn compute_match_usefulness<'p, Cx: TypeCx>( +pub fn compute_match_usefulness<'p, Cx: PatCx>( tycx: &Cx, arms: &[MatchArm<'p, Cx>], scrut_ty: Cx::Ty, - scrut_validity: ValidityConstraint, + scrut_validity: PlaceValidity, complexity_limit: Option, ) -> Result, Cx::Error> { let mut cx = UsefulnessCtxt { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index fe3598616817..9f8cb8fcb41e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -549,7 +549,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { self.update(def_id, macro_ev, Level::Reachable); match def_kind { // No type privacy, so can be directly marked as reachable. - DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => { + DefKind::Const | DefKind::Static { .. } | DefKind::TraitAlias | DefKind::TyAlias => { if vis.is_accessible_from(module, self.tcx) { self.update(def_id, macro_ev, Level::Reachable); } @@ -1170,12 +1170,12 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { let def = def.filter(|(kind, _)| { matches!( kind, - DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static(_) + DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static { .. } ) }); if let Some((kind, def_id)) = def { let is_local_static = - if let DefKind::Static(_) = kind { def_id.is_local() } else { false }; + if let DefKind::Static { .. } = kind { def_id.is_local() } else { false }; if !self.item_is_accessible(def_id) && !is_local_static { let name = match *qpath { hir::QPath::LangItem(it, ..) => { @@ -1496,7 +1496,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { let def_kind = tcx.def_kind(def_id); match def_kind { - DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => { + DefKind::Const | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias => { if let DefKind::TyAlias = def_kind { self.check_unnameable(def_id, effective_vis); } diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 33116737a420..527671555327 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -41,7 +41,7 @@ use rustc_span::{ErrorGuaranteed, Span}; #[macro_use] mod plumbing; -pub use crate::plumbing::QueryCtxt; +pub use crate::plumbing::{query_key_hash_verify_all, QueryCtxt}; mod profiling_support; pub use self::profiling_support::alloc_self_profile_query_strings; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index b06d75be3902..aa9657797310 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -7,6 +7,7 @@ use crate::rustc_middle::ty::TyEncoder; use crate::QueryConfigRestored; use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_data_structures::sync::Lock; +use rustc_data_structures::unord::UnordMap; use rustc_errors::DiagInner; use rustc_index::Idx; @@ -189,6 +190,16 @@ pub(super) fn encode_all_query_results<'tcx>( } } +pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) { + if tcx.sess().opts.unstable_opts.incremental_verify_ich || cfg!(debug_assertions) { + tcx.sess.time("query_key_hash_verify_all", || { + for verify in super::QUERY_KEY_HASH_VERIFY.iter() { + verify(tcx); + } + }) + } +} + macro_rules! handle_cycle_error { ([]) => {{ rustc_query_system::HandleCycleError::Error @@ -370,6 +381,34 @@ pub(crate) fn encode_query_results<'a, 'tcx, Q>( }); } +pub(crate) fn query_key_hash_verify<'tcx>( + query: impl QueryConfig>, + qcx: QueryCtxt<'tcx>, +) { + let _timer = + qcx.profiler().generic_activity_with_arg("query_key_hash_verify_for", query.name()); + + let mut map = UnordMap::default(); + + let cache = query.query_cache(qcx); + cache.iter(&mut |key, _, _| { + let node = DepNode::construct(qcx.tcx, query.dep_kind(), key); + if let Some(other_key) = map.insert(node, *key) { + bug!( + "query key:\n\ + `{:?}`\n\ + and key:\n\ + `{:?}`\n\ + mapped to the same dep node:\n\ + {:?}", + key, + other_key, + node + ); + } + }); +} + fn try_load_from_on_disk_cache<'tcx, Q>(query: Q, tcx: TyCtxt<'tcx>, dep_node: DepNode) where Q: QueryConfig>, @@ -691,6 +730,13 @@ macro_rules! define_queries { ) } }} + + pub fn query_key_hash_verify<'tcx>(tcx: TyCtxt<'tcx>) { + $crate::plumbing::query_key_hash_verify( + query_impl::$name::QueryType::config(tcx), + QueryCtxt::new(tcx), + ) + } })*} pub(crate) fn engine(incremental: bool) -> QueryEngine { @@ -730,6 +776,10 @@ macro_rules! define_queries { > ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*]; + const QUERY_KEY_HASH_VERIFY: &[ + for<'tcx> fn(TyCtxt<'tcx>) + ] = &[$(query_impl::$name::query_key_hash_verify),*]; + #[allow(nonstandard_style)] mod query_callbacks { use super::*; diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index cc823917ce8c..0c6a63582931 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -179,13 +179,15 @@ impl SerializedDepGraph { pub fn decode(d: &mut MemDecoder<'_>) -> SerializedDepGraph { // The last 16 bytes are the node count and edge count. debug!("position: {:?}", d.position()); - let (node_count, edge_count) = - d.with_position(d.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { + let (node_count, edge_count, graph_size) = + d.with_position(d.len() - 3 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| { debug!("position: {:?}", d.position()); let node_count = IntEncodedWithFixedSize::decode(d).0 as usize; let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize; - (node_count, edge_count) + let graph_size = IntEncodedWithFixedSize::decode(d).0 as usize; + (node_count, edge_count, graph_size) }); + assert_eq!(d.len(), graph_size); debug!("position: {:?}", d.position()); debug!(?node_count, ?edge_count); @@ -491,6 +493,8 @@ impl EncoderState { debug!("position: {:?}", encoder.position()); IntEncodedWithFixedSize(node_count).encode(&mut encoder); IntEncodedWithFixedSize(edge_count).encode(&mut encoder); + let graph_size = encoder.position() + IntEncodedWithFixedSize::ENCODED_SIZE; + IntEncodedWithFixedSize(graph_size as u64).encode(&mut encoder); debug!("position: {:?}", encoder.position()); // Drop the encoder so that nothing is written after the counts. let result = encoder.finish(); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index dd18ab7d9d23..375f20dd809f 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -990,7 +990,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { Res::Def( DefKind::Fn | DefKind::AssocFn - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst | DefKind::Ctor(..), diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index bb3b902c0de6..bef95aca0d1c 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -127,7 +127,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ItemKind::Union(..) => DefKind::Union, ItemKind::ExternCrate(..) => DefKind::ExternCrate, ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Static(s) => DefKind::Static(s.mutability), + ItemKind::Static(s) => DefKind::Static { mutability: s.mutability, nested: false }, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(..) => { @@ -214,7 +214,9 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(_, mt, _) => DefKind::Static(mt), + ForeignItemKind::Static(_, mutability, _) => { + DefKind::Static { mutability, nested: false } + } ForeignItemKind::Fn(_) => DefKind::Fn, ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 0bb2a69ae992..476b31f44ae6 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -574,7 +574,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => { use errs::GenericParamsFromOuterItemLabel as Label; let static_or_const = match def_kind { - DefKind::Static(_) => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), + DefKind::Static{ .. } => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const), _ => None, }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ea07ed9e6546..a996188db022 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -500,7 +500,7 @@ impl<'a> PathSource<'a> { Res::Def( DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn) | DefKind::Const - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Fn | DefKind::AssocFn | DefKind::AssocConst @@ -3645,7 +3645,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } Some(res) } - Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static(_), _) => { + Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static { .. }, _) => { // This is unambiguously a fresh binding, either syntactically // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves // to something unusable as a pattern (e.g., constructor function), diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d8fd8d22439c..dbca2f9895d2 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -19,7 +19,7 @@ use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, Resolver use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; -use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; +use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::RegisteredTools; @@ -431,40 +431,15 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { expn_id: LocalExpnId, path: &ast::Path, ) -> Result { - let span = path.span; - let path = &Segment::from_path(path); - let parent_scope = self.invocation_parent_scopes[&expn_id]; + self.path_accessible(expn_id, path, &[TypeNS, ValueNS, MacroNS]) + } - let mut indeterminate = false; - for ns in [TypeNS, ValueNS, MacroNS].iter().copied() { - match self.maybe_resolve_path(path, Some(ns), &parent_scope) { - PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true), - PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => { - return Ok(true); - } - PathResult::NonModule(..) | - // HACK(Urgau): This shouldn't be necessary - PathResult::Failed { is_error_from_last_segment: false, .. } => { - self.dcx() - .emit_err(errors::CfgAccessibleUnsure { span }); - - // If we get a partially resolved NonModule in one namespace, we should get the - // same result in any other namespaces, so we can return early. - return Ok(false); - } - PathResult::Indeterminate => indeterminate = true, - // We can only be sure that a path doesn't exist after having tested all the - // possibilities, only at that time we can return false. - PathResult::Failed { .. } => {} - PathResult::Module(_) => panic!("unexpected path resolution"), - } - } - - if indeterminate { - return Err(Indeterminate); - } - - Ok(false) + fn macro_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + ) -> Result { + self.path_accessible(expn_id, path, &[MacroNS]) } fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span { @@ -960,4 +935,46 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let ItemKind::MacroDef(def) = &item.kind else { unreachable!() }; MacroData { ext: Lrc::new(ext), rule_spans, macro_rules: def.macro_rules } } + + fn path_accessible( + &mut self, + expn_id: LocalExpnId, + path: &ast::Path, + namespaces: &[Namespace], + ) -> Result { + let span = path.span; + let path = &Segment::from_path(path); + let parent_scope = self.invocation_parent_scopes[&expn_id]; + + let mut indeterminate = false; + for ns in namespaces { + match self.maybe_resolve_path(path, Some(*ns), &parent_scope) { + PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true), + PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => { + return Ok(true); + } + PathResult::NonModule(..) | + // HACK(Urgau): This shouldn't be necessary + PathResult::Failed { is_error_from_last_segment: false, .. } => { + self.dcx() + .emit_err(errors::CfgAccessibleUnsure { span }); + + // If we get a partially resolved NonModule in one namespace, we should get the + // same result in any other namespaces, so we can return early. + return Ok(false); + } + PathResult::Indeterminate => indeterminate = true, + // We can only be sure that a path doesn't exist after having tested all the + // possibilities, only at that time we can return false. + PathResult::Failed { .. } => {} + PathResult::Module(_) => panic!("unexpected path resolution"), + } + } + + if indeterminate { + return Err(Indeterminate); + } + + Ok(false) + } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index b947ac818057..5c52ee66128c 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -134,31 +134,26 @@ pub enum LtoCli { /// and higher). Nevertheless, there are many variables, depending on options /// selected, code structure, and enabled attributes. If errors are encountered, /// either while compiling or when generating `llvm-cov show` reports, consider -/// lowering the optimization level, including or excluding `-C link-dead-code`, -/// or using `-Zunstable-options -C instrument-coverage=except-unused-functions` -/// or `-Zunstable-options -C instrument-coverage=except-unused-generics`. -/// -/// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the -/// coverage map, it will not attempt to generate synthetic functions for unused -/// (and not code-generated) functions (whether they are generic or not). As a -/// result, non-codegenned functions will not be included in the coverage map, -/// and will not appear, as covered or uncovered, in coverage reports. -/// -/// `ExceptUnusedGenerics` will add synthetic functions to the coverage map, -/// unless the function has type parameters. +/// lowering the optimization level, or including/excluding `-C link-dead-code`. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum InstrumentCoverage { /// `-C instrument-coverage=no` (or `off`, `false` etc.) No, /// `-C instrument-coverage` or `-C instrument-coverage=yes` Yes, - /// Additionally, instrument branches and output branch coverage. - /// `-Zunstable-options -C instrument-coverage=branch` - Branch, - /// `-Zunstable-options -C instrument-coverage=except-unused-generics` - ExceptUnusedGenerics, - /// `-Zunstable-options -C instrument-coverage=except-unused-functions` - ExceptUnusedFunctions, +} + +/// Individual flag values controlled by `-Z coverage-options`. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct CoverageOptions { + /// Add branch coverage instrumentation (placeholder flag; not yet implemented). + pub branch: bool, +} + +impl Default for CoverageOptions { + fn default() -> Self { + Self { branch: false } + } } /// Settings for `-Z instrument-xray` flag. @@ -2718,24 +2713,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M } } - // Check for unstable values of `-C instrument-coverage`. - // This is what prevents them from being used on stable compilers. - match cg.instrument_coverage { - // Stable values: - InstrumentCoverage::Yes | InstrumentCoverage::No => {} - // Unstable values: - InstrumentCoverage::Branch - | InstrumentCoverage::ExceptUnusedFunctions - | InstrumentCoverage::ExceptUnusedGenerics => { - if !unstable_opts.unstable_options { - early_dcx.early_fatal( - "`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \ - require `-Z unstable-options`", - ); - } - } - } - if cg.instrument_coverage != InstrumentCoverage::No { if cg.profile_generate.enabled() || cg.profile_use.is_some() { early_dcx.early_fatal( @@ -3204,12 +3181,12 @@ pub enum WasiExecModel { /// how the hash should be calculated when adding a new command-line argument. pub(crate) mod dep_tracking { use super::{ - BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CrateType, DebugInfo, - DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold, - InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli, - NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius, - RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, - SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, + BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions, + CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn, + InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, + LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, + Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, + SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3279,6 +3256,7 @@ pub(crate) mod dep_tracking { CodeModel, TlsModel, InstrumentCoverage, + CoverageOptions, InstrumentXRay, CrateType, MergeFunctions, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index ea4b8f2463e7..9c03bdb21874 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -395,7 +395,8 @@ mod desc { pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; - pub const parse_instrument_coverage: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions`"; + pub const parse_instrument_coverage: &str = parse_bool; + pub const parse_coverage_options: &str = "`branch` or `no-branch`"; pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; @@ -928,21 +929,34 @@ mod parse { return true; }; + // Parse values that have historically been accepted by stable compilers, + // even though they're currently just aliases for boolean values. *slot = match v { "all" => InstrumentCoverage::Yes, - "branch" => InstrumentCoverage::Branch, - "except-unused-generics" | "except_unused_generics" => { - InstrumentCoverage::ExceptUnusedGenerics - } - "except-unused-functions" | "except_unused_functions" => { - InstrumentCoverage::ExceptUnusedFunctions - } "0" => InstrumentCoverage::No, _ => return false, }; true } + pub(crate) fn parse_coverage_options(slot: &mut CoverageOptions, v: Option<&str>) -> bool { + let Some(v) = v else { return true }; + + for option in v.split(',') { + let (option, enabled) = match option.strip_prefix("no-") { + Some(without_no) => (without_no, false), + None => (option, true), + }; + let slot = match option { + "branch" => &mut slot.branch, + _ => return false, + }; + *slot = enabled; + } + + true + } + pub(crate) fn parse_instrument_xray( slot: &mut Option, v: Option<&str>, @@ -1445,14 +1459,9 @@ options! { "set the threshold for inlining a function"), #[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")] instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED], - "instrument the generated code to support LLVM source-based code coverage \ - reports (note, the compiler build config must include `profiler = true`); \ - implies `-C symbol-mangling-version=v0`. Optional values are: - `=no` `=n` `=off` `=false` (default) - `=yes` `=y` `=on` `=true` (implicit value) - `=branch` (unstable) - `=except-unused-generics` (unstable) - `=except-unused-functions` (unstable)"), + "instrument the generated code to support LLVM source-based code coverage reports \ + (note, the compiler build config must include `profiler = true`); \ + implies `-C symbol-mangling-version=v0`"), link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED], "a single extra argument to append to the linker invocation (can be used several times)"), link_args: Vec = (Vec::new(), parse_list, [UNTRACKED], @@ -1574,6 +1583,8 @@ options! { "set option to collapse debuginfo for macros"), combine_cgu: bool = (false, parse_bool, [TRACKED], "combine CGUs into a single one"), + coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED], + "control details of coverage instrumentation"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED], @@ -1674,7 +1685,9 @@ options! { "print high-level information about incremental reuse (or the lack thereof) \ (default: no)"), incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED], - "verify incr. comp. hashes of green query instances (default: no)"), + "verify extended properties for incr. comp. (default: no): + - hashes of green query instances + - hash collisions of query keys"), inline_in_all_cgus: Option = (None, parse_opt_bool, [TRACKED], "control whether `#[inline]` functions are in all CGUs"), inline_llvm: bool = (true, parse_bool, [TRACKED], @@ -1818,7 +1831,9 @@ options! { print_llvm_passes: bool = (false, parse_bool, [UNTRACKED], "print the LLVM optimization passes being run (default: no)"), print_mono_items: Option = (None, parse_opt_string, [UNTRACKED], - "print the result of the monomorphization collection pass"), + "print the result of the monomorphization collection pass. \ + Value `lazy` means to use normal collection; `eager` means to collect all items. + Note that this overwrites the effect `-Clink-dead-code` has on collection!"), print_type_sizes: bool = (false, parse_bool, [UNTRACKED], "print layout information for each type encountered (default: no)"), print_vtable_sizes: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ab636b14d19a..9c94fd7027fd 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -353,15 +353,7 @@ impl Session { } pub fn instrument_coverage_branch(&self) -> bool { - self.opts.cg.instrument_coverage() == InstrumentCoverage::Branch - } - - pub fn instrument_coverage_except_unused_generics(&self) -> bool { - self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedGenerics - } - - pub fn instrument_coverage_except_unused_functions(&self) -> bool { - self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedFunctions + self.instrument_coverage() && self.opts.unstable_opts.coverage_options.branch } pub fn is_sanitizer_cfi_enabled(&self) -> bool { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 540bc4835486..8488777eda99 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -264,7 +264,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { use rustc_hir::def::DefKind; match tcx.def_kind(def_id) { DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)), - DefKind::Static(..) => ForeignItemKind::Static(tables.static_def(def_id)), + DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)), DefKind::ForeignTy => ForeignItemKind::Type( tables.intern_ty(rustc_middle::ty::Ty::new_foreign(tcx, def_id)), ), @@ -587,6 +587,16 @@ impl<'tcx> Context for TablesWrapper<'tcx> { } } + /// Retrieve the plain intrinsic name of an instance. + /// + /// This assumes that the instance is an intrinsic. + fn intrinsic_name(&self, def: InstanceDef) -> Symbol { + let tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + let intrinsic = tables.tcx.intrinsic(instance.def_id()).unwrap(); + intrinsic.name.to_string() + } + fn ty_layout(&self, ty: Ty) -> Result { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index bd02e52794c0..aba7e7dc9c21 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -95,7 +95,7 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind { DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => { ItemKind::Const } - DefKind::Static(_) => ItemKind::Static, + DefKind::Static { .. } => ItemKind::Static, DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const), DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn), } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f592c1d3dd37..7de0555bb220 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1205,6 +1205,7 @@ symbols! { negative_bounds, negative_impls, neon, + nested, never, never_patterns, never_type, diff --git a/compiler/rustc_target/src/spec/base/windows_msvc.rs b/compiler/rustc_target/src/spec/base/windows_msvc.rs index e3cf9757219e..bd0318f31832 100644 --- a/compiler/rustc_target/src/spec/base/windows_msvc.rs +++ b/compiler/rustc_target/src/spec/base/windows_msvc.rs @@ -17,15 +17,19 @@ pub fn opts() -> TargetOptions { crt_static_allows_dylibs: true, crt_static_respected: true, requires_uwtable: true, - // Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC - // as there's been trouble in the past of linking the C++ standard - // library required by LLVM. This likely needs to happen one day, but - // in general Windows is also a more controlled environment than - // Unix, so it's not necessarily as critical that this be implemented. + // We don't pass the /NODEFAULTLIB flag to the linker on MSVC + // as that prevents linker directives embedded in object files from + // including other necessary libraries. // - // Note that there are also some licensing worries about statically - // linking some libraries which require a specific agreement, so it may - // not ever be possible for us to pass this flag. + // For example, msvcrt.lib embeds a linker directive like: + // /DEFAULTLIB:vcruntime.lib /DEFAULTLIB:ucrt.lib + // So that vcruntime.lib and ucrt.lib are included when the entry point + // in msvcrt.lib is used. Using /NODEFAULTLIB would mean having to + // manually add those two libraries and potentially further dependencies + // they bring in. + // + // See also https://learn.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-170#lib + // for documention on including library dependencies in C/C++ code. no_default_libraries: false, has_thread_local: true, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 6bca86af30c0..941d767b850d 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -211,7 +211,7 @@ impl ToJson for LldFlavor { impl LinkerFlavor { /// At this point the target's reference linker flavor doesn't yet exist and we need to infer - /// it. The inference always succeds and gives some result, and we don't report any flavor + /// it. The inference always succeeds and gives some result, and we don't report any flavor /// incompatibility errors for json target specs. The CLI flavor is used as the main source /// of truth, other flags are used in case of ambiguities. fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor { @@ -581,7 +581,7 @@ impl LinkSelfContainedDefault { self == LinkSelfContainedDefault::False } - /// Returns whether the target spec explictly requests self-contained linking, i.e. not via + /// Returns whether the target spec explicitly requests self-contained linking, i.e. not via /// inference. pub fn is_linker_enabled(self) -> bool { match self { @@ -1596,7 +1596,7 @@ supported_targets! { ("wasm32-wasi", wasm32_wasi), ("wasm32-wasip1", wasm32_wasip1), ("wasm32-wasip2", wasm32_wasip2), - ("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads), + ("wasm32-wasip1-threads", wasm32_wasip1_threads), ("wasm64-unknown-unknown", wasm64_unknown_unknown), ("thumbv6m-none-eabi", thumbv6m_none_eabi), @@ -2090,7 +2090,7 @@ pub struct TargetOptions { /// If `None`, then `CFG_DEFAULT_CODEGEN_BACKEND` environmental variable captured when /// compiling `rustc` will be used instead (or llvm if it is not set). /// - /// N.B. when *using* the compiler, backend can always be overriden with `-Zcodegen-backend`. + /// N.B. when *using* the compiler, backend can always be overridden with `-Zcodegen-backend`. pub default_codegen_backend: Option>, /// Whether to generate trap instructions in places where optimization would diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs index eb44520ad9bf..becd2fd7afb2 100644 --- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs @@ -24,7 +24,7 @@ pub fn target() -> Target { Target { llvm_target: "i686-pc-windows-msvc".into(), metadata: crate::spec::TargetMetadata { - description: Some("32-bit MSVC (Windows 7+)".into()), + description: Some("32-bit MSVC (Windows 10+)".into()), tier: Some(1), host_tools: Some(true), std: Some(true), diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs deleted file mode 100644 index 26bdb1cbebef..000000000000 --- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an -//! experimental target. The definition in this file is likely to be tweaked -//! over time and shouldn't be relied on too much. -//! -//! The `wasi-threads` target is a proposal to define a standardized set of syscalls -//! that WebAssembly files can interoperate with. This set of syscalls is -//! intended to empower WebAssembly binaries with native capabilities such as -//! threads, filesystem access, network access, etc. -//! -//! You can see more about the proposal at . -//! -//! The Rust target definition here is interesting in a few ways. We want to -//! serve two use cases here with this target: -//! -//! * First, we want Rust usage of the target to be as hassle-free as possible, -//! ideally avoiding the need to configure and install a local wasm32-wasi-preview1-threads -//! toolchain. -//! -//! * Second, one of the primary use cases of LLVM's new wasm backend and the -//! wasm support in LLD is that any compiled language can interoperate with -//! any other. To that the `wasm32-wasi-preview1-threads` target is the first with a viable C -//! standard library and sysroot common definition, so we want Rust and C/C++ -//! code to interoperate when compiled to `wasm32-unknown-unknown`. -//! -//! You'll note, however, that the two goals above are somewhat at odds with one -//! another. To attempt to solve both use cases in one go we define a target -//! that (ab)uses the `crt-static` target feature to indicate which one you're -//! in. -//! -//! ## No interop with C required -//! -//! By default the `crt-static` target feature is enabled, and when enabled -//! this means that the bundled version of `libc.a` found in `liblibc.rlib` -//! is used. This isn't intended really for interoperation with a C because it -//! may be the case that Rust's bundled C library is incompatible with a -//! foreign-compiled C library. In this use case, though, we use `rust-lld` and -//! some copied crt startup object files to ensure that you can download the -//! wasi target for Rust and you're off to the races, no further configuration -//! necessary. -//! -//! All in all, by default, no external dependencies are required. You can -//! compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, -//! reliably interoperate with C code in this mode (yet). -//! -//! ## Interop with C required -//! -//! For the second goal we repurpose the `target-feature` flag, meaning that -//! you'll need to do a few things to have C/Rust code interoperate. -//! -//! 1. All Rust code needs to be compiled with `-C target-feature=-crt-static`, -//! indicating that the bundled C standard library in the Rust sysroot will -//! not be used. -//! -//! 2. If you're using rustc to build a linked artifact then you'll need to -//! specify `-C linker` to a `clang` binary that supports -//! `wasm32-wasi-preview1-threads` and is configured with the `wasm32-wasi-preview1-threads` sysroot. This -//! will cause Rust code to be linked against the libc.a that the specified -//! `clang` provides. -//! -//! 3. If you're building a staticlib and integrating Rust code elsewhere, then -//! compiling with `-C target-feature=-crt-static` is all you need to do. -//! -//! You can configure the linker via Cargo using the -//! `CARGO_TARGET_WASM32_WASI_LINKER` env var. Be sure to also set -//! `CC_wasm32-wasi-preview1-threads` if any crates in the dependency graph are using the `cc` -//! crate. -//! -//! ## Remember, this is all in flux -//! -//! The wasi target is **very** new in its specification. It's likely going to -//! be a long effort to get it standardized and stable. We'll be following it as -//! best we can with this target. Don't start relying on too much here unless -//! you know what you're getting in to! - -use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; - -pub fn target() -> Target { - let mut options = base::wasm::options(); - - options.os = "wasi".into(); - - options.add_pre_link_args( - LinkerFlavor::WasmLld(Cc::No), - &["--import-memory", "--export-memory", "--shared-memory"], - ); - options.add_pre_link_args( - LinkerFlavor::WasmLld(Cc::Yes), - &[ - "--target=wasm32-wasi-threads", - "-Wl,--import-memory", - "-Wl,--export-memory,", - "-Wl,--shared-memory", - ], - ); - - options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); - options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); - - // FIXME: Figure out cases in which WASM needs to link with a native toolchain. - options.link_self_contained = LinkSelfContainedDefault::True; - - // Right now this is a bit of a workaround but we're currently saying that - // the target by default has a static crt which we're taking as a signal - // for "use the bundled crt". If that's turned off then the system's crt - // will be used, but this means that default usage of this target doesn't - // need an external compiler but it's still interoperable with an external - // compiler if configured correctly. - options.crt_static_default = true; - options.crt_static_respected = true; - - // Allow `+crt-static` to create a "cdylib" output which is just a wasm file - // without a main function. - options.crt_static_allows_dylibs = true; - - // WASI's `sys::args::init` function ignores its arguments; instead, - // `args::args()` makes the WASI API calls itself. - options.main_needs_argc_argv = false; - - // And, WASI mangles the name of "main" to distinguish between different - // signatures. - options.entry_name = "__main_void".into(); - - options.singlethread = false; - options.features = "+atomics,+bulk-memory,+mutable-globals".into(); - - Target { - llvm_target: "wasm32-wasi".into(), - metadata: crate::spec::TargetMetadata { - description: None, - tier: None, - host_tools: None, - std: None, - }, - pointer_width: 32, - data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(), - arch: "wasm32".into(), - options, - } -} diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs new file mode 100644 index 000000000000..c592b944d44a --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1_threads.rs @@ -0,0 +1,74 @@ +//! The `wasm32-wasip1-threads` target is an extension of the `wasm32-wasip1` +//! target where threads are enabled by default for all crates. This target +//! should be considered "in flux" as WASI itself has moved on from "p1" to "p2" +//! now and threads in "p2" are still under heavy design. +//! +//! This target inherits most of the other aspects of `wasm32-wasip1`. +//! +//! Historically this target was known as `wasm32-wasi-preview1-threads`. + +use crate::spec::{base, crt_objects, Cc, LinkSelfContainedDefault, LinkerFlavor, Target}; + +pub fn target() -> Target { + let mut options = base::wasm::options(); + + options.os = "wasi".into(); + + options.add_pre_link_args( + LinkerFlavor::WasmLld(Cc::No), + &["--import-memory", "--export-memory", "--shared-memory"], + ); + options.add_pre_link_args( + LinkerFlavor::WasmLld(Cc::Yes), + &[ + "--target=wasm32-wasip1-threads", + "-Wl,--import-memory", + "-Wl,--export-memory,", + "-Wl,--shared-memory", + ], + ); + + options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained(); + options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained(); + + // FIXME: Figure out cases in which WASM needs to link with a native toolchain. + options.link_self_contained = LinkSelfContainedDefault::True; + + // Right now this is a bit of a workaround but we're currently saying that + // the target by default has a static crt which we're taking as a signal + // for "use the bundled crt". If that's turned off then the system's crt + // will be used, but this means that default usage of this target doesn't + // need an external compiler but it's still interoperable with an external + // compiler if configured correctly. + options.crt_static_default = true; + options.crt_static_respected = true; + + // Allow `+crt-static` to create a "cdylib" output which is just a wasm file + // without a main function. + options.crt_static_allows_dylibs = true; + + // WASI's `sys::args::init` function ignores its arguments; instead, + // `args::args()` makes the WASI API calls itself. + options.main_needs_argc_argv = false; + + // And, WASI mangles the name of "main" to distinguish between different + // signatures. + options.entry_name = "__main_void".into(); + + options.singlethread = false; + options.features = "+atomics,+bulk-memory,+mutable-globals".into(); + + Target { + llvm_target: "wasm32-wasi".into(), + metadata: crate::spec::TargetMetadata { + description: None, + tier: None, + host_tools: None, + std: None, + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(), + arch: "wasm32".into(), + options, + } +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs index da4dc9bf9499..3ef3e5114e68 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs @@ -11,7 +11,7 @@ pub fn target() -> Target { Target { llvm_target: "x86_64-pc-windows-msvc".into(), metadata: crate::spec::TargetMetadata { - description: Some("64-bit MSVC (Windows 7+)".into()), + description: Some("64-bit MSVC (Windows 10+)".into()), tier: Some(1), host_tools: Some(true), std: Some(true), diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 3be53a6591dc..9c7fa5216d76 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -274,7 +274,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let goal = goal.with(self.tcx(), goal.predicate.with_self_ty(self.tcx(), normalized_self_ty)); - debug_assert_eq!(goal, self.resolve_vars_if_possible(goal)); + // Vars that show up in the rest of the goal substs may have been constrained by + // normalizing the self type as well, since type variables are not uniquified. + let goal = self.resolve_vars_if_possible(goal); let mut candidates = vec![]; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1241227a5af3..2924a1865444 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -763,7 +763,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(def_id.as_local()?); match self.tcx.parent_hir_node(hir_id) { - hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. }) => { + hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(local), .. }) => { get_name(err, &local.pat.kind) } // Different to previous arm because one is `&hir::Local` and the other diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index ad5b7debad7b..d18acb8c864b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -3091,6 +3091,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { rustc_transmute::Reason::DstIsTooBig => { format!("The size of `{src}` is smaller than the size of `{dst}`") } + rustc_transmute::Reason::DstRefIsTooBig { src, dst } => { + let src_size = src.size; + let dst_size = dst.size; + format!( + "The referent size of `{src}` ({src_size} bytes) is smaller than that of `{dst}` ({dst_size} bytes)" + ) + } rustc_transmute::Reason::SrcSizeOverflow => { format!( "values of the type `{src}` are too big for the current architecture" diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 68c03e3c73e7..6756b5dec231 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1061,8 +1061,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Integers and floats always have `u8` as their discriminant. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, - // type parameters, opaques, and unnormalized projections have pointer - // metadata if they're known (e.g. by the param_env) to be sized + // type parameters, opaques, and unnormalized projections don't have + // a known discriminant and may need to be normalized further or rely + // on param env for discriminant projections ty::Param(_) | ty::Alias(..) | ty::Bound(..) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 66f740b761d3..89654ed61aeb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -219,6 +219,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Result<(), SelectionError<'tcx>> { debug!(?stack.obligation); + // An error type will unify with anything. So, avoid + // matching an error type with `ParamCandidate`. + // This helps us avoid spurious errors like issue #121941. + if stack.obligation.predicate.references_error() { + return Ok(()); + } + let all_bounds = stack .obligation .param_env diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs index 0441b49cb14c..a7c60c3b4904 100644 --- a/compiler/rustc_transmute/src/layout/mod.rs +++ b/compiler/rustc_transmute/src/layout/mod.rs @@ -35,6 +35,8 @@ pub(crate) trait Def: Debug + Hash + Eq + PartialEq + Copy + Clone { pub trait Ref: Debug + Hash + Eq + PartialEq + Copy + Clone { fn min_align(&self) -> usize; + fn size(&self) -> usize; + fn is_mutable(&self) -> bool; } @@ -48,6 +50,9 @@ impl Ref for ! { fn min_align(&self) -> usize { unreachable!() } + fn size(&self) -> usize { + unreachable!() + } fn is_mutable(&self) -> bool { unreachable!() } @@ -57,6 +62,7 @@ impl Ref for ! { pub mod rustc { use rustc_middle::mir::Mutability; use rustc_middle::ty::{self, Ty}; + use std::fmt::{self, Write}; /// A reference in the layout. #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone, Copy)] @@ -65,6 +71,7 @@ pub mod rustc { pub ty: Ty<'tcx>, pub mutability: Mutability, pub align: usize, + pub size: usize, } impl<'tcx> super::Ref for Ref<'tcx> { @@ -72,6 +79,10 @@ pub mod rustc { self.align } + fn size(&self) -> usize { + self.size + } + fn is_mutable(&self) -> bool { match self.mutability { Mutability::Mut => true, @@ -81,6 +92,16 @@ pub mod rustc { } impl<'tcx> Ref<'tcx> {} + impl<'tcx> fmt::Display for Ref<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_char('&')?; + if self.mutability == Mutability::Mut { + f.write_str("mut ")?; + } + self.ty.fmt(f) + } + } + /// A visibility node in the layout. #[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)] pub enum Def<'tcx> { diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 71b72828e4cf..c2fc55542ffb 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -372,12 +372,15 @@ pub(crate) mod rustc { } ty::Ref(lifetime, ty, mutability) => { - let align = layout_of(tcx, *ty)?.align(); + let layout = layout_of(tcx, *ty)?; + let align = layout.align(); + let size = layout.size(); Ok(Tree::Ref(Ref { lifetime: *lifetime, ty: *ty, mutability: *mutability, align, + size, })) } diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index fefce2640ebd..8f3af491453e 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -23,7 +23,7 @@ pub struct Assume { #[derive(Debug, Hash, Eq, PartialEq, Clone)] pub enum Answer { Yes, - No(Reason), + No(Reason), If(Condition), } @@ -42,7 +42,7 @@ pub enum Condition { /// Answers "why wasn't the source type transmutable into the destination type?" #[derive(Debug, Hash, Eq, PartialEq, PartialOrd, Ord, Clone)] -pub enum Reason { +pub enum Reason { /// The layout of the source type is unspecified. SrcIsUnspecified, /// The layout of the destination type is unspecified. @@ -53,6 +53,13 @@ pub enum Reason { DstMayHaveSafetyInvariants, /// `Dst` is larger than `Src`, and the excess bytes were not exclusively uninitialized. DstIsTooBig, + /// A referent of `Dst` is larger than a referent in `Src`. + DstRefIsTooBig { + /// The referent of the source type. + src: T, + /// The too-large referent of the destination type. + dst: T, + }, /// Src should have a stricter alignment than Dst, but it does not. DstHasStricterAlignment { src_min_align: usize, dst_min_align: usize }, /// Can't go from shared pointer to unique pointer diff --git a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs index 0e05aa4d3b2a..e9f425686c4c 100644 --- a/compiler/rustc_transmute/src/maybe_transmutable/mod.rs +++ b/compiler/rustc_transmute/src/maybe_transmutable/mod.rs @@ -266,6 +266,11 @@ where src_min_align: src_ref.min_align(), dst_min_align: dst_ref.min_align(), }) + } else if dst_ref.size() > src_ref.size() { + Answer::No(Reason::DstRefIsTooBig { + src: src_ref, + dst: dst_ref, + }) } else { // ...such that `src` is transmutable into `dst`, if // `src_ref` is transmutability into `dst_ref`. diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 87462963c27c..e1534af4987d 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -134,7 +134,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::TyParam | DefKind::Const | DefKind::ConstParam - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Ctor(_, _) | DefKind::Macro(_) | DefKind::ExternCrate diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 4a1064b29f6f..fc16edc6d130 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -240,6 +240,10 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { continue; } + if !self.seen.insert(assoc.def_id.expect_local()) { + return; + } + let impl_args = alias_ty.args.rebase_onto( self.tcx, impl_trait_ref.def_id, @@ -318,7 +322,7 @@ fn opaque_types_defined_by<'tcx>( match kind { DefKind::AssocFn | DefKind::Fn - | DefKind::Static(_) + | DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 72fcc95c3b35..63654a453dde 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -41,9 +41,9 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( } } // Walk over the type behind the alias - DefKind::TyAlias {..} | DefKind::AssocTy | + DefKind::TyAlias { .. } | DefKind::AssocTy | // Walk over the type of the item - DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { + DefKind::Static { .. } | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { // If the type of the item uses `_`, we're gonna error out anyway, but // typeck (which type_of invokes below), will call back into opaque_types_defined_by diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 7fda9ceb79ac..92bc2e34561a 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -383,7 +383,7 @@ impl WrappingRange { return Err(error!("Expected size <= 128 bits, but found {} instead", size.bits())); }; if self.start <= max_value && self.end <= max_value { - Ok(self.start == 0 && max_value == self.end) + Ok(self.start == (self.end.wrapping_add(1) & max_value)) } else { Err(error!("Range `{self:?}` out of bounds for size `{}` bits.", size.bits())) } diff --git a/compiler/stable_mir/src/compiler_interface.rs b/compiler/stable_mir/src/compiler_interface.rs index 0f7d8d7e083b..1c51c175d81b 100644 --- a/compiler/stable_mir/src/compiler_interface.rs +++ b/compiler/stable_mir/src/compiler_interface.rs @@ -183,6 +183,7 @@ pub trait Context { fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option; fn krate(&self, def_id: DefId) -> Crate; fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol; + fn intrinsic_name(&self, def: InstanceDef) -> Symbol; /// Return information about the target machine. fn target_info(&self) -> MachineInfo; diff --git a/compiler/stable_mir/src/mir/mono.rs b/compiler/stable_mir/src/mir/mono.rs index 97f57d2c7b35..38e5776c48ce 100644 --- a/compiler/stable_mir/src/mir/mono.rs +++ b/compiler/stable_mir/src/mir/mono.rs @@ -90,6 +90,17 @@ impl Instance { with(|context| context.instance_name(self.def, true)) } + /// Retrieve the plain intrinsic name of an instance if it's an intrinsic. + /// + /// The plain name does not include type arguments (as `trimmed_name` does), + /// which is more convenient to match with intrinsic symbols. + pub fn intrinsic_name(&self) -> Option { + match self.kind { + InstanceKind::Intrinsic => Some(with(|context| context.intrinsic_name(self.def))), + InstanceKind::Item | InstanceKind::Virtual { .. } | InstanceKind::Shim => None, + } + } + /// Resolve an instance starting from a function definition and generic arguments. pub fn resolve(def: FnDef, args: &GenericArgs) -> Result { with(|context| { diff --git a/config.example.toml b/config.example.toml index ddcd0ec02e0d..f94553dd63f7 100644 --- a/config.example.toml +++ b/config.example.toml @@ -543,23 +543,15 @@ # FIXME(#61117): Some tests fail when this option is enabled. #debuginfo-level-tests = 0 -# Should rustc be build with split debuginfo? Default is platform dependent. -# Valid values are the same as those accepted by `-C split-debuginfo` -# (`off`/`unpacked`/`packed`). +# Should rustc and the standard library be built with split debuginfo? Default +# is platform dependent. # -# On Linux, split debuginfo is disabled by default. +# This field is deprecated, use `target..split-debuginfo` instead. # -# On Apple platforms, unpacked split debuginfo is used by default. Unpacked -# debuginfo does not run `dsymutil`, which packages debuginfo from disparate -# object files into a single `.dSYM` file. `dsymutil` adds time to builds for -# no clear benefit, and also makes it more difficult for debuggers to find -# debug info. The compiler currently defaults to running `dsymutil` to preserve -# its historical default, but when compiling the compiler itself, we skip it by -# default since we know it's safe to do so in that case. +# The value specified here is only used when targeting the `build.build` triple, +# and is overridden by `target..split-debuginfo` if specified. # -# On Windows platforms, packed debuginfo is the only supported option, -# producing a `.pdb` file. -#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked } +#split-debuginfo = see target..split-debuginfo # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) #backtrace = true @@ -773,6 +765,26 @@ # Setting this will override the `use-lld` option for Rust code when targeting MSVC. #linker = "cc" (path) +# Should rustc and the standard library be built with split debuginfo? Default +# is platform dependent. +# +# Valid values are the same as those accepted by `-C split-debuginfo` +# (`off`/`unpacked`/`packed`). +# +# On Linux, split debuginfo is disabled by default. +# +# On Apple platforms, unpacked split debuginfo is used by default. Unpacked +# debuginfo does not run `dsymutil`, which packages debuginfo from disparate +# object files into a single `.dSYM` file. `dsymutil` adds time to builds for +# no clear benefit, and also makes it more difficult for debuggers to find +# debug info. The compiler currently defaults to running `dsymutil` to preserve +# its historical default, but when compiling the compiler itself, we skip it by +# default since we know it's safe to do so in that case. +# +# On Windows platforms, packed debuginfo is the only supported option, +# producing a `.pdb` file. +#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked } + # Path to the `llvm-config` binary of the installation of a custom LLVM to link # against. Note that if this is specified we don't compile LLVM at all for this # target. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6bcf7c13e64e..9b786feba898 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -203,8 +203,10 @@ // Language features: // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(diagnostic_namespace))] +#![cfg_attr(bootstrap, feature(exhaustive_patterns))] #![cfg_attr(bootstrap, feature(platform_intrinsics))] #![cfg_attr(not(bootstrap), feature(freeze_impls))] +#![cfg_attr(not(bootstrap), feature(min_exhaustive_patterns))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -229,7 +231,6 @@ #![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] #![feature(effects)] -#![feature(exhaustive_patterns)] #![feature(extern_types)] #![feature(fundamental)] #![feature(generic_arg_infer)] diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 610966625b53..e04bf69ef511 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -73,7 +73,7 @@ pub fn is_available() -> bool { /// The main type provided by this crate, representing an abstract stream of /// tokens, or, more specifically, a sequence of token trees. -/// The type provide interfaces for iterating over those token trees and, conversely, +/// The type provides interfaces for iterating over those token trees and, conversely, /// collecting a number of token trees into one stream. /// /// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]` diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8cf44f4760da..3db5cda83b7d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -270,7 +270,9 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(exhaustive_patterns))] #![cfg_attr(bootstrap, feature(platform_intrinsics))] +#![cfg_attr(not(bootstrap), feature(min_exhaustive_patterns))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] @@ -289,7 +291,6 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(exhaustive_patterns)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] #![feature(lang_items)] diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs index 9c4b926b7ecd..b20574e4f149 100644 --- a/library/std/src/sync/condvar.rs +++ b/library/std/src/sync/condvar.rs @@ -3,7 +3,7 @@ mod tests; use crate::fmt; use crate::sync::{mutex, poison, LockResult, MutexGuard, PoisonError}; -use crate::sys::locks as sys; +use crate::sys::sync as sys; use crate::time::{Duration, Instant}; /// A type indicating whether a timed wait on a condition variable returned diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index 65ff10e02d46..895fcbd6b7ed 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -8,7 +8,7 @@ use crate::mem::ManuallyDrop; use crate::ops::{Deref, DerefMut}; use crate::ptr::NonNull; use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; -use crate::sys::locks as sys; +use crate::sys::sync as sys; /// A mutual exclusion primitive useful for protecting shared data /// diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 2bb4f3f9e038..608229fd674d 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -8,7 +8,7 @@ mod tests; use crate::fmt; use crate::panic::{RefUnwindSafe, UnwindSafe}; -use crate::sys_common::once as sys; +use crate::sys::sync as sys; /// A synchronization primitive which can be used to run a one-time global /// initialization. Useful for one-time initialization for FFI or related diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs index 3c51389fa349..f4975088b372 100644 --- a/library/std/src/sync/poison.rs +++ b/library/std/src/sync/poison.rs @@ -270,6 +270,8 @@ impl fmt::Debug for TryLockError { match *self { #[cfg(panic = "unwind")] TryLockError::Poisoned(..) => "Poisoned(..)".fmt(f), + #[cfg(not(panic = "unwind"))] + TryLockError::Poisoned(ref p) => match p._never {}, TryLockError::WouldBlock => "WouldBlock".fmt(f), } } @@ -281,6 +283,8 @@ impl fmt::Display for TryLockError { match *self { #[cfg(panic = "unwind")] TryLockError::Poisoned(..) => "poisoned lock: another task failed inside", + #[cfg(not(panic = "unwind"))] + TryLockError::Poisoned(ref p) => match p._never {}, TryLockError::WouldBlock => "try_lock failed because the operation would block", } .fmt(f) @@ -294,6 +298,8 @@ impl Error for TryLockError { match *self { #[cfg(panic = "unwind")] TryLockError::Poisoned(ref p) => p.description(), + #[cfg(not(panic = "unwind"))] + TryLockError::Poisoned(ref p) => match p._never {}, TryLockError::WouldBlock => "try_lock failed because the operation would block", } } @@ -303,6 +309,8 @@ impl Error for TryLockError { match *self { #[cfg(panic = "unwind")] TryLockError::Poisoned(ref p) => Some(p), + #[cfg(not(panic = "unwind"))] + TryLockError::Poisoned(ref p) => match p._never {}, _ => None, } } diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index 9a44998ebf64..80b9e0cf1521 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -6,7 +6,7 @@ use crate::fmt; use crate::ops::Deref; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; -use crate::sys::locks as sys; +use crate::sys::sync as sys; /// A re-entrant mutual exclusion lock /// diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 0b3d25c32980..f7f098c082a0 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -8,7 +8,7 @@ use crate::mem::ManuallyDrop; use crate::ops::{Deref, DerefMut}; use crate::ptr::NonNull; use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; -use crate::sys::locks as sys; +use crate::sys::sync as sys; /// A reader-writer lock /// diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 81200e0061e0..bbd1d840e92d 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -6,9 +6,9 @@ mod pal; mod personality; pub mod cmath; -pub mod locks; pub mod os_str; pub mod path; +pub mod sync; #[allow(dead_code)] #[allow(unused_imports)] pub mod thread_local; diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 1fb9d5438dee..c392a0ea264b 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -19,8 +19,6 @@ pub mod fs; #[path = "../unsupported/io.rs"] pub mod io; pub mod net; -#[path = "../unsupported/once.rs"] -pub mod once; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 7c5b37fb4900..562b00c2c01a 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -21,8 +21,6 @@ pub mod fs; pub mod io; #[path = "../unsupported/net.rs"] pub mod net; -#[path = "../unsupported/once.rs"] -pub mod once; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index 9ce275ee72d5..be344fb7caed 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -6,7 +6,6 @@ pub mod env; pub mod fs; pub mod io; pub mod net; -pub mod once; pub mod os; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 308dd2960048..a78547261adf 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -41,8 +41,6 @@ pub mod time; cfg_if::cfg_if! { if #[cfg(not(target_feature = "atomics"))] { - #[path = "../unsupported/once.rs"] - pub mod once; #[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; } diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index b12a8d5ea11c..d1d444d7b798 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -51,10 +51,6 @@ cfg_if::cfg_if! { if #[cfg(target_feature = "atomics")] { compile_error!("The wasm32-wasip2 target does not support atomics"); } else { - #[path = "../unsupported/locks/mod.rs"] - pub mod locks; - #[path = "../unsupported/once.rs"] - pub mod once; #[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; } diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 40b15120e6da..5cbc3e453410 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -48,8 +48,6 @@ cfg_if::cfg_if! { #[path = "atomics/thread.rs"] pub mod thread; } else { - #[path = "../unsupported/once.rs"] - pub mod once; #[path = "../unsupported/thread.rs"] pub mod thread; #[path = "../unsupported/thread_parking.rs"] diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 6c714f76309a..228a976dbabc 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -21,8 +21,6 @@ pub mod fs; pub mod io; #[path = "../unsupported/net.rs"] pub mod net; -#[path = "../unsupported/once.rs"] -pub mod once; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/locks/condvar/futex.rs b/library/std/src/sys/sync/condvar/futex.rs similarity index 98% rename from library/std/src/sys/locks/condvar/futex.rs rename to library/std/src/sys/sync/condvar/futex.rs index 3ad93ce07f75..4586d0fd941a 100644 --- a/library/std/src/sys/locks/condvar/futex.rs +++ b/library/std/src/sys/sync/condvar/futex.rs @@ -1,6 +1,6 @@ use crate::sync::atomic::{AtomicU32, Ordering::Relaxed}; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; -use crate::sys::locks::Mutex; +use crate::sys::sync::Mutex; use crate::time::Duration; pub struct Condvar { diff --git a/library/std/src/sys/locks/condvar/itron.rs b/library/std/src/sys/sync/condvar/itron.rs similarity index 99% rename from library/std/src/sys/locks/condvar/itron.rs rename to library/std/src/sys/sync/condvar/itron.rs index 4c6f5e9dad26..9b64d241efd1 100644 --- a/library/std/src/sys/locks/condvar/itron.rs +++ b/library/std/src/sys/sync/condvar/itron.rs @@ -2,7 +2,7 @@ use crate::sys::pal::itron::{ abi, error::expect_success_aborting, spin::SpinMutex, task, time::with_tmos_strong, }; -use crate::{mem::replace, ptr::NonNull, sys::locks::Mutex, time::Duration}; +use crate::{mem::replace, ptr::NonNull, sys::sync::Mutex, time::Duration}; // The implementation is inspired by the queue-based implementation shown in // Andrew D. Birrell's paper "Implementing Condition Variables with Semaphores" diff --git a/library/std/src/sys/locks/condvar/mod.rs b/library/std/src/sys/sync/condvar/mod.rs similarity index 100% rename from library/std/src/sys/locks/condvar/mod.rs rename to library/std/src/sys/sync/condvar/mod.rs diff --git a/library/std/src/sys/locks/condvar/no_threads.rs b/library/std/src/sys/sync/condvar/no_threads.rs similarity index 94% rename from library/std/src/sys/locks/condvar/no_threads.rs rename to library/std/src/sys/sync/condvar/no_threads.rs index 3f0943b50ee4..36b89c5f5bef 100644 --- a/library/std/src/sys/locks/condvar/no_threads.rs +++ b/library/std/src/sys/sync/condvar/no_threads.rs @@ -1,4 +1,4 @@ -use crate::sys::locks::Mutex; +use crate::sys::sync::Mutex; use crate::time::Duration; pub struct Condvar {} diff --git a/library/std/src/sys/locks/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs similarity index 99% rename from library/std/src/sys/locks/condvar/pthread.rs rename to library/std/src/sys/sync/condvar/pthread.rs index 094738d5a3f2..728371685eee 100644 --- a/library/std/src/sys/locks/condvar/pthread.rs +++ b/library/std/src/sys/sync/condvar/pthread.rs @@ -1,7 +1,7 @@ use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; -use crate::sys::locks::{mutex, Mutex}; +use crate::sys::sync::{mutex, Mutex}; #[cfg(not(target_os = "nto"))] use crate::sys::time::TIMESPEC_MAX; #[cfg(target_os = "nto")] diff --git a/library/std/src/sys/locks/condvar/sgx.rs b/library/std/src/sys/sync/condvar/sgx.rs similarity index 97% rename from library/std/src/sys/locks/condvar/sgx.rs rename to library/std/src/sys/sync/condvar/sgx.rs index cabd3250275a..ecb5872f60d9 100644 --- a/library/std/src/sys/locks/condvar/sgx.rs +++ b/library/std/src/sys/sync/condvar/sgx.rs @@ -1,5 +1,5 @@ -use crate::sys::locks::Mutex; use crate::sys::pal::waitqueue::{SpinMutex, WaitQueue, WaitVariable}; +use crate::sys::sync::Mutex; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use crate::time::Duration; diff --git a/library/std/src/sys/locks/condvar/teeos.rs b/library/std/src/sys/sync/condvar/teeos.rs similarity index 98% rename from library/std/src/sys/locks/condvar/teeos.rs rename to library/std/src/sys/sync/condvar/teeos.rs index c08e8145b8c3..0a931f407d2f 100644 --- a/library/std/src/sys/locks/condvar/teeos.rs +++ b/library/std/src/sys/sync/condvar/teeos.rs @@ -1,7 +1,7 @@ use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; -use crate::sys::locks::mutex::{self, Mutex}; +use crate::sys::sync::mutex::{self, Mutex}; use crate::sys::time::TIMESPEC_MAX; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; use crate::time::Duration; diff --git a/library/std/src/sys/locks/condvar/windows7.rs b/library/std/src/sys/sync/condvar/windows7.rs similarity index 96% rename from library/std/src/sys/locks/condvar/windows7.rs rename to library/std/src/sys/sync/condvar/windows7.rs index 28a288335d2f..07fa5fdd698e 100644 --- a/library/std/src/sys/locks/condvar/windows7.rs +++ b/library/std/src/sys/sync/condvar/windows7.rs @@ -1,7 +1,7 @@ use crate::cell::UnsafeCell; use crate::sys::c; -use crate::sys::locks::{mutex, Mutex}; use crate::sys::os; +use crate::sys::sync::{mutex, Mutex}; use crate::time::Duration; pub struct Condvar { diff --git a/library/std/src/sys/locks/condvar/xous.rs b/library/std/src/sys/sync/condvar/xous.rs similarity index 99% rename from library/std/src/sys/locks/condvar/xous.rs rename to library/std/src/sys/sync/condvar/xous.rs index 0e51449e0afa..7b218818ef8e 100644 --- a/library/std/src/sys/locks/condvar/xous.rs +++ b/library/std/src/sys/sync/condvar/xous.rs @@ -1,6 +1,6 @@ use crate::os::xous::ffi::{blocking_scalar, scalar}; use crate::os::xous::services::{ticktimer_server, TicktimerScalar}; -use crate::sys::locks::Mutex; +use crate::sys::sync::Mutex; use crate::time::Duration; use core::sync::atomic::{AtomicUsize, Ordering}; diff --git a/library/std/src/sys/locks/mod.rs b/library/std/src/sys/sync/mod.rs similarity index 71% rename from library/std/src/sys/locks/mod.rs rename to library/std/src/sys/sync/mod.rs index 0bdc4a1e1db8..623e6bccd515 100644 --- a/library/std/src/sys/locks/mod.rs +++ b/library/std/src/sys/sync/mod.rs @@ -1,7 +1,9 @@ mod condvar; mod mutex; +mod once; mod rwlock; pub use condvar::Condvar; pub use mutex::Mutex; +pub use once::{Once, OnceState}; pub use rwlock::RwLock; diff --git a/library/std/src/sys/locks/mutex/fuchsia.rs b/library/std/src/sys/sync/mutex/fuchsia.rs similarity index 100% rename from library/std/src/sys/locks/mutex/fuchsia.rs rename to library/std/src/sys/sync/mutex/fuchsia.rs diff --git a/library/std/src/sys/locks/mutex/futex.rs b/library/std/src/sys/sync/mutex/futex.rs similarity index 100% rename from library/std/src/sys/locks/mutex/futex.rs rename to library/std/src/sys/sync/mutex/futex.rs diff --git a/library/std/src/sys/locks/mutex/itron.rs b/library/std/src/sys/sync/mutex/itron.rs similarity index 100% rename from library/std/src/sys/locks/mutex/itron.rs rename to library/std/src/sys/sync/mutex/itron.rs diff --git a/library/std/src/sys/locks/mutex/mod.rs b/library/std/src/sys/sync/mutex/mod.rs similarity index 100% rename from library/std/src/sys/locks/mutex/mod.rs rename to library/std/src/sys/sync/mutex/mod.rs diff --git a/library/std/src/sys/locks/mutex/no_threads.rs b/library/std/src/sys/sync/mutex/no_threads.rs similarity index 100% rename from library/std/src/sys/locks/mutex/no_threads.rs rename to library/std/src/sys/sync/mutex/no_threads.rs diff --git a/library/std/src/sys/locks/mutex/pthread.rs b/library/std/src/sys/sync/mutex/pthread.rs similarity index 100% rename from library/std/src/sys/locks/mutex/pthread.rs rename to library/std/src/sys/sync/mutex/pthread.rs diff --git a/library/std/src/sys/locks/mutex/sgx.rs b/library/std/src/sys/sync/mutex/sgx.rs similarity index 100% rename from library/std/src/sys/locks/mutex/sgx.rs rename to library/std/src/sys/sync/mutex/sgx.rs diff --git a/library/std/src/sys/locks/mutex/windows7.rs b/library/std/src/sys/sync/mutex/windows7.rs similarity index 100% rename from library/std/src/sys/locks/mutex/windows7.rs rename to library/std/src/sys/sync/mutex/windows7.rs diff --git a/library/std/src/sys/locks/mutex/xous.rs b/library/std/src/sys/sync/mutex/xous.rs similarity index 100% rename from library/std/src/sys/locks/mutex/xous.rs rename to library/std/src/sys/sync/mutex/xous.rs diff --git a/library/std/src/sys_common/once/futex.rs b/library/std/src/sys/sync/once/futex.rs similarity index 100% rename from library/std/src/sys_common/once/futex.rs rename to library/std/src/sys/sync/once/futex.rs diff --git a/library/std/src/sys_common/once/mod.rs b/library/std/src/sys/sync/once/mod.rs similarity index 94% rename from library/std/src/sys_common/once/mod.rs rename to library/std/src/sys/sync/once/mod.rs index ec57568c54c4..61b29713fa1a 100644 --- a/library/std/src/sys_common/once/mod.rs +++ b/library/std/src/sys/sync/once/mod.rs @@ -30,6 +30,7 @@ cfg_if::cfg_if! { mod queue; pub use queue::{Once, OnceState}; } else { - pub use crate::sys::once::{Once, OnceState}; + mod no_threads; + pub use no_threads::{Once, OnceState}; } } diff --git a/library/std/src/sys/pal/unsupported/once.rs b/library/std/src/sys/sync/once/no_threads.rs similarity index 100% rename from library/std/src/sys/pal/unsupported/once.rs rename to library/std/src/sys/sync/once/no_threads.rs diff --git a/library/std/src/sys_common/once/queue.rs b/library/std/src/sys/sync/once/queue.rs similarity index 100% rename from library/std/src/sys_common/once/queue.rs rename to library/std/src/sys/sync/once/queue.rs diff --git a/library/std/src/sys/locks/rwlock/futex.rs b/library/std/src/sys/sync/rwlock/futex.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/futex.rs rename to library/std/src/sys/sync/rwlock/futex.rs diff --git a/library/std/src/sys/locks/rwlock/mod.rs b/library/std/src/sys/sync/rwlock/mod.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/mod.rs rename to library/std/src/sys/sync/rwlock/mod.rs diff --git a/library/std/src/sys/locks/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/no_threads.rs rename to library/std/src/sys/sync/rwlock/no_threads.rs diff --git a/library/std/src/sys/locks/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/queue.rs rename to library/std/src/sys/sync/rwlock/queue.rs diff --git a/library/std/src/sys/locks/rwlock/sgx.rs b/library/std/src/sys/sync/rwlock/sgx.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/sgx.rs rename to library/std/src/sys/sync/rwlock/sgx.rs diff --git a/library/std/src/sys/locks/rwlock/sgx/tests.rs b/library/std/src/sys/sync/rwlock/sgx/tests.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/sgx/tests.rs rename to library/std/src/sys/sync/rwlock/sgx/tests.rs diff --git a/library/std/src/sys/locks/rwlock/solid.rs b/library/std/src/sys/sync/rwlock/solid.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/solid.rs rename to library/std/src/sys/sync/rwlock/solid.rs diff --git a/library/std/src/sys/locks/rwlock/teeos.rs b/library/std/src/sys/sync/rwlock/teeos.rs similarity index 95% rename from library/std/src/sys/locks/rwlock/teeos.rs rename to library/std/src/sys/sync/rwlock/teeos.rs index 27cdb88788fc..ef9b1ab51546 100644 --- a/library/std/src/sys/locks/rwlock/teeos.rs +++ b/library/std/src/sys/sync/rwlock/teeos.rs @@ -1,4 +1,4 @@ -use crate::sys::locks::mutex::Mutex; +use crate::sys::sync::mutex::Mutex; /// we do not supported rwlock, so use mutex to simulate rwlock. /// it's useful because so many code in std will use rwlock. diff --git a/library/std/src/sys/locks/rwlock/windows7.rs b/library/std/src/sys/sync/rwlock/windows7.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/windows7.rs rename to library/std/src/sys/sync/rwlock/windows7.rs diff --git a/library/std/src/sys/locks/rwlock/xous.rs b/library/std/src/sys/sync/rwlock/xous.rs similarity index 100% rename from library/std/src/sys/locks/rwlock/xous.rs rename to library/std/src/sys/sync/rwlock/xous.rs diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index c9025a81bf3d..5410f135a73f 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -24,7 +24,6 @@ pub mod backtrace; pub mod fs; pub mod io; pub mod lazy_box; -pub mod once; pub mod process; pub mod thread; pub mod thread_info; diff --git a/rust-bors.toml b/rust-bors.toml index 54f4f641248c..f27eb2393675 100644 --- a/rust-bors.toml +++ b/rust-bors.toml @@ -1 +1 @@ -timeout = 7200 +timeout = 14400 diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 242fe3c12b99..94ea2a01a405 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1536,7 +1536,8 @@ impl Step for Sysroot { }; let sysroot = sysroot_dir(compiler.stage); - builder.verbose(&format!("Removing sysroot {} to avoid caching bugs", sysroot.display())); + builder + .verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display())); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); @@ -1606,7 +1607,7 @@ impl Step for Sysroot { return true; } if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) { - builder.verbose_than(1, &format!("ignoring {}", path.display())); + builder.verbose_than(1, || println!("ignoring {}", path.display())); false } else { true @@ -2085,7 +2086,7 @@ pub fn stream_cargo( cargo.arg(arg); } - builder.verbose(&format!("running: {cargo:?}")); + builder.verbose(|| println!("running: {cargo:?}")); if builder.config.dry_run() { return true; diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 613c58252d3b..3efdfc324b86 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2107,7 +2107,7 @@ fn maybe_install_llvm( { let mut cmd = Command::new(llvm_config); cmd.arg("--libfiles"); - builder.verbose(&format!("running {cmd:?}")); + builder.verbose(|| println!("running {cmd:?}")); let files = if builder.config.dry_run() { "".into() } else { output(&mut cmd) }; let build_llvm_out = &builder.llvm_out(builder.config.build); let target_llvm_out = &builder.llvm_out(target); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index c23cd9374a6b..1d4d9d4c2e1b 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -145,7 +145,8 @@ impl Step for RustbookSrc

{ let rustbook = builder.tool_exe(Tool::Rustbook); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); - if !builder.config.dry_run() && !(up_to_date(&src, &index) || up_to_date(&rustbook, &index)) + if !builder.config.dry_run() + && (!up_to_date(&src, &index) || !up_to_date(&rustbook, &index)) { builder.info(&format!("Rustbook ({target}) - {name}")); let _ = fs::remove_dir_all(&out); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 47b0637538b2..e9e2a881d111 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -551,7 +551,7 @@ impl Miri { if builder.config.dry_run() { String::new() } else { - builder.verbose(&format!("running: {cargo:?}")); + builder.verbose(|| println!("running: {cargo:?}")); let out = cargo.output().expect("We already ran `cargo miri setup` before and that worked"); assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code"); @@ -559,7 +559,7 @@ impl Miri { let stdout = String::from_utf8(out.stdout) .expect("`cargo miri setup` stdout is not valid UTF-8"); let sysroot = stdout.trim_end(); - builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {sysroot:?}")); + builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}")); sysroot.to_owned() } } @@ -2326,7 +2326,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> } } - builder.verbose(&format!("doc tests for: {}", markdown.display())); + builder.verbose(|| println!("doc tests for: {}", markdown.display())); let mut cmd = builder.rustdoc_cmd(compiler); builder.add_rust_test_threads(&mut cmd); // allow for unstable options such as new editions diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index 5e5d6d024ee8..7f93fdc72ef0 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -291,7 +291,7 @@ impl PathSet { const PATH_REMAP: &[(&str, &[&str])] = &[ // config.toml uses `rust-analyzer-proc-macro-srv`, but the // actual path is `proc-macro-srv-cli` - ("rust-analyzer-proc-macro-srv", &["proc-macro-srv-cli"]), + ("rust-analyzer-proc-macro-srv", &["src/tools/rust-analyzer/crates/proc-macro-srv-cli"]), // Make `x test tests` function the same as `x t tests/*` ( "tests", @@ -382,10 +382,12 @@ impl StepDescription { } if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) { - builder.verbose(&format!( - "{:?} not skipped for {:?} -- not in {:?}", - pathset, self.name, builder.config.skip - )); + builder.verbose(|| { + println!( + "{:?} not skipped for {:?} -- not in {:?}", + pathset, self.name, builder.config.skip + ) + }); } false } @@ -1093,10 +1095,9 @@ impl<'a> Builder<'a> { // Avoid deleting the rustlib/ directory we just copied // (in `impl Step for Sysroot`). if !builder.download_rustc() { - builder.verbose(&format!( - "Removing sysroot {} to avoid caching bugs", - sysroot.display() - )); + builder.verbose(|| { + println!("Removing sysroot {} to avoid caching bugs", sysroot.display()) + }); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); } @@ -1436,7 +1437,7 @@ impl<'a> Builder<'a> { let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8"); if !matches!(self.config.dry_run, DryRun::SelfCheck) { - self.verbose_than(0, &format!("using sysroot {sysroot_str}")); + self.verbose_than(0, || println!("using sysroot {sysroot_str}")); } let mut rustflags = Rustflags::new(target); @@ -1731,15 +1732,16 @@ impl<'a> Builder<'a> { }, ); + let split_debuginfo = self.config.split_debuginfo(target); let split_debuginfo_is_stable = target.contains("linux") || target.contains("apple") - || (target.is_msvc() && self.config.rust_split_debuginfo == SplitDebuginfo::Packed) - || (target.is_windows() && self.config.rust_split_debuginfo == SplitDebuginfo::Off); + || (target.is_msvc() && split_debuginfo == SplitDebuginfo::Packed) + || (target.is_windows() && split_debuginfo == SplitDebuginfo::Off); if !split_debuginfo_is_stable { rustflags.arg("-Zunstable-options"); } - match self.config.rust_split_debuginfo { + match split_debuginfo { SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"), SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"), SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"), @@ -2102,11 +2104,11 @@ impl<'a> Builder<'a> { panic!("{}", out); } if let Some(out) = self.cache.get(&step) { - self.verbose_than(1, &format!("{}c {:?}", " ".repeat(stack.len()), step)); + self.verbose_than(1, || println!("{}c {:?}", " ".repeat(stack.len()), step)); return out; } - self.verbose_than(1, &format!("{}> {:?}", " ".repeat(stack.len()), step)); + self.verbose_than(1, || println!("{}> {:?}", " ".repeat(stack.len()), step)); stack.push(Box::new(step.clone())); } @@ -2144,7 +2146,7 @@ impl<'a> Builder<'a> { let cur_step = stack.pop().expect("step stack empty"); assert_eq!(cur_step.downcast_ref(), Some(&step)); } - self.verbose_than(1, &format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); + self.verbose_than(1, || println!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); self.cache.put(step, out.clone()); out } diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 6a1dde51603b..7739303aca10 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -115,6 +115,19 @@ fn test_intersection() { assert_eq!(command_paths, vec![Path::new("library/stdarch")]); } +#[test] +fn validate_path_remap() { + let build = Build::new(configure("test", &["A"], &["A"])); + + PATH_REMAP + .iter() + .flat_map(|(_, paths)| paths.iter()) + .map(|path| build.src.join(path)) + .for_each(|path| { + assert!(path.exists(), "{} should exist.", path.display()); + }); +} + #[test] fn test_exclude() { let mut config = configure("test", &["A"], &["A"]); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index ae5169e93839..3e1bc9a9acdd 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -256,7 +256,7 @@ pub struct Config { pub rust_debuginfo_level_std: DebuginfoLevel, pub rust_debuginfo_level_tools: DebuginfoLevel, pub rust_debuginfo_level_tests: DebuginfoLevel, - pub rust_split_debuginfo: SplitDebuginfo, + pub rust_split_debuginfo_for_build_triple: Option, // FIXME: Deprecated field. Remove in Q3'24. pub rust_rpath: bool, pub rust_strip: bool, pub rust_frame_pointers: bool, @@ -574,6 +574,7 @@ pub struct Target { pub ranlib: Option, pub default_linker: Option, pub linker: Option, + pub split_debuginfo: Option, pub sanitizers: Option, pub profiler: Option, pub rpath: Option, @@ -1133,6 +1134,7 @@ define_config! { ranlib: Option = "ranlib", default_linker: Option = "default-linker", linker: Option = "linker", + split_debuginfo: Option = "split-debuginfo", llvm_config: Option = "llvm-config", llvm_has_rust_patches: Option = "llvm-has-rust-patches", llvm_filecheck: Option = "llvm-filecheck", @@ -1627,11 +1629,18 @@ impl Config { debuginfo_level_tools = debuginfo_level_tools_toml; debuginfo_level_tests = debuginfo_level_tests_toml; - config.rust_split_debuginfo = split_debuginfo + config.rust_split_debuginfo_for_build_triple = split_debuginfo .as_deref() .map(SplitDebuginfo::from_str) - .map(|v| v.expect("invalid value for rust.split_debuginfo")) - .unwrap_or(SplitDebuginfo::default_for_platform(config.build)); + .map(|v| v.expect("invalid value for rust.split-debuginfo")); + + if config.rust_split_debuginfo_for_build_triple.is_some() { + println!( + "WARNING: specifying `rust.split-debuginfo` is deprecated, use `target.{}.split-debuginfo` instead", + config.build + ); + } + optimize = optimize_toml; omit_git_hash = omit_git_hash_toml; config.rust_new_symbol_mangling = new_symbol_mangling; @@ -1853,10 +1862,11 @@ impl Config { if let Some(ref s) = cfg.llvm_filecheck { target.llvm_filecheck = Some(config.src.join(s)); } - target.llvm_libunwind = cfg - .llvm_libunwind - .as_ref() - .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")); + target.llvm_libunwind = cfg.llvm_libunwind.as_ref().map(|v| { + v.parse().unwrap_or_else(|_| { + panic!("failed to parse target.{triple}.llvm-libunwind") + }) + }); if let Some(s) = cfg.no_std { target.no_std = s; } @@ -1893,6 +1903,12 @@ impl Config { }).collect()); } + target.split_debuginfo = cfg.split_debuginfo.as_ref().map(|v| { + v.parse().unwrap_or_else(|_| { + panic!("invalid value for target.{triple}.split-debuginfo") + }) + }); + config.target_config.insert(TargetSelection::from_user(&triple), target); } } @@ -2043,7 +2059,7 @@ impl Config { if self.dry_run() { return Ok(()); } - self.verbose(&format!("running: {cmd:?}")); + self.verbose(|| println!("running: {cmd:?}")); build_helper::util::try_run(cmd, self.is_verbose()) } @@ -2230,9 +2246,10 @@ impl Config { } } - pub fn verbose(&self, msg: &str) { + /// Runs a function if verbosity is greater than 0 + pub fn verbose(&self, f: impl Fn()) { if self.verbose > 0 { - println!("{msg}"); + f() } } @@ -2291,6 +2308,16 @@ impl Config { }) } + pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo { + self.target_config + .get(&target) + .and_then(|t| t.split_debuginfo) + .or_else(|| { + if self.build == target { self.rust_split_debuginfo_for_build_triple } else { None } + }) + .unwrap_or_else(|| SplitDebuginfo::default_for_platform(target)) + } + pub fn submodules(&self, rust_info: &GitInfo) -> bool { self.submodules.unwrap_or(rust_info.is_managed_git_subrepository()) } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 27829eab9379..251138388caf 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -61,7 +61,7 @@ impl Config { if self.dry_run() { return true; } - self.verbose(&format!("running: {cmd:?}")); + self.verbose(|| println!("running: {cmd:?}")); check_run(cmd, self.is_verbose()) } @@ -195,7 +195,7 @@ impl Config { } fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) { - self.verbose(&format!("download {url}")); + self.verbose(|| println!("download {url}")); // Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/. let tempfile = self.tempdir().join(dest_path.file_name().unwrap()); // While bootstrap itself only supports http and https downloads, downstream forks might @@ -300,7 +300,9 @@ impl Config { } short_path = t!(short_path.strip_prefix(pattern)); let dst_path = dst.join(short_path); - self.verbose(&format!("extracting {} to {}", original_path.display(), dst.display())); + self.verbose(|| { + println!("extracting {} to {}", original_path.display(), dst.display()) + }); if !t!(member.unpack_in(dst)) { panic!("path traversal attack ??"); } @@ -323,7 +325,7 @@ impl Config { pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool { use sha2::Digest; - self.verbose(&format!("verifying {}", path.display())); + self.verbose(|| println!("verifying {}", path.display())); if self.dry_run() { return false; @@ -379,7 +381,7 @@ enum DownloadSource { /// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions. impl Config { pub(crate) fn download_clippy(&self) -> PathBuf { - self.verbose("downloading stage0 clippy artifacts"); + self.verbose(|| println!("downloading stage0 clippy artifacts")); let date = &self.stage0_metadata.compiler.date; let version = &self.stage0_metadata.compiler.version; @@ -469,7 +471,7 @@ impl Config { } pub(crate) fn download_ci_rustc(&self, commit: &str) { - self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})")); + self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})")); let version = self.artifact_version_part(commit); // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the @@ -486,7 +488,7 @@ impl Config { } pub(crate) fn download_beta_toolchain(&self) { - self.verbose("downloading stage0 beta artifacts"); + self.verbose(|| println!("downloading stage0 beta artifacts")); let date = &self.stage0_metadata.compiler.date; let version = &self.stage0_metadata.compiler.version; @@ -625,10 +627,12 @@ impl Config { self.unpack(&tarball, &bin_root, prefix); return; } else { - self.verbose(&format!( - "ignoring cached file {} due to failed verification", - tarball.display() - )); + self.verbose(|| { + println!( + "ignoring cached file {} due to failed verification", + tarball.display() + ) + }); self.remove(&tarball); } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 9cbd4d367f0f..85211aabb74c 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -288,7 +288,7 @@ macro_rules! forward { } forward! { - verbose(msg: &str), + verbose(f: impl Fn()), is_verbose() -> bool, create(path: &Path, s: &str), remove(f: &Path), @@ -440,11 +440,11 @@ impl Build { .unwrap() .trim(); if local_release.split('.').take(2).eq(version.split('.').take(2)) { - build.verbose(&format!("auto-detected local-rebuild {local_release}")); + build.verbose(|| println!("auto-detected local-rebuild {local_release}")); build.local_rebuild = true; } - build.verbose("finding compilers"); + build.verbose(|| println!("finding compilers")); utils::cc_detect::find(&build); // When running `setup`, the profile is about to change, so any requirements we have now may // be different on the next invocation. Don't check for them until the next time x.py is @@ -452,7 +452,7 @@ impl Build { // // Similarly, for `setup` we don't actually need submodules or cargo metadata. if !matches!(build.config.cmd, Subcommand::Setup { .. }) { - build.verbose("running sanity check"); + build.verbose(|| println!("running sanity check")); crate::core::sanity::check(&mut build); // Make sure we update these before gathering metadata so we don't get an error about missing @@ -464,7 +464,7 @@ impl Build { // Now, update all existing submodules. build.update_existing_submodules(); - build.verbose("learning about cargo"); + build.verbose(|| println!("learning about cargo")); crate::core::metadata::build(&mut build); } @@ -693,7 +693,7 @@ impl Build { let stamp = dir.join(".stamp"); let mut cleared = false; if mtime(&stamp) < mtime(input) { - self.verbose(&format!("Dirty - {}", dir.display())); + self.verbose(|| println!("Dirty - {}", dir.display())); let _ = fs::remove_dir_all(dir); cleared = true; } else if stamp.exists() { @@ -986,7 +986,7 @@ impl Build { } let command = cmd.into(); - self.verbose(&format!("running: {command:?}")); + self.verbose(|| println!("running: {command:?}")); let (output, print_error) = match command.output_mode { mode @ (OutputMode::PrintAll | OutputMode::PrintOutput) => ( @@ -1044,14 +1044,15 @@ impl Build { } } + /// Check if verbosity is greater than the `level` pub fn is_verbose_than(&self, level: usize) -> bool { self.verbosity > level } - /// Prints a message if this build is configured in more verbose mode than `level`. - fn verbose_than(&self, level: usize, msg: &str) { + /// Runs a function if verbosity is greater than `level`. + fn verbose_than(&self, level: usize, f: impl Fn()) { if self.is_verbose_than(level) { - println!("{msg}"); + f() } } @@ -1654,7 +1655,7 @@ impl Build { if self.config.dry_run() { return; } - self.verbose_than(1, &format!("Copy {src:?} to {dst:?}")); + self.verbose_than(1, || println!("Copy {src:?} to {dst:?}")); if src == dst { return; } @@ -1745,7 +1746,7 @@ impl Build { return; } let dst = dstdir.join(src.file_name().unwrap()); - self.verbose_than(1, &format!("Install {src:?} to {dst:?}")); + self.verbose_than(1, || println!("Install {src:?} to {dst:?}")); t!(fs::create_dir_all(dstdir)); if !src.exists() { panic!("ERROR: File \"{}\" not found!", src.display()); diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index ff2992bc896e..3ba4e0cb686e 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -145,15 +145,15 @@ pub fn find_target(build: &Build, target: TargetSelection) { build.cxx.borrow_mut().insert(target, compiler); } - build.verbose(&format!("CC_{} = {:?}", &target.triple, build.cc(target))); - build.verbose(&format!("CFLAGS_{} = {:?}", &target.triple, cflags)); + build.verbose(|| println!("CC_{} = {:?}", &target.triple, build.cc(target))); + build.verbose(|| println!("CFLAGS_{} = {:?}", &target.triple, cflags)); if let Ok(cxx) = build.cxx(target) { let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx); - build.verbose(&format!("CXX_{} = {:?}", &target.triple, cxx)); - build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags)); + build.verbose(|| println!("CXX_{} = {:?}", &target.triple, cxx)); + build.verbose(|| println!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags)); } if let Some(ar) = ar { - build.verbose(&format!("AR_{} = {:?}", &target.triple, ar)); + build.verbose(|| println!("AR_{} = {:?}", &target.triple, ar)); build.ar.borrow_mut().insert(target, ar); } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 85dfe45111fa..14c1dc073069 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -151,4 +151,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New option `rust.llvm-bitcode-linker` that will build the llvm-bitcode-linker.", }, + ChangeInfo { + change_id: 121754, + severity: ChangeSeverity::Warning, + summary: "`rust.split-debuginfo` has been moved to `target..split-debuginfo` and its default value is determined for each target individually.", + }, ]; diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index cbd01606a895..70f25b2cc87c 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -44,7 +44,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bo fn run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool { cmd.stdout(Stdio::piped()); - builder.verbose(&format!("running: {cmd:?}")); + builder.verbose(|| println!("running: {cmd:?}")); let mut process = cmd.spawn().unwrap(); diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index a14dfd1ca123..03f56cba29d8 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -328,7 +328,9 @@ impl<'a> Tarball<'a> { // For `x install` tarball files aren't needed, so we can speed up the process by not producing them. let compression_profile = if self.builder.kind == Kind::Install { - self.builder.verbose("Forcing dist.compression-profile = 'no-op' for `x install`."); + self.builder.verbose(|| { + println!("Forcing dist.compression-profile = 'no-op' for `x install`.") + }); // "no-op" indicates that the rust-installer won't produce compressed tarball sources. "no-op" } else { diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index abd109a6ea3f..9b15bb3530b6 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -113,7 +113,7 @@ ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-wasi ENV TARGETS=$TARGETS,wasm32-wasip1 -ENV TARGETS=$TARGETS,wasm32-wasi-preview1-threads +ENV TARGETS=$TARGETS,wasm32-wasip1-threads ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,x86_64-pc-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 @@ -138,7 +138,7 @@ RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-llvm-bitcode-linker --disable-docs \ --set target.wasm32-wasi.wasi-root=/wasm32-wasip1 \ --set target.wasm32-wasip1.wasi-root=/wasm32-wasip1 \ - --set target.wasm32-wasi-preview1-threads.wasi-root=/wasm32-wasi-preview1-threads \ + --set target.wasm32-wasip1-threads.wasi-root=/wasm32-wasip1-threads \ --musl-root-armv7=/musl-armv7 ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh index 689fe52863e0..8f802eeaa8c0 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-wasi-threads-toolchain.sh @@ -16,7 +16,7 @@ make -j$(nproc) \ NM="$bin/llvm-nm" \ AR="$bin/llvm-ar" \ THREAD_MODEL=posix \ - INSTALL_DIR=/wasm32-wasi-preview1-threads \ + INSTALL_DIR=/wasm32-wasip1-threads \ install cd .. diff --git a/src/doc/reference b/src/doc/reference index 3417f866932c..5afb503a4c1e 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 3417f866932cb1c09c6be0f31d2a02ee01b4b95d +Subproject commit 5afb503a4c1ea3c84370f8f4c08a1cddd1cdf6ad diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 57f1e708f5d5..e09309970945 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 57f1e708f5d5850562bc385aaf610e6af14d6ec8 +Subproject commit e093099709456e6fd74fecd2505fdf49a2471c10 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 7b0ef5b0bea5..8a5d647f19b0 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 7b0ef5b0bea5e3ce3b9764aa5754a60e2cc05c52 +Subproject commit 8a5d647f19b08998612146b1cb2ca47083db63e0 diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 5a0168e30cbb..12a421f3c454 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -62,7 +62,7 @@ - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) - [wasm32-wasip1](platform-support/wasm32-wasip1.md) - - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md) + - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md) - [wasm32-wasip2](platform-support/wasm32-wasip2.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md) diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 2f93252eddcd..7780f2102ba6 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -346,14 +346,13 @@ $ llvm-cov report \ more fine-grained coverage options are added. Using this value is currently not recommended. -### Unstable values +## `-Z coverage-options=` -- `-Z unstable-options -C instrument-coverage=branch`: - Placeholder for potential branch coverage support in the future. -- `-Z unstable-options -C instrument-coverage=except-unused-generics`: - Instrument all functions except unused generics. -- `-Z unstable-options -C instrument-coverage=except-unused-functions`: - Instrument only used (called) functions and instantiated generic functions. +This unstable option provides finer control over some aspects of coverage +instrumentation. Pass one or more of the following values, separated by commas. + +- `branch` or `no-branch` + - Placeholder for potential branch coverage support in the future. ## Other references diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 537a724579eb..285c773afa2d 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -33,12 +33,12 @@ All tier 1 targets with host tools support the full standard library. target | notes -------|------- `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) -`i686-pc-windows-gnu` | 32-bit MinGW (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI] -`i686-pc-windows-msvc` | 32-bit MSVC (Windows 7+) [^windows-support] [^x86_32-floats-return-ABI] +`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+) [^windows-support] [^x86_32-floats-return-ABI] +`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+) [^windows-support] [^x86_32-floats-return-ABI] `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI] `x86_64-apple-darwin` | 64-bit macOS (10.12+, Sierra+) -`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 7+) [^windows-support] -`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 7+) [^windows-support] +`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+) [^windows-support] +`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+) [^windows-support] `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+) [^windows-support]: Only Windows 10 currently undergoes automated testing. Earlier versions of Windows rely on testing and support from the community. @@ -190,7 +190,7 @@ target | std | notes `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename]) [`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI -[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads +[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` @@ -292,7 +292,6 @@ target | std | host | notes [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI] [`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86, restricted to Pentium `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+) [^x86_32-floats-return-ABI] -`i686-pc-windows-msvc` | * | | 32-bit Windows XP support [^x86_32-floats-return-ABI] [`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [^x86_32-floats-return-ABI] `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku [^x86_32-floats-return-ABI] [`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd [^x86_32-floats-return-ABI] @@ -369,7 +368,6 @@ target | std | host | notes [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS | [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | -`x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.3 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md similarity index 83% rename from src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md rename to src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md index b719cb53aba4..519e9cc7cc49 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md @@ -1,12 +1,16 @@ -# `wasm32-wasi-preview1-threads` +# `wasm32-wasip1-threads` **Tier: 2** -The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an -experimental target. This target is an extension to `wasm32-wasi-preview1` target, +The `wasm32-wasip1-threads` target is a new and still (as of July 2023) an +experimental target. This target is an extension to `wasm32-wasip1` target, originally known as `wasm32-wasi`. It extends the original target with a -standardized set of syscalls that are intended to empower WebAssembly binaries with -native multi threading capabilities. +standardized set of syscalls that are intended to empower WebAssembly binaries +with native multi threading capabilities. + +> **Note**: Prior to March 2024 this target was known as +> `wasm32-wasi-preview1-threads`, and even longer before that it was known as +> `wasm32-wasi-threads`. [wasi-threads]: https://github.com/WebAssembly/wasi-threads [threads]: https://github.com/WebAssembly/threads @@ -26,11 +30,11 @@ This target is cross-compiled. The target supports `std` fully. The Rust target definition here is interesting in a few ways. We want to serve two use cases here with this target: * First, we want Rust usage of the target to be as hassle-free as possible, - ideally avoiding the need to configure and install a local wasm32-wasi-preview1-threads + ideally avoiding the need to configure and install a local wasm32-wasip1-threads toolchain. * Second, one of the primary use cases of LLVM's new wasm backend and the wasm support in LLD is that any compiled language can interoperate with - any other. The `wasm32-wasi-preview1-threads` target is the first with a viable C + any other. The `wasm32-wasip1-threads` target is the first with a viable C standard library and sysroot common definition, so we want Rust and C/C++ code to interoperate when compiled to `wasm32-unknown-unknown`. @@ -49,7 +53,7 @@ some copied crt startup object files to ensure that you can download the wasi target for Rust and you're off to the races, no further configuration necessary. All in all, by default, no external dependencies are required. You can -compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, +compile `wasm32-wasip1-threads` binaries straight out of the box. You can't, however, reliably interoperate with C code in this mode (yet). ### Interop with C required For the second goal we repurpose the `target-feature` flag, meaning that @@ -59,18 +63,18 @@ you'll need to do a few things to have C/Rust code interoperate. not be used. 2. If you're using rustc to build a linked artifact then you'll need to specify `-C linker` to a `clang` binary that supports - `wasm32-wasi-preview1-threads` and is configured with the `wasm32-wasi-preview1-threads` sysroot. This + `wasm32-wasip1-threads` and is configured with the `wasm32-wasip1-threads` sysroot. This will cause Rust code to be linked against the libc.a that the specified `clang` provides. 3. If you're building a staticlib and integrating Rust code elsewhere, then compiling with `-C target-feature=-crt-static` is all you need to do. All in all, by default, no external dependencies are required. You can -compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, +compile `wasm32-wasip1-threads` binaries straight out of the box. You can't, however, reliably interoperate with C code in this mode (yet). -Also note that at this time the `wasm32-wasi-preview1-threads` target assumes the +Also note that at this time the `wasm32-wasip1-threads` target assumes the presence of other merged wasm proposals such as (with their LLVM feature flags): * [Bulk memory] - `+bulk-memory` @@ -106,7 +110,7 @@ https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-20 and specify path to *wasi-root* `.cargo/config.toml` ```toml -[target.wasm32-wasi-preview1-threads] +[target.wasm32-wasip1-threads] wasi-root = ".../wasi-libc/sysroot" ``` @@ -118,13 +122,13 @@ After that users can build this by adding it to the `target` list in From Rust Nightly 1.71.1 (2023-08-03) on the artifacts are shipped pre-compiled: ```text -rustup target add wasm32-wasi-preview1-threads --toolchain nightly +rustup target add wasm32-wasip1-threads --toolchain nightly ``` Rust programs can be built for that target: ```text -rustc --target wasm32-wasi-preview1-threads your-code.rs +rustc --target wasm32-wasip1-threads your-code.rs ``` ## Cross-compilation @@ -133,7 +137,7 @@ This target can be cross-compiled from any hosts. ## Testing -Currently testing is not well supported for `wasm32-wasi-preview1-threads` and the +Currently testing is not well supported for `wasm32-wasip1-threads` and the Rust project doesn't run any tests for this target. However the UI testsuite can be run manually following this instructions: @@ -141,8 +145,8 @@ manually following this instructions: or another engine that supports `wasi-threads` is installed and can be found in the `$PATH` env variable. 1. Clone master branch. 2. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1. -3. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests. +3. Run `./x.py test --target wasm32-wasip1-threads tests/ui` and save the list of failed tests. 4. Checkout branch with your changes. 5. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1. -6. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests. +6. Run `./x.py test --target wasm32-wasip1-threads tests/ui` and save the list of failed tests. 7. For both lists of failed tests run `cat list | sort > sorted_list` and compare it with `diff sorted_list1 sorted_list2`. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md index 71f8d281bc88..a1ca81d1fecb 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md @@ -49,7 +49,7 @@ this target are: This target is cross-compiled. The target includes support for `std` itself, but not all of the standard library works. For example spawning a thread will -always return an error (see the `wasm32-wasi-preview1-threads` target for +always return an error (see the `wasm32-wasip1-threads` target for example). Another example is that spawning a process will always return an error. Operations such as opening a file, however, will be implemented by calling WASI-defined APIs. diff --git a/src/doc/unstable-book/src/compiler-flags/coverage-options.md b/src/doc/unstable-book/src/compiler-flags/coverage-options.md new file mode 100644 index 000000000000..105dce615117 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/coverage-options.md @@ -0,0 +1,8 @@ +# `coverage-options` + +This option controls details of the coverage instrumentation performed by +`-C instrument-coverage`. + +Multiple options can be passed, separated by commas. Valid options are: + +- `branch` or `no-branch`: Placeholder for future branch coverage support. diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 03f62f41a26f..77a78f57e950 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -120,7 +120,7 @@ pub(crate) fn try_inline( record_extern_fqn(cx, did, ItemType::Module); clean::ModuleItem(build_module(cx, did, visited)) } - Res::Def(DefKind::Static(_), did) => { + Res::Def(DefKind::Static { .. }, did) => { record_extern_fqn(cx, did, ItemType::Static); cx.with_param_env(did, |cx| { clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did))) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 0b7d35d7be4c..57916ff0ff78 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -526,7 +526,7 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId { | Mod | ForeignTy | Const - | Static(_) + | Static { .. } | Macro(..) | TraitAlias), did, diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index f10c829bf4ee..d5468798bd39 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -128,7 +128,7 @@ impl ItemType { DefKind::Fn => Self::Function, DefKind::Mod => Self::Module, DefKind::Const => Self::Constant, - DefKind::Static(_) => Self::Static, + DefKind::Static { .. } => Self::Static, DefKind::Struct => Self::Struct, DefKind::Union => Self::Union, DefKind::Trait => Self::Trait, diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index e5bb8e6d19ce..0f3debae66c7 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -6,11 +6,13 @@ {# #} {# #} {{page.title}} {# #} + {# #} {# #} { "const" } - DefKind::Static(_) => "static", + DefKind::Static { .. } => "static", // Now handle things that don't have a specific disambiguator _ => match kind .ns() @@ -1514,7 +1514,7 @@ impl Disambiguator { "union" => Kind(DefKind::Union), "module" | "mod" => Kind(DefKind::Mod), "const" | "constant" => Kind(DefKind::Const), - "static" => Kind(DefKind::Static(Mutability::Not)), + "static" => Kind(DefKind::Static { mutability: Mutability::Not, nested: false }), "function" | "fn" | "method" => Kind(DefKind::Fn), "derive" => Kind(DefKind::Macro(MacroKind::Derive)), "type" => NS(Namespace::TypeNS), @@ -1926,7 +1926,7 @@ fn resolution_failure( | OpaqueTy | TraitAlias | TyParam - | Static(_) => "associated item", + | Static { .. } => "associated item", Impl { .. } | GlobalAsm => unreachable!("not a path"), } } else { diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 067bf4054da0..eab9138b8fed 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -149,7 +149,7 @@ static TARGETS: &[&str] = &[ "wasm32-unknown-unknown", "wasm32-wasi", "wasm32-wasip1", - "wasm32-wasi-preview1-threads", + "wasm32-wasip1-threads", "x86_64-apple-darwin", "x86_64-apple-ios", "x86_64-fortanix-unknown-sgx", diff --git a/src/tools/cargo b/src/tools/cargo index a4c63fe5388b..7065f0ef4aa2 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit a4c63fe5388beaa09e5f91196c86addab0a03580 +Subproject commit 7065f0ef4aa267a7455e1c478b5ccacb7baea59c diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs index 9b36cc00444f..91ae19acbf7f 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -52,7 +52,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_ .as_ref() .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)), |stmt| match &stmt.kind { - StmtKind::Local(_) => true, + StmtKind::Let(_) => true, StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr), StmtKind::Item(_) => false, }, diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index 247048bbc49d..acdcb54be271 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -349,7 +349,7 @@ impl BlockEq { /// If the statement is a local, checks if the bound names match the expected list of names. fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool { - if let StmtKind::Local(l) = s.kind { + if let StmtKind::Let(l) = s.kind { let mut i = 0usize; let mut res = true; l.pat.each_binding_or_first(&mut |_, _, _, name| { @@ -389,7 +389,7 @@ fn eq_stmts( eq: &mut HirEqInterExpr<'_, '_, '_>, moved_bindings: &mut Vec<(HirId, Symbol)>, ) -> bool { - (if let StmtKind::Local(l) = stmt.kind { + (if let StmtKind::Let(l) = stmt.kind { let old_count = moved_bindings.len(); l.pat.each_binding_or_first(&mut |_, id, _, name| { moved_bindings.push((id, name.name)); @@ -432,7 +432,7 @@ fn scan_block_for_eq<'tcx>( .iter() .enumerate() .find(|&(i, stmt)| { - if let StmtKind::Local(l) = stmt.kind + if let StmtKind::Let(l) = stmt.kind && needs_ordered_drop(cx, cx.typeck_results().node_type(l.hir_id)) { local_needs_ordered_drop = true; @@ -509,7 +509,7 @@ fn scan_block_for_eq<'tcx>( // Clear out all locals seen at the end so far. None of them can be moved. let stmts = &blocks[0].stmts; for stmt in &stmts[stmts.len() - init..=stmts.len() - offset] { - if let StmtKind::Local(l) = stmt.kind { + if let StmtKind::Let(l) = stmt.kind { l.pat.each_binding_or_first(&mut |_, id, _, _| { // FIXME(rust/#120456) - is `swap_remove` correct? eq.locals.swap_remove(&id); diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 8789efcc9944..98a6d9370c34 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { // find all binding statements like `let mut _ = T::default()` where `T::default()` is the // `default` method of the `Default` trait, and store statement index in current block being // checked and the name of the bound variable - let (local, variant, binding_name, binding_type, span) = if let StmtKind::Local(local) = stmt.kind + let (local, variant, binding_name, binding_type, span) = if let StmtKind::Let(local) = stmt.kind // only take `let ...` statements && let Some(expr) = local.init && !any_parent_is_automatically_derived(cx.tcx, expr.hir_id) diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 59d2df0295fb..1d6c4ce72e18 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { match stmt.kind { // we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric` - StmtKind::Local(local) => self.ty_bounds.push(ExplicitTyBound(local.ty.is_some())), + StmtKind::Let(local) => self.ty_bounds.push(ExplicitTyBound(local.ty.is_some())), _ => self.ty_bounds.push(ExplicitTyBound(false)), } diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index de6073c27236..ebda2ad83870 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -423,7 +423,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { } }, StmtKind::Expr(e) => self.visit_expr(e), - StmtKind::Local(l) => { + StmtKind::Let(l) => { self.visit_pat(l.pat); if let Some(e) = l.init { self.allow_insert_closure &= !self.in_tail_pos; diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index de048fef5f22..2e9bec6a7b08 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) -> &'tcx ExprKind<'hir> { if let ExprKind::Block(block, _label @ None) = kind && let Block { - stmts: [Stmt { kind: StmtKind::Local(local), .. }], + stmts: [Stmt { kind: StmtKind::Let(local), .. }], expr: Some(expr_end_of_block), rules: BlockCheckMode::DefaultBlock, .. diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 270162ae7717..f084d89ccc28 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { let mut it = block.stmts.iter().peekable(); while let Some(stmt) = it.next() { if let Some(expr) = it.peek() - && let hir::StmtKind::Local(local) = stmt.kind + && let hir::StmtKind::Let(local) = stmt.kind && let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind && let hir::StmtKind::Expr(if_) = expr.kind && let hir::ExprKind::If( diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index 18f799e875a0..a7c1d1bd6cd3 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -410,7 +410,7 @@ fn get_assignments<'a, 'tcx>( stmts .iter() .filter_map(move |stmt| match stmt.kind { - StmtKind::Local(..) | StmtKind::Item(..) => None, + StmtKind::Let(..) | StmtKind::Item(..) => None, StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) .chain(*expr) diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs index ca584a454d03..b00a082bb8cf 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs @@ -72,7 +72,7 @@ fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr } fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && is_vec_pop_unwrap(cx, init, is_empty_recv) { diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 08b8a9e2ff07..47dc3807e624 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -273,7 +273,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { } return false; // no need to walk further *on the variable* }, - Res::Def(DefKind::Static(_) | DefKind::Const, ..) => { + Res::Def(DefKind::Static{..} | DefKind::Const, ..) => { if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 65d922f03df3..6cc79440f39a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -137,7 +137,7 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t match stmt.kind { StmtKind::Semi(e) | StmtKind::Expr(e) => Some((e, None)), // add the let...else expression (if present) - StmtKind::Local(local) => local.init.map(|init| (init, local.els)), + StmtKind::Let(local) => local.init.map(|init| (init, local.els)), StmtKind::Item(..) => None, } } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs index 9fd9b7a16312..3511d24e8134 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> { Res::Local(hir_id) => { self.ids.insert(hir_id); }, - Res::Def(DefKind::Static(_), def_id) => { + Res::Def(DefKind::Static{..}, def_id) => { let mutable = self.cx.tcx.is_mutable_static(def_id); self.def_ids.insert(def_id, mutable); }, diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs index 735d704a43ce..93774b897682 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs @@ -11,7 +11,7 @@ use rustc_lint::LateContext; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) { let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) { ([stmt, stmts @ ..], expr) => { - if let StmtKind::Local(&Local { + if let StmtKind::Let(&Local { init: Some(e), els: None, .. diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index fdf8fa4e2771..03e4d668dd8f 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -53,7 +53,7 @@ impl<'tcx> QuestionMark { return; } - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && local.els.is_none() && local.ty.is_none() diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index 3b82c50a84e6..c9eab7109ebc 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -138,7 +138,7 @@ fn reduce_unit_expression(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option< // If block only contains statements, // reduce `{ X; }` to `X` or `X;` match inner_stmt.kind { - hir::StmtKind::Local(local) => Some(local.span), + hir::StmtKind::Let(local) => Some(local.span), hir::StmtKind::Expr(e) => Some(e.span), hir::StmtKind::Semi(..) => Some(inner_stmt.span), hir::StmtKind::Item(..) => None, diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs index f0fc925799a3..e2c2997594ad 100644 --- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs +++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs @@ -91,7 +91,7 @@ pub(super) fn check<'tcx>( }, hir::ExprKind::Path(ref p) => matches!( cx.qpath_res(p, arg.hir_id), - hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static(_), _) + hir::def::Res::Def(hir::def::DefKind::Const | hir::def::DefKind::Static{..}, _) ), _ => false, } diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 55050ae693e7..78540353005d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -424,7 +424,7 @@ fn get_expr_and_hir_id_from_stmt<'v>(stmt: &'v Stmt<'v>) -> Option<(&'v Expr<'v> match stmt.kind { StmtKind::Expr(expr) | StmtKind::Semi(expr) => Some((expr, None)), StmtKind::Item(..) => None, - StmtKind::Local(Local { init, pat, .. }) => { + StmtKind::Let(Local { init, pat, .. }) => { if let PatKind::Binding(_, hir_id, ..) = pat.kind { init.map(|init_expr| (init_expr, Some(hir_id))) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 0e7ad8fc996e..55cd1a38ec96 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -198,7 +198,7 @@ fn indirect_usage<'tcx>( binding: HirId, ctxt: SyntaxContext, ) -> Option> { - if let StmtKind::Local(&Local { + if let StmtKind::Let(&Local { pat: Pat { kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None), .. diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs index 7b0cf48ac43b..cdfaa690d5f4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs @@ -27,7 +27,7 @@ fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &E fn get_last_chain_binding_hir_id(mut hir_id: HirId, statements: &[Stmt<'_>]) -> Option { for stmt in statements { - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && let ExprKind::Path(QPath::Resolved(_, path)) = init.kind && let hir::def::Res::Local(local_hir_id) = path.res diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index b9784a58596c..4094d7ded7d8 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if !in_external_macro(cx.tcx.sess, stmt.span) - && let StmtKind::Local(local) = stmt.kind + && let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind && let Some(init) = local.init // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue. diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index a1f7dc7b38c4..12c7c18afde6 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { match stmt.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { if let Local { init: Some(e), .. } = local { DivergenceVisitor { cx }.visit_expr(e); } @@ -291,7 +291,7 @@ fn check_stmt<'tcx>(vis: &mut ReadVisitor<'_, 'tcx>, stmt: &'tcx Stmt<'_>) -> St StmtKind::Expr(expr) | StmtKind::Semi(expr) => check_expr(vis, expr), // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. - StmtKind::Local(local) => local + StmtKind::Let(local) => local .init .as_ref() .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)), diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index 049f44f3246f..70fd07cd93ce 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -109,7 +109,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static(Mutability::Mut), _), + res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _), .. }, )) => { @@ -149,7 +149,7 @@ fn collect_unsafe_exprs<'tcx>( ExprKind::Path(QPath::Resolved( _, hir::Path { - res: Res::Def(DefKind::Static(Mutability::Mut), _), + res: Res::Def(DefKind::Static{mutability:Mutability::Mut, ..}, _), .. } )) diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 3e63c0a1d36e..4cda4b171e31 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -86,7 +86,7 @@ fn contains_let(cond: &Expr<'_>) -> bool { } fn stmt_needs_ordered_drop(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { - let StmtKind::Local(local) = stmt.kind else { + let StmtKind::Let(local) = stmt.kind else { return false; }; !local.pat.walk_short(|pat| { diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index cac34c8ce06e..43810ec0ec74 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -174,7 +174,7 @@ impl NoEffect { ); return true; } - } else if let StmtKind::Local(local) = stmt.kind { + } else if let StmtKind::Let(local) = stmt.kind { if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) && !matches!(local.source, LocalSource::AsyncFn) && let Some(init) = local.init diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index 60ced9c12082..fbca4329342a 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -82,7 +82,7 @@ declare_lint_pass!(PatternTypeMismatch => [PATTERN_TYPE_MISMATCH]); impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if let StmtKind::Local(local) = stmt.kind { + if let StmtKind::Let(local) = stmt.kind { if in_external_macro(cx.sess(), local.pat.span) { return; } diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index cf7f730140ce..831c291ed7cc 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -109,7 +109,7 @@ fn find_let_else_ret_expression<'hir>(block: &'hir Block<'hir>) -> Option<&'hir } fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { - if let StmtKind::Local(Local { + if let StmtKind::Let(Local { pat, init: Some(init_expr), els: Some(els), diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs index 650324d4249e..d0b37cd92e00 100644 --- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs +++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { return; } - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Local { pat, init: Some(init), .. } = local diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index f61527cc0a9f..c2673bc409fa 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -262,7 +262,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { } for w in block.stmts.windows(2) { - if let hir::StmtKind::Local(local) = w[0].kind + if let hir::StmtKind::Let(local) = w[0].kind && let Option::Some(t) = local.init && let hir::ExprKind::Closure { .. } = t.kind && let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 2af466d3f51e..196975274674 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { // we need both a let-binding stmt and an expr if let Some(retexpr) = block.expr && let Some(stmt) = block.stmts.iter().last() - && let StmtKind::Local(local) = &stmt.kind + && let StmtKind::Let(local) = &stmt.kind && local.ty.is_none() && cx.tcx.hir().attrs(local.hir_id).is_empty() && let Some(initexpr) = &local.init diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index 6c99ccda7ea7..f8726aa173a9 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -236,7 +236,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx fn manage_has_expensive_expr_after_last_attr(&mut self) { let has_expensive_stmt = match self.ap.curr_stmt.kind { hir::StmtKind::Expr(expr) if is_inexpensive_expr(expr) => false, - hir::StmtKind::Local(local) + hir::StmtKind::Let(local) if let Some(expr) = local.init && let hir::ExprKind::Path(_) = expr.kind => { @@ -290,7 +290,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o }; let mut ac = AttrChecker::new(self.cx, self.seen_types, self.type_cache); if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) { - if let hir::StmtKind::Local(local) = self.ap.curr_stmt.kind + if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind && !self.ap.apas.contains_key(&hir_id) && { @@ -326,7 +326,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o return; }; match self.ap.curr_stmt.kind { - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { apa.last_bind_ident = ident; } diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 4837f2858a66..ff8e8fe70217 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` // or `Vec::new()` - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind && let Some(init) = local.init && let Some(size_expr) = Self::as_vec_initializer(cx, init) diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index daa6fe8715ca..be590aede158 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -148,7 +148,7 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { } for [s1, s2, s3] in block.stmts.array_windows::<3>() { - if let StmtKind::Local(tmp) = s1.kind + if let StmtKind::Let(tmp) = s1.kind // let t = foo(); && let Some(tmp_init) = tmp.init && let PatKind::Binding(.., ident, None) = tmp.pat.kind @@ -243,7 +243,7 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr< if let ExprKind::Assign(lhs, rhs, _) = expr.kind { return Some((ExprOrIdent::Expr(lhs), rhs)); } - } else if let StmtKind::Local(expr) = stmt.kind { + } else if let StmtKind::Let(expr) = stmt.kind { if let Some(rhs) = expr.init { if let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind { return Some((ExprOrIdent::Ident(ident_l), rhs)); diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 559d7ace40ed..0efa65b28e23 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -158,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &hir::Stmt<'tcx>) { - let (hir::StmtKind::Local(&hir::Local { init: Some(expr), .. }) + let (hir::StmtKind::Let(&hir::Local { init: Some(expr), .. }) | hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr)) = stmt.kind else { @@ -358,7 +358,7 @@ fn block_parents_have_safety_comment( }, Node::Stmt(hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { span, hir_id, .. }) + hir::StmtKind::Let(hir::Local { span, hir_id, .. }) | hir::StmtKind::Expr(hir::Expr { span, hir_id, .. }) | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }), .. diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs index fc8519d56283..9ffcfcc0f50c 100644 --- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs +++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs @@ -153,7 +153,7 @@ impl<'tcx> VecLocation<'tcx> { /// or `self` expression for `Vec::reserve()`. fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> Option> { match stmt.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { if let Some(init_expr) = local.init && let PatKind::Binding(_, hir_id, _, None) = local.pat.kind && let Some(init_kind) = get_vec_init_kind(cx, init_expr) diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 6b3ea7700b73..eb64dd633f60 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -61,10 +61,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { /// we need to check them at `check_expr` or `check_block` as they are not stmts /// but we can't check them at `check_expr` because we need the broader context /// because we should do this only for the final expression of the block, and not for - /// `StmtKind::Local` which binds values => the io amount is used. + /// `StmtKind::Let` which binds values => the io amount is used. /// /// To check for unused io amount in stmts, we only consider `StmtKind::Semi`. - /// `StmtKind::Local` is not considered because it binds values => the io amount is used. + /// `StmtKind::Let` is not considered because it binds values => the io amount is used. /// `StmtKind::Expr` is not considered because requires unit type => the io amount is used. /// `StmtKind::Item` is not considered because it's not an expression. /// diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs index ba72b3450b93..f1d0c22b1aec 100644 --- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs +++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable { for (idx, stmt) in block.stmts.iter().enumerate() { if !stmt.span.from_expansion() - && let StmtKind::Local(local) = stmt.kind + && let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(_, binding, ident, _) = local.pat.kind && let Some(init) = local.init && !init.span.from_expansion() @@ -197,7 +197,7 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { }, Node::Stmt(stmt) => { match stmt.kind { - StmtKind::Local(_) | StmtKind::Item(_) => self.found_peek_call = true, + StmtKind::Let(_) | StmtKind::Item(_) => self.found_peek_call = true, StmtKind::Expr(_) | StmtKind::Semi(_) => {}, } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index a0a6382046d0..187bfda129cd 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -724,7 +724,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } match stmt.value.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { bind!(self, local); kind!("Local({local})"); self.option(field!(local.init), "init", |init| { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 3b3939da7b6b..3874c1169e48 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -267,7 +267,7 @@ pub fn eq_block(l: &Block, r: &Block) -> bool { pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { use StmtKind::*; match (&l.kind, &r.kind) { - (Local(l), Local(r)) => { + (Let(l), Let(r)) => { eq_pat(&l.pat, &r.pat) && both(&l.ty, &r.ty, |l, r| eq_ty(l, r)) && eq_local_kind(&l.kind, &r.kind) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index f7f5f7ca35ff..106d1d0d77f0 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -108,7 +108,7 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> { impl HirEqInterExpr<'_, '_, '_> { pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool { match (&left.kind, &right.kind) { - (&StmtKind::Local(l), &StmtKind::Local(r)) => { + (&StmtKind::Let(l), &StmtKind::Let(r)) => { // This additional check ensures that the type of the locals are equivalent even if the init // expression or type have some inferred parts. if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results { @@ -1030,7 +1030,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { std::mem::discriminant(&b.kind).hash(&mut self.s); match &b.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { self.hash_pat(local.pat); if let Some(init) = local.init { self.hash_expr(init); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 708037a46555..dc0725730322 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2161,7 +2161,7 @@ pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { Node::Stmt(Stmt { kind: StmtKind::Expr(_) | StmtKind::Semi(_) - | StmtKind::Local(Local { + | StmtKind::Let(Local { pat: Pat { kind: PatKind::Wild, .. diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 213e2a63517e..a512599f723b 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -694,7 +694,6 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "check-stdout", "check-test-line-numbers-match", "compile-flags", - "count", "dont-check-compiler-stderr", "dont-check-compiler-stdout", "dont-check-failure-status", @@ -853,6 +852,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-sparc64", "only-stable", "only-thumb", + "only-unix", "only-wasm32", "only-wasm32-bare", "only-windows", diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 433f3e8b5559..cf300fbe74fe 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -285,6 +285,7 @@ fn ignore_target() { assert!(check_ignore(&config, "//@ ignore-x86_64-unknown-linux-gnu")); assert!(check_ignore(&config, "//@ ignore-x86_64")); assert!(check_ignore(&config, "//@ ignore-linux")); + assert!(check_ignore(&config, "//@ ignore-unix")); assert!(check_ignore(&config, "//@ ignore-gnu")); assert!(check_ignore(&config, "//@ ignore-64bit")); @@ -300,6 +301,7 @@ fn only_target() { assert!(check_ignore(&config, "//@ only-x86")); assert!(check_ignore(&config, "//@ only-linux")); + assert!(check_ignore(&config, "//@ only-unix")); assert!(check_ignore(&config, "//@ only-msvc")); assert!(check_ignore(&config, "//@ only-32bit")); diff --git a/src/tools/miri/src/intptrcast.rs b/src/tools/miri/src/alloc_addresses/mod.rs similarity index 78% rename from src/tools/miri/src/intptrcast.rs rename to src/tools/miri/src/alloc_addresses/mod.rs index 3fe127f97326..e1714aa9e46b 100644 --- a/src/tools/miri/src/intptrcast.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -1,3 +1,8 @@ +//! This module is responsible for managing the absolute addresses that allocations are located at, +//! and for casting between pointers and integers based on those addresses. + +mod reuse_pool; + use std::cell::RefCell; use std::cmp::max; use std::collections::hash_map::Entry; @@ -6,9 +11,10 @@ use rand::Rng; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_span::Span; -use rustc_target::abi::{HasDataLayout, Size}; +use rustc_target::abi::{Align, HasDataLayout, Size}; use crate::*; +use reuse_pool::ReusePool; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ProvenanceMode { @@ -23,7 +29,7 @@ pub enum ProvenanceMode { pub type GlobalState = RefCell; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct GlobalStateInner { /// This is used as a map between the address of each allocation and its `AllocId`. It is always /// sorted by address. We cannot use a `HashMap` since we can be given an address that is offset @@ -35,6 +41,8 @@ pub struct GlobalStateInner { /// they do not have an `AllocExtra`. /// This is the inverse of `int_to_ptr_map`. base_addr: FxHashMap, + /// A pool of addresses we can reuse for future allocations. + reuse: ReusePool, /// Whether an allocation has been exposed or not. This cannot be put /// into `AllocExtra` for the same reason as `base_addr`. exposed: FxHashSet, @@ -50,6 +58,7 @@ impl VisitProvenance for GlobalStateInner { let GlobalStateInner { int_to_ptr_map: _, base_addr: _, + reuse: _, exposed: _, next_base_addr: _, provenance_mode: _, @@ -68,6 +77,7 @@ impl GlobalStateInner { GlobalStateInner { int_to_ptr_map: Vec::default(), base_addr: FxHashMap::default(), + reuse: ReusePool::new(), exposed: FxHashSet::default(), next_base_addr: stack_addr, provenance_mode: config.provenance_mode, @@ -96,7 +106,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // or `None` if the addr is out of bounds fn alloc_id_from_addr(&self, addr: u64) -> Option { let ecx = self.eval_context_ref(); - let global_state = ecx.machine.intptrcast.borrow(); + let global_state = ecx.machine.alloc_addresses.borrow(); assert!(global_state.provenance_mode != ProvenanceMode::Strict); let pos = global_state.int_to_ptr_map.binary_search_by_key(&addr, |(addr, _)| *addr); @@ -133,12 +143,13 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn addr_from_alloc_id(&self, alloc_id: AllocId) -> InterpResult<'tcx, u64> { let ecx = self.eval_context_ref(); - let mut global_state = ecx.machine.intptrcast.borrow_mut(); + let mut global_state = ecx.machine.alloc_addresses.borrow_mut(); let global_state = &mut *global_state; Ok(match global_state.base_addr.entry(alloc_id) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { + let mut rng = ecx.machine.rng.borrow_mut(); let (size, align, kind) = ecx.get_alloc_info(alloc_id); // This is either called immediately after allocation (and then cached), or when // adjusting `tcx` pointers (which never get freed). So assert that we are looking @@ -147,44 +158,63 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // information was removed. assert!(!matches!(kind, AllocKind::Dead)); - // This allocation does not have a base address yet, pick one. - // Leave some space to the previous allocation, to give it some chance to be less aligned. - let slack = { - let mut rng = ecx.machine.rng.borrow_mut(); - // This means that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. - rng.gen_range(0..16) + // This allocation does not have a base address yet, pick or reuse one. + let base_addr = if let Some(reuse_addr) = + global_state.reuse.take_addr(&mut *rng, size, align) + { + reuse_addr + } else { + // We have to pick a fresh address. + // Leave some space to the previous allocation, to give it some chance to be less aligned. + // We ensure that `(global_state.next_base_addr + slack) % 16` is uniformly distributed. + let slack = rng.gen_range(0..16); + // From next_base_addr + slack, round up to adjust for alignment. + let base_addr = global_state + .next_base_addr + .checked_add(slack) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + let base_addr = align_addr(base_addr, align.bytes()); + + // Remember next base address. If this allocation is zero-sized, leave a gap + // of at least 1 to avoid two allocations having the same base address. + // (The logic in `alloc_id_from_addr` assumes unique addresses, and different + // function/vtable pointers need to be distinguishable!) + global_state.next_base_addr = base_addr + .checked_add(max(size.bytes(), 1)) + .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; + // Even if `Size` didn't overflow, we might still have filled up the address space. + if global_state.next_base_addr > ecx.target_usize_max() { + throw_exhaust!(AddressSpaceFull); + } + + base_addr }; - // From next_base_addr + slack, round up to adjust for alignment. - let base_addr = global_state - .next_base_addr - .checked_add(slack) - .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - let base_addr = align_addr(base_addr, align.bytes()); - entry.insert(base_addr); trace!( - "Assigning base address {:#x} to allocation {:?} (size: {}, align: {}, slack: {})", + "Assigning base address {:#x} to allocation {:?} (size: {}, align: {})", base_addr, alloc_id, size.bytes(), align.bytes(), - slack, ); - // Remember next base address. If this allocation is zero-sized, leave a gap - // of at least 1 to avoid two allocations having the same base address. - // (The logic in `alloc_id_from_addr` assumes unique addresses, and different - // function/vtable pointers need to be distinguishable!) - global_state.next_base_addr = base_addr - .checked_add(max(size.bytes(), 1)) - .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - // Even if `Size` didn't overflow, we might still have filled up the address space. - if global_state.next_base_addr > ecx.target_usize_max() { - throw_exhaust!(AddressSpaceFull); - } - // Also maintain the opposite mapping in `int_to_ptr_map`. - // Given that `next_base_addr` increases in each allocation, pushing the - // corresponding tuple keeps `int_to_ptr_map` sorted - global_state.int_to_ptr_map.push((base_addr, alloc_id)); + // Store address in cache. + entry.insert(base_addr); + + // Also maintain the opposite mapping in `int_to_ptr_map`, ensuring we keep it sorted. + // We have a fast-path for the common case that this address is bigger than all previous ones. + let pos = if global_state + .int_to_ptr_map + .last() + .is_some_and(|(last_addr, _)| *last_addr < base_addr) + { + global_state.int_to_ptr_map.len() + } else { + global_state + .int_to_ptr_map + .binary_search_by_key(&base_addr, |(addr, _)| *addr) + .unwrap_err() + }; + global_state.int_to_ptr_map.insert(pos, (base_addr, alloc_id)); base_addr } @@ -196,7 +226,7 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn expose_ptr(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { let ecx = self.eval_context_mut(); - let global_state = ecx.machine.intptrcast.get_mut(); + let global_state = ecx.machine.alloc_addresses.get_mut(); // In strict mode, we don't need this, so we can save some cycles by not tracking it. if global_state.provenance_mode == ProvenanceMode::Strict { return Ok(()); @@ -207,7 +237,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(()); } trace!("Exposing allocation id {alloc_id:?}"); - let global_state = ecx.machine.intptrcast.get_mut(); + let global_state = ecx.machine.alloc_addresses.get_mut(); global_state.exposed.insert(alloc_id); if ecx.machine.borrow_tracker.is_some() { ecx.expose_tag(alloc_id, tag)?; @@ -219,7 +249,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { trace!("Casting {:#x} to a pointer", addr); let ecx = self.eval_context_ref(); - let global_state = ecx.machine.intptrcast.borrow(); + let global_state = ecx.machine.alloc_addresses.borrow(); // Potentially emit a warning. match global_state.provenance_mode { @@ -299,7 +329,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } impl GlobalStateInner { - pub fn free_alloc_id(&mut self, dead_id: AllocId) { + pub fn free_alloc_id( + &mut self, + rng: &mut impl Rng, + dead_id: AllocId, + size: Size, + align: Align, + ) { // We can *not* remove this from `base_addr`, since the interpreter design requires that we // be able to retrieve an AllocId + offset for any memory access *before* we check if the // access is valid. Specifically, `ptr_get_alloc` is called on each attempt at a memory @@ -319,6 +355,8 @@ impl GlobalStateInner { // We can also remove it from `exposed`, since this allocation can anyway not be returned by // `alloc_id_from_addr` any more. self.exposed.remove(&dead_id); + // Also remember this address for future reuse. + self.reuse.add_addr(rng, addr, size, align) } } diff --git a/src/tools/miri/src/alloc_addresses/reuse_pool.rs b/src/tools/miri/src/alloc_addresses/reuse_pool.rs new file mode 100644 index 000000000000..8374d0ec605a --- /dev/null +++ b/src/tools/miri/src/alloc_addresses/reuse_pool.rs @@ -0,0 +1,87 @@ +//! Manages a pool of addresses that can be reused. + +use rand::Rng; + +use rustc_target::abi::{Align, Size}; + +const MAX_POOL_SIZE: usize = 64; + +// Just use fair coins, until we have evidence that other numbers are better. +const ADDR_REMEMBER_CHANCE: f64 = 0.5; +const ADDR_TAKE_CHANCE: f64 = 0.5; + +/// The pool strikes a balance between exploring more possible executions and making it more likely +/// to find bugs. The hypothesis is that bugs are more likely to occur when reuse happens for +/// allocations with the same layout, since that can trigger e.g. ABA issues in a concurrent data +/// structure. Therefore we only reuse allocations when size and alignment match exactly. +#[derive(Debug)] +pub struct ReusePool { + /// The i-th element in `pool` stores allocations of alignment `2^i`. We store these reusable + /// allocations as address-size pairs, the list must be sorted by the size. + /// + /// Each of these maps has at most MAX_POOL_SIZE elements, and since alignment is limited to + /// less than 64 different possible value, that bounds the overall size of the pool. + pool: Vec>, +} + +impl ReusePool { + pub fn new() -> Self { + ReusePool { pool: vec![] } + } + + fn subpool(&mut self, align: Align) -> &mut Vec<(u64, Size)> { + let pool_idx: usize = align.bytes().trailing_zeros().try_into().unwrap(); + if self.pool.len() <= pool_idx { + self.pool.resize(pool_idx + 1, Vec::new()); + } + &mut self.pool[pool_idx] + } + + pub fn add_addr(&mut self, rng: &mut impl Rng, addr: u64, size: Size, align: Align) { + // Let's see if we even want to remember this address. + if !rng.gen_bool(ADDR_REMEMBER_CHANCE) { + return; + } + // Determine the pool to add this to, and where in the pool to put it. + let subpool = self.subpool(align); + let pos = subpool.partition_point(|(_addr, other_size)| *other_size < size); + // Make sure the pool does not grow too big. + if subpool.len() >= MAX_POOL_SIZE { + // Pool full. Replace existing element, or last one if this would be even bigger. + let clamped_pos = pos.min(subpool.len() - 1); + subpool[clamped_pos] = (addr, size); + return; + } + // Add address to pool, at the right position. + subpool.insert(pos, (addr, size)); + } + + pub fn take_addr(&mut self, rng: &mut impl Rng, size: Size, align: Align) -> Option { + // Determine whether we'll even attempt a reuse. + if !rng.gen_bool(ADDR_TAKE_CHANCE) { + return None; + } + // Determine the pool to take this from. + let subpool = self.subpool(align); + // Let's see if we can find something of the right size. We want to find the full range of + // such items, beginning with the first, so we can't use `binary_search_by_key`. + let begin = subpool.partition_point(|(_addr, other_size)| *other_size < size); + let mut end = begin; + while let Some((_addr, other_size)) = subpool.get(end) { + if *other_size != size { + break; + } + end += 1; + } + if end == begin { + // Could not find any item of the right size. + return None; + } + // Pick a random element with the desired size. + let idx = rng.gen_range(begin..end); + // Remove it from the pool and return. + let (chosen_addr, chosen_size) = subpool.remove(idx); + debug_assert!(chosen_size >= size && chosen_addr % align.bytes() == 0); + Some(chosen_addr) + } +} diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 884b8a3b9bc6..0f7200fb4074 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -485,14 +485,14 @@ impl AllocState { &mut self, alloc_id: AllocId, prov_extra: ProvenanceExtra, - range: AllocRange, + size: Size, machine: &MiriMachine<'_, 'tcx>, ) -> InterpResult<'tcx> { match self { AllocState::StackedBorrows(sb) => - sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, range, machine), + sb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine), AllocState::TreeBorrows(tb) => - tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, range, machine), + tb.get_mut().before_memory_deallocation(alloc_id, prov_extra, size, machine), } } diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 6eed62d7edc6..9130601bbddb 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -574,13 +574,13 @@ impl Stacks { &mut self, alloc_id: AllocId, tag: ProvenanceExtra, - range: AllocRange, + size: Size, machine: &MiriMachine<'_, 'tcx>, ) -> InterpResult<'tcx> { - trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, range.size.bytes()); + trace!("deallocation with tag {:?}: {:?}, size {}", tag, alloc_id, size.bytes()); let dcx = DiagnosticCxBuilder::dealloc(machine, tag); let state = machine.borrow_tracker.as_ref().unwrap().borrow(); - self.for_each(range, dcx, |stack, dcx, exposed_tags| { + self.for_each(alloc_range(Size::ZERO, size), dcx, |stack, dcx, exposed_tags| { stack.dealloc(tag, &state, dcx, exposed_tags) })?; Ok(()) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index ae38ce6e7534..9eb78b08ef77 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -80,7 +80,7 @@ impl<'tcx> Tree { &mut self, alloc_id: AllocId, prov: ProvenanceExtra, - range: AllocRange, + size: Size, machine: &MiriMachine<'_, 'tcx>, ) -> InterpResult<'tcx> { // TODO: for now we bail out on wildcard pointers. Eventually we should @@ -91,7 +91,7 @@ impl<'tcx> Tree { }; let global = machine.borrow_tracker.as_ref().unwrap(); let span = machine.current_span(); - self.dealloc(tag, range, global, alloc_id, span) + self.dealloc(tag, alloc_range(Size::ZERO, size), global, alloc_id, span) } pub fn expose_tag(&mut self, _tag: BorTag) { diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index e30448840838..4a1c3ac868e1 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -1071,10 +1071,10 @@ impl VClockAlloc { pub fn deallocate<'tcx>( &mut self, alloc_id: AllocId, - range: AllocRange, + size: Size, machine: &mut MiriMachine<'_, '_>, ) -> InterpResult<'tcx> { - self.unique_access(alloc_id, range, NaWriteType::Deallocate, machine) + self.unique_access(alloc_id, alloc_range(Size::ZERO, size), NaWriteType::Deallocate, machine) } } diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 5e9de3ffb80e..76f4b77c8f8c 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -5,6 +5,8 @@ use std::num::NonZero; use std::sync::Mutex; use std::time::Duration; +use rand::RngCore; + use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_hir::def::{DefKind, Namespace}; @@ -20,8 +22,6 @@ use rustc_span::{def_id::CrateNum, sym, Span, Symbol}; use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants}; use rustc_target::spec::abi::Abi; -use rand::RngCore; - use crate::*; /// Indicates which kind of access is being performed. diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index c3bd6b912d5a..416d0cda8f1e 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -72,13 +72,13 @@ extern crate rustc_target; #[allow(unused_extern_crates)] extern crate rustc_driver; +mod alloc_addresses; mod borrow_tracker; mod clock; mod concurrency; mod diagnostics; mod eval; mod helpers; -mod intptrcast; mod machine; mod mono_hash_map; mod operator; @@ -101,6 +101,7 @@ pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _}; pub use crate::shims::time::EvalContextExt as _; pub use crate::shims::tls::TlsData; +pub use crate::alloc_addresses::{EvalContextExt as _, ProvenanceMode}; pub use crate::borrow_tracker::stacked_borrows::{ EvalContextExt as _, Item, Permission, Stack, Stacks, }; @@ -122,7 +123,6 @@ pub use crate::eval::{ create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith, }; pub use crate::helpers::{AccessKind, EvalContextExt as _}; -pub use crate::intptrcast::{EvalContextExt as _, ProvenanceMode}; pub use crate::machine::{ AllocExtra, FrameExtra, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, PrimitiveLayouts, Provenance, ProvenanceExtra, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index f0e3c43a5c5f..4dbb814fc27d 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -435,7 +435,7 @@ pub struct MiriMachine<'mir, 'tcx> { pub data_race: Option, /// Ptr-int-cast module global data. - pub intptrcast: intptrcast::GlobalState, + pub alloc_addresses: alloc_addresses::GlobalState, /// Environment variables set by `setenv`. /// Miri does not expose env vars from the host to the emulated program. @@ -630,7 +630,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { tcx, borrow_tracker, data_race, - intptrcast: RefCell::new(intptrcast::GlobalStateInner::new(config, stack_addr)), + alloc_addresses: RefCell::new(alloc_addresses::GlobalStateInner::new(config, stack_addr)), // `env_vars` depends on a full interpreter so we cannot properly initialize it yet. env_vars: EnvVars::default(), main_fn_ret_place: None, @@ -777,7 +777,7 @@ impl VisitProvenance for MiriMachine<'_, '_> { dir_handler, borrow_tracker, data_race, - intptrcast, + alloc_addresses, file_handler, tcx: _, isolated_op: _, @@ -821,7 +821,7 @@ impl VisitProvenance for MiriMachine<'_, '_> { file_handler.visit_provenance(visit); data_race.visit_provenance(visit); borrow_tracker.visit_provenance(visit); - intptrcast.visit_provenance(visit); + alloc_addresses.visit_provenance(visit); main_fn_ret_place.visit_provenance(visit); argc.visit_provenance(visit); argv.visit_provenance(visit); @@ -1282,22 +1282,28 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { machine: &mut Self, alloc_extra: &mut AllocExtra<'tcx>, (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra), - range: AllocRange, + size: Size, + align: Align, ) -> InterpResult<'tcx> { if machine.tracked_alloc_ids.contains(&alloc_id) { machine.emit_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id)); } if let Some(data_race) = &mut alloc_extra.data_race { - data_race.deallocate(alloc_id, range, machine)?; + data_race.deallocate(alloc_id, size, machine)?; } if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker { - borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, range, machine)?; + borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, size, machine)?; } if let Some((_, deallocated_at)) = machine.allocation_spans.borrow_mut().get_mut(&alloc_id) { *deallocated_at = Some(machine.current_span()); } - machine.intptrcast.get_mut().free_alloc_id(alloc_id); + machine.alloc_addresses.get_mut().free_alloc_id( + machine.rng.get_mut(), + alloc_id, + size, + align, + ); Ok(()) } diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs index 347951ce3727..f23d7dfd52d5 100644 --- a/src/tools/miri/src/provenance_gc.rs +++ b/src/tools/miri/src/provenance_gc.rs @@ -197,7 +197,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let allocs = LiveAllocs { ecx: this, collected: allocs }; this.machine.allocation_spans.borrow_mut().retain(|id, _| allocs.is_live(*id)); this.machine.symbolic_alignment.borrow_mut().retain(|id, _| allocs.is_live(*id)); - this.machine.intptrcast.borrow_mut().remove_unreachable_allocs(&allocs); + this.machine.alloc_addresses.borrow_mut().remove_unreachable_allocs(&allocs); if let Some(borrow_tracker) = &this.machine.borrow_tracker { borrow_tracker.borrow_mut().remove_unreachable_allocs(&allocs); } diff --git a/src/tools/miri/tests/pass/address-reuse.rs b/src/tools/miri/tests/pass/address-reuse.rs new file mode 100644 index 000000000000..9b5c8c38b8fb --- /dev/null +++ b/src/tools/miri/tests/pass/address-reuse.rs @@ -0,0 +1,16 @@ +//! Check that we do sometimes reuse addresses. +use std::collections::HashSet; + +fn main() { + let count = 100; + let mut addrs = HashSet::::new(); + for _ in 0..count { + // We make a `Box` with a layout that's hopefully not used by tons of things inside the + // allocator itself, so that we are more likely to get reuse. (With `i32` or `usize`, on + // Windows the reuse chances are very low.) + let b = Box::new([42usize; 4]); + addrs.insert(&*b as *const [usize; 4] as usize); + } + // dbg!(addrs.len()); + assert!(addrs.len() > 1 && addrs.len() < count); +} diff --git a/src/tools/miri/tests/pass/intptrcast.rs b/src/tools/miri/tests/pass/intptrcast.rs index 42b6f433420b..370b09f512cb 100644 --- a/src/tools/miri/tests/pass/intptrcast.rs +++ b/src/tools/miri/tests/pass/intptrcast.rs @@ -67,8 +67,8 @@ fn ptr_eq_dangling() { drop(b); let b = Box::new(0); let y = &*b as *const i32; // different allocation - // They *could* be equal if memory was reused, but probably are not. - assert!(x != y); + // They *could* be equal if memory is reused... + assert!(x != y || x == y); } fn ptr_eq_out_of_bounds() { diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 4d83547d664e..83f59837d442 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -26,7 +26,7 @@ pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { match stmt.kind { - ast::StmtKind::Local(ref local) => local.span, + ast::StmtKind::Let(ref local) => local.span, ast::StmtKind::Item(ref item) => item.span, ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, ast::StmtKind::MacCall(ref mac_stmt) => mac_stmt.mac.span(), diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 5960b1444994..4aaf7fdb27fb 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -61,7 +61,7 @@ implement_spanned!(ast::Local); impl Spanned for ast::Stmt { fn span(&self) -> Span { match self.kind { - ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), + ast::StmtKind::Let(ref local) => mk_sp(local.span().lo(), self.span.hi()), ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { mk_sp(expr.span().lo(), self.span.hi()) diff --git a/src/tools/rustfmt/src/stmt.rs b/src/tools/rustfmt/src/stmt.rs index e3fe4ebca11f..73a9cce416c1 100644 --- a/src/tools/rustfmt/src/stmt.rs +++ b/src/tools/rustfmt/src/stmt.rs @@ -115,7 +115,7 @@ fn format_stmt( skip_out_of_file_lines_range!(context, stmt.span()); let result = match stmt.kind { - ast::StmtKind::Local(ref local) => local.rewrite(context, shape), + ast::StmtKind::Let(ref local) => local.rewrite(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(context, stmt, is_last_expr) { ";" diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 47f772b485da..6209b37004bf 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -150,7 +150,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_item(item); self.last_pos = stmt.span().hi(); } - ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { + ast::StmtKind::Let(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let attrs = get_attrs_from_stmt(stmt.as_ast_node()); if contains_skip(attrs) { self.push_skipped_with_span( diff --git a/tests/assembly/simd-bitmask.rs b/tests/assembly/simd-bitmask.rs new file mode 100644 index 000000000000..8264a7068520 --- /dev/null +++ b/tests/assembly/simd-bitmask.rs @@ -0,0 +1,149 @@ +//@ revisions: x86 x86-avx2 x86-avx512 aarch64 +//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86] needs-llvm-components: x86 +//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx2] compile-flags: -C target-feature=+avx2 +//@ [x86-avx2] needs-llvm-components: x86 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [aarch64] needs-llvm-components: aarch64 +//@ [aarch64] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct m8x16([i8; 16]); + +#[repr(simd)] +pub struct m8x64([i8; 64]); + +#[repr(simd)] +pub struct m32x4([i32; 4]); + +#[repr(simd)] +pub struct m64x2([i64; 2]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +extern "rust-intrinsic" { + fn simd_bitmask(mask: V) -> B; +} + +// CHECK-LABEL: bitmask_m8x16 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m8x16(mask: m8x16) -> u16 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit + // of each byte into the right position. + // + // x86-NOT: psllw + // x86: movmskb eax, xmm0 + // + // x86-avx2-NOT: vpsllw + // x86-avx2: vpmovmskb eax, xmm0 + // + // x86-avx512-NOT: vpsllw xmm0 + // x86-avx512: vpmovmskb eax, xmm0 + // + // aarch64: adrp + // aarch64-NEXT: cmlt + // aarch64-NEXT: ldr + // aarch64-NEXT: and + // aarch64-NEXT: ext + // aarch64-NEXT: zip1 + // aarch64-NEXT: addv + // aarch64-NEXT: fmov + simd_bitmask(mask) +} + +// CHECK-LABEL: bitmask_m8x64 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m8x64(mask: m8x64) -> u64 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit + // of each byte into the right position. + // + // The parameter is a 512 bit vector which in the C abi is only valid for avx512 targets. + // + // x86-avx512-NOT: vpsllw + // x86-avx512: vpmovb2m k0, zmm0 + // x86-avx512: kmovq rax, k0 + simd_bitmask(mask) +} + +// CHECK-LABEL: bitmask_m32x4 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m32x4(mask: m32x4) -> u8 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // + // x86-NOT: psllq + // x86: movmskps eax, xmm0 + // + // x86-avx2-NOT: vpsllq + // x86-avx2: vmovmskps eax, xmm0 + // + // x86-avx512-NOT: vpsllq + // x86-avx512: vmovmskps eax, xmm0 + // + // aarch64: adrp + // aarch64-NEXT: cmlt + // aarch64-NEXT: ldr + // aarch64-NEXT: and + // aarch64-NEXT: addv + // aarch64-NEXT: fmov + // aarch64-NEXT: and + simd_bitmask(mask) +} + +// CHECK-LABEL: bitmask_m64x2 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m64x2(mask: m64x2) -> u8 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // + // x86-NOT: psllq + // x86: movmskpd eax, xmm0 + // + // x86-avx2-NOT: vpsllq + // x86-avx2: vmovmskpd eax, xmm0 + // + // x86-avx512-NOT: vpsllq + // x86-avx512: vmovmskpd eax, xmm0 + // + // aarch64: adrp + // aarch64-NEXT: cmlt + // aarch64-NEXT: ldr + // aarch64-NEXT: and + // aarch64-NEXT: addp + // aarch64-NEXT: fmov + // aarch64-NEXT: and + simd_bitmask(mask) +} + +// CHECK-LABEL: bitmask_m64x4 +#[no_mangle] +pub unsafe extern "C" fn bitmask_m64x4(mask: m64x4) -> u8 { + // The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary. + // + // The parameter is a 256 bit vector which in the C abi is only valid for avx/avx512 targets. + // + // x86-avx2-NOT: vpsllq + // x86-avx2: vmovmskpd eax, ymm0 + // + // x86-avx512-NOT: vpsllq + // x86-avx512: vmovmskpd eax, ymm0 + simd_bitmask(mask) +} diff --git a/tests/assembly/simd-intrinsic-gather.rs b/tests/assembly/simd-intrinsic-gather.rs new file mode 100644 index 000000000000..ef6b597c25f1 --- /dev/null +++ b/tests/assembly/simd-intrinsic-gather.rs @@ -0,0 +1,44 @@ +//@ revisions: x86-avx512 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ [x86-avx512] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +#[repr(simd)] +pub struct pf64x4([*const f64; 4]); + +extern "rust-intrinsic" { + fn simd_gather(values: V, mask: M, pointer: P) -> V; +} + +// CHECK-LABEL: gather_f64x4 +#[no_mangle] +pub unsafe extern "C" fn gather_f64x4(mask: m64x4, ptrs: pf64x4) -> f64x4 { + // FIXME: This should also get checked to generate a gather instruction for avx2. + // Currently llvm scalarizes this code, see https://github.com/llvm/llvm-project/issues/59789 + // + // x86-avx512: vpsllq ymm0, ymm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NEXT: vpxor xmm0, xmm0, xmm0 + // x86-avx512-NEXT: vgatherqpd ymm0 {k1}, ymmword ptr [1*ymm1] + simd_gather(f64x4([0_f64, 0_f64, 0_f64, 0_f64]), ptrs, mask) +} diff --git a/tests/assembly/simd-intrinsic-mask-load.rs b/tests/assembly/simd-intrinsic-mask-load.rs new file mode 100644 index 000000000000..49d231c45f85 --- /dev/null +++ b/tests/assembly/simd-intrinsic-mask-load.rs @@ -0,0 +1,88 @@ +//@ revisions: x86-avx2 x86-avx512 +//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx2] compile-flags: -C target-feature=+avx2 +//@ [x86-avx2] needs-llvm-components: x86 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct i8x16([i8; 16]); + +#[repr(simd)] +pub struct m8x16([i8; 16]); + +#[repr(simd)] +pub struct f32x8([f32; 8]); + +#[repr(simd)] +pub struct m32x8([i32; 8]); + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +extern "rust-intrinsic" { + fn simd_masked_load(mask: M, pointer: P, values: T) -> T; +} + +// CHECK-LABEL: load_i8x16 +#[no_mangle] +pub unsafe extern "C" fn load_i8x16(mask: m8x16, pointer: *const i8) -> i8x16 { + // Since avx2 supports no masked loads for bytes, the code tests each individual bit + // and jumps to code that inserts individual bytes. + // x86-avx2: vpsllw xmm0, xmm0, 7 + // x86-avx2-NEXT: vpmovmskb eax, xmm0 + // x86-avx2-NEXT: vpxor xmm0, xmm0 + // x86-avx2-NEXT: test al, 1 + // x86-avx2-NEXT: jne + // x86-avx2-NEXT: test al, 2 + // x86-avx2-NEXT: jne + // x86-avx2-DAG: movzx [[REG:[a-z]+]], byte ptr [rdi] + // x86-avx2-NEXT: vmovd xmm0, [[REG]] + // x86-avx2-DAG: vpinsrb xmm0, xmm0, byte ptr [rdi + 1], 1 + // + // x86-avx512: vpsllw xmm0, xmm0, 7 + // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NEXT: vmovdqu8 xmm0 {k1} {z}, xmmword ptr [rdi] + simd_masked_load(mask, pointer, i8x16([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) +} + +// CHECK-LABEL: load_f32x8 +#[no_mangle] +pub unsafe extern "C" fn load_f32x8(mask: m32x8, pointer: *const f32) -> f32x8 { + // x86-avx2: vpslld ymm0, ymm0, 31 + // x86-avx2-NEXT: vmaskmovps ymm0, ymm0, ymmword ptr [rdi] + // + // x86-avx512: vpslld ymm0, ymm0, 31 + // x86-avx512-NEXT: vpmovd2m k1, ymm0 + // x86-avx512-NEXT: vmovups ymm0 {k1} {z}, ymmword ptr [rdi] + simd_masked_load(mask, pointer, f32x8([0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32])) +} + +// CHECK-LABEL: load_f64x4 +#[no_mangle] +pub unsafe extern "C" fn load_f64x4(mask: m64x4, pointer: *const f64) -> f64x4 { + // x86-avx2: vpsllq ymm0, ymm0, 63 + // x86-avx2-NEXT: vmaskmovpd ymm0, ymm0, ymmword ptr [rdi] + // + // x86-avx512: vpsllq ymm0, ymm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NEXT: vmovupd ymm0 {k1} {z}, ymmword ptr [rdi] + simd_masked_load(mask, pointer, f64x4([0_f64, 0_f64, 0_f64, 0_f64])) +} diff --git a/tests/assembly/simd-intrinsic-mask-reduce.rs b/tests/assembly/simd-intrinsic-mask-reduce.rs new file mode 100644 index 000000000000..763401755fad --- /dev/null +++ b/tests/assembly/simd-intrinsic-mask-reduce.rs @@ -0,0 +1,60 @@ +// verify that simd mask reductions do not introduce additional bit shift operations +//@ revisions: x86 aarch64 +//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86] needs-llvm-components: x86 +//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [aarch64] needs-llvm-components: aarch64 +//@ [aarch64] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct mask8x16([i8; 16]); + +extern "rust-intrinsic" { + fn simd_reduce_all(x: T) -> bool; + fn simd_reduce_any(x: T) -> bool; +} + +// CHECK-LABEL: mask_reduce_all: +#[no_mangle] +pub unsafe extern "C" fn mask_reduce_all(m: mask8x16) -> bool { + // x86: psllw xmm0, 7 + // x86-NEXT: pmovmskb eax, xmm0 + // x86-NEXT: {{cmp ax, -1|xor eax, 65535}} + // x86-NEXT: sete al + // + // aarch64: shl v0.16b, v0.16b, #7 + // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 + // aarch64-NEXT: uminv b0, v0.16b + // aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0 + // aarch64-NEXT: and w0, [[REG]], #0x1 + simd_reduce_all(m) +} + +// CHECK-LABEL: mask_reduce_any: +#[no_mangle] +pub unsafe extern "C" fn mask_reduce_any(m: mask8x16) -> bool { + // x86: psllw xmm0, 7 + // x86-NEXT: pmovmskb + // x86-NEXT: test eax, eax + // x86-NEXT: setne al + // + // aarch64: shl v0.16b, v0.16b, #7 + // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 + // aarch64-NEXT: umaxv b0, v0.16b + // aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0 + // aarch64-NEXT: and w0, [[REG]], #0x1 + simd_reduce_any(m) +} diff --git a/tests/assembly/simd-intrinsic-mask-store.rs b/tests/assembly/simd-intrinsic-mask-store.rs new file mode 100644 index 000000000000..a6611e1c23d5 --- /dev/null +++ b/tests/assembly/simd-intrinsic-mask-store.rs @@ -0,0 +1,86 @@ +//@ revisions: x86-avx2 x86-avx512 +//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx2] compile-flags: -C target-feature=+avx2 +//@ [x86-avx2] needs-llvm-components: x86 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct i8x16([i8; 16]); + +#[repr(simd)] +pub struct m8x16([i8; 16]); + +#[repr(simd)] +pub struct f32x8([f32; 8]); + +#[repr(simd)] +pub struct m32x8([i32; 8]); + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +extern "rust-intrinsic" { + fn simd_masked_store(mask: M, pointer: P, values: T); +} + +// CHECK-LABEL: store_i8x16 +#[no_mangle] +pub unsafe extern "C" fn store_i8x16(mask: m8x16, pointer: *mut i8, value: i8x16) { + // Since avx2 supports no masked stores for bytes, the code tests each individual bit + // and jumps to code that extracts individual bytes to memory. + // x86-avx2: vpsllw xmm0, xmm0, 7 + // x86-avx2-NEXT: vpmovmskb eax, xmm0 + // x86-avx2-NEXT: test al, 1 + // x86-avx2-NEXT: jne + // x86-avx2-NEXT: test al, 2 + // x86-avx2-NEXT: jne + // x86-avx2-DAG: vpextrb byte ptr [rdi + 1], xmm1, 1 + // x86-avx2-DAG: vpextrb byte ptr [rdi], xmm1, 0 + // + // x86-avx512: vpsllw xmm0, xmm0, 7 + // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NEXT: vmovdqu8 xmmword ptr [rdi] {k1}, xmm1 + simd_masked_store(mask, pointer, value) +} + +// CHECK-LABEL: store_f32x8 +#[no_mangle] +pub unsafe extern "C" fn store_f32x8(mask: m32x8, pointer: *mut f32, value: f32x8) { + // x86-avx2: vpslld ymm0, ymm0, 31 + // x86-avx2-NEXT: vmaskmovps ymmword ptr [rdi], ymm0, ymm1 + // + // x86-avx512: vpslld ymm0, ymm0, 31 + // x86-avx512-NEXT: vpmovd2m k1, ymm0 + // x86-avx512-NEXT: vmovups ymmword ptr [rdi] {k1}, ymm1 + simd_masked_store(mask, pointer, value) +} + +// CHECK-LABEL: store_f64x4 +#[no_mangle] +pub unsafe extern "C" fn store_f64x4(mask: m64x4, pointer: *mut f64, value: f64x4) { + // x86-avx2: vpsllq ymm0, ymm0, 63 + // x86-avx2-NEXT: vmaskmovpd ymmword ptr [rdi], ymm0, ymm1 + // + // x86-avx512: vpsllq ymm0, ymm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NEXT: vmovupd ymmword ptr [rdi] {k1}, ymm1 + simd_masked_store(mask, pointer, value) +} diff --git a/tests/assembly/simd-intrinsic-scatter.rs b/tests/assembly/simd-intrinsic-scatter.rs new file mode 100644 index 000000000000..6ffefb0801ae --- /dev/null +++ b/tests/assembly/simd-intrinsic-scatter.rs @@ -0,0 +1,40 @@ +//@ revisions: x86-avx512 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ [x86-avx512] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +#[repr(simd)] +pub struct pf64x4([*mut f64; 4]); + +extern "rust-intrinsic" { + fn simd_scatter(values: V, pointer: P, mask: M); +} + +// CHECK-LABEL: scatter_f64x4 +#[no_mangle] +pub unsafe extern "C" fn scatter_f64x4(values: f64x4, ptrs: pf64x4, mask: m64x4) { + // x86-avx512: vpsllq ymm2, ymm2, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm2 + // x86-avx512-NEXT: vscatterqpd ymmword ptr [1*ymm1] {k1}, ymm0 + simd_scatter(values, ptrs, mask) +} diff --git a/tests/assembly/simd-intrinsic-select.rs b/tests/assembly/simd-intrinsic-select.rs new file mode 100644 index 000000000000..3f36402e3d0d --- /dev/null +++ b/tests/assembly/simd-intrinsic-select.rs @@ -0,0 +1,130 @@ +//@ revisions: x86-avx2 x86-avx512 aarch64 +//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx2] compile-flags: -C target-feature=+avx2 +//@ [x86-avx2] needs-llvm-components: x86 +//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx512] needs-llvm-components: x86 +//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [aarch64] needs-llvm-components: aarch64 +//@ [aarch64] min-llvm-version: 18.0 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type=lib -O + +#![feature(no_core, lang_items, repr_simd, intrinsics)] +#![no_core] +#![allow(non_camel_case_types)] + +// Because we don't have core yet. +#[lang = "sized"] +pub trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct i8x16([i8; 16]); + +#[repr(simd)] +pub struct m8x16([i8; 16]); + +#[repr(simd)] +pub struct f32x4([f32; 4]); + +#[repr(simd)] +pub struct m32x4([i32; 4]); + +#[repr(simd)] +pub struct f64x2([f64; 2]); + +#[repr(simd)] +pub struct m64x2([i64; 2]); + +#[repr(simd)] +pub struct f64x4([f64; 4]); + +#[repr(simd)] +pub struct m64x4([i64; 4]); + +#[repr(simd)] +pub struct f64x8([f64; 8]); + +#[repr(simd)] +pub struct m64x8([i64; 8]); + +extern "rust-intrinsic" { + fn simd_select(mask: M, a: V, b: V) -> V; +} + +// CHECK-LABEL: select_i8x16 +#[no_mangle] +pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16 { + // x86-avx2: vpsllw xmm0, xmm0, 7 + // x86-avx2-NEXT: vpblendvb xmm0, xmm2, xmm1, xmm0 + // + // x86-avx512: vpsllw xmm0, xmm0, 7 + // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1 + // + // aarch64: shl v0.16b, v0.16b, #7 + // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 + // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b + simd_select(mask, a, b) +} + +// CHECK-LABEL: select_f32x4 +#[no_mangle] +pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4 { + // x86-avx2: vpslld xmm0, xmm0, 31 + // x86-avx2-NEXT: vblendvps xmm0, xmm2, xmm1, xmm0 + // + // x86-avx512: vpslld xmm0, xmm0, 31 + // x86-avx512-NEXT: vpmovd2m k1, xmm0 + // x86-avx512-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1 + // + // aarch64: shl v0.4s, v0.4s, #31 + // aarch64-NEXT: cmlt v0.4s, v0.4s, #0 + // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b + simd_select(mask, a, b) +} + +// CHECK-LABEL: select_f64x2 +#[no_mangle] +pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 { + // x86-avx2: vpsllq xmm0, xmm0, 63 + // x86-avx2-NEXT: vblendvpd xmm0, xmm2, xmm1, xmm0 + // + // x86-avx512: vpsllq xmm0, xmm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, xmm0 + // x86-avx512-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1 + // + // aarch64: shl v0.2d, v0.2d, #63 + // aarch64-NEXT: cmlt v0.2d, v0.2d, #0 + // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b + simd_select(mask, a, b) +} + +// CHECK-LABEL: select_f64x4 +#[no_mangle] +pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 { + // The parameter is a 256 bit vector which in the C abi is only valid for avx targets. + // + // x86-avx2: vpsllq ymm0, ymm0, 63 + // x86-avx2-NEXT: vblendvpd ymm0, ymm2, ymm1, ymm0 + // + // x86-avx512: vpsllq ymm0, ymm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1 + simd_select(mask, a, b) +} + +// CHECK-LABEL: select_f64x8 +#[no_mangle] +pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 { + // The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets. + // + // x86-avx512: vpsllq zmm0, zmm0, 63 + // x86-avx512-NEXT: vpmovq2m k1, zmm0 + // x86-avx512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1 + simd_select(mask, a, b) +} diff --git a/tests/assembly/stack-protector/stack-protector-target-support.rs b/tests/assembly/stack-protector/stack-protector-target-support.rs index df8a0dce40b2..74a609dcdcc1 100644 --- a/tests/assembly/stack-protector/stack-protector-target-support.rs +++ b/tests/assembly/stack-protector/stack-protector-target-support.rs @@ -151,7 +151,7 @@ //@ [r72] needs-llvm-components: webassembly //@ [r73] compile-flags:--target wasm32-wasip1 //@ [r73] needs-llvm-components: webassembly -//@ [r74] compile-flags:--target wasm32-wasi-preview1-threads +//@ [r74] compile-flags:--target wasm32-wasip1-threads //@ [r74] needs-llvm-components: webassembly //@ [r75] compile-flags:--target x86_64-apple-ios //@ [r75] needs-llvm-components: x86 @@ -179,7 +179,6 @@ //@ compile-flags: -C opt-level=2 #![crate_type = "lib"] - #![feature(no_core, lang_items)] #![crate_type = "lib"] #![no_core] diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index b0f8ebd5920b..bda77b5f09b8 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -492,9 +492,9 @@ //@ revisions: wasm32_wasip1 //@ [wasm32_wasip1] compile-flags: --target wasm32-wasip1 //@ [wasm32_wasip1] needs-llvm-components: webassembly -//@ revisions: wasm32_wasi_preview1_threads -//@ [wasm32_wasi_preview1_threads] compile-flags: --target wasm32-wasi-preview1-threads -//@ [wasm32_wasi_preview1_threads] needs-llvm-components: webassembly +//@ revisions: wasm32_wasip1_threads +//@ [wasm32_wasip1_threads] compile-flags: --target wasm32-wasip1-threads +//@ [wasm32_wasip1_threads] needs-llvm-components: webassembly //@ revisions: wasm32_wasip2 //@ [wasm32_wasip2] compile-flags: --target wasm32-wasip2 //@ [wasm32_wasip2] needs-llvm-components: webassembly diff --git a/tests/codegen/common_prim_int_ptr.rs b/tests/codegen/common_prim_int_ptr.rs new file mode 100644 index 000000000000..87fa89abb866 --- /dev/null +++ b/tests/codegen/common_prim_int_ptr.rs @@ -0,0 +1,51 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +// Tests that codegen works properly when enums like `Result>` +// are represented as `{ u64, ptr }`, i.e., for `Ok(123)`, `123` is stored +// as a pointer. + +// CHECK-LABEL: @insert_int +#[no_mangle] +pub fn insert_int(x: usize) -> Result> { + // CHECK: start: + // CHECK-NEXT: inttoptr i{{[0-9]+}} %x to ptr + // CHECK-NEXT: insertvalue + // CHECK-NEXT: ret { i{{[0-9]+}}, ptr } + Ok(x) +} + +// CHECK-LABEL: @insert_box +#[no_mangle] +pub fn insert_box(x: Box<()>) -> Result> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: ret + Err(x) +} + +// CHECK-LABEL: @extract_int +// CHECK-NOT: nonnull +// CHECK-SAME: (i{{[0-9]+}} {{[^,]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]]) +#[no_mangle] +pub unsafe fn extract_int(x: Result>) -> usize { + // CHECK: [[TEMP:%.+]] = ptrtoint ptr [[PAYLOAD]] to [[USIZE:i[0-9]+]] + // CHECK: ret [[USIZE]] [[TEMP]] + match x { + Ok(v) => v, + Err(_) => std::intrinsics::unreachable(), + } +} + +// CHECK-LABEL: @extract_box +// CHECK-SAME: (i{{[0-9]+}} {{[^,]+}} [[DISCRIMINANT:%[0-9]+]], ptr {{[^,]+}} [[PAYLOAD:%[0-9]+]]) +#[no_mangle] +pub unsafe fn extract_box(x: Result>) -> Box { + // CHECK: ret ptr [[PAYLOAD]] + match x { + Ok(_) => std::intrinsics::unreachable(), + Err(e) => e, + } +} diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index 5a503e86010b..f858562b5f11 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -296,7 +296,7 @@ pub unsafe fn check_pair_with_bool(x: (u8, bool)) -> (bool, i8) { pub unsafe fn check_float_to_pointer(x: f64) -> *const () { // CHECK-NOT: alloca // CHECK: %0 = bitcast double %x to i64 - // CHECK: %_0 = inttoptr i64 %0 to ptr + // CHECK: %_0 = getelementptr i8, ptr null, i64 %0 // CHECK: ret ptr %_0 transmute(x) } @@ -371,7 +371,7 @@ pub unsafe fn check_issue_110005(x: (usize, bool)) -> Option> { // CHECK-LABEL: @check_pair_to_dst_ref( #[no_mangle] pub unsafe fn check_pair_to_dst_ref<'a>(x: (usize, usize)) -> &'a [u8] { - // CHECK: %_0.0 = inttoptr i64 %x.0 to ptr + // CHECK: %_0.0 = getelementptr i8, ptr null, i64 %x.0 // CHECK: %0 = insertvalue { ptr, i64 } poison, ptr %_0.0, 0 // CHECK: %1 = insertvalue { ptr, i64 } %0, i64 %x.1, 1 // CHECK: ret { ptr, i64 } %1 diff --git a/tests/codegen/precondition-checks.rs b/tests/codegen/precondition-checks.rs new file mode 100644 index 000000000000..191494450037 --- /dev/null +++ b/tests/codegen/precondition-checks.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 -Cdebug-assertions=no + +// This test ensures that in a debug build which turns off debug assertions, we do not monomorphize +// any of the standard library's unsafe precondition checks. +// The naive codegen of those checks contains the actual check underneath an `if false`, which +// could be optimized out if optimizations are enabled. But if we rely on optimizations to remove +// panic branches, then we can't link compiler_builtins without optimizing it, which means that +// -Zbuild-std doesn't work with -Copt-level=0. +// +// In other words, this tests for a mandatory optimization. + +#![crate_type = "lib"] + +use std::ptr::NonNull; + +// CHECK-LABEL: ; core::ptr::non_null::NonNull::new_unchecked +// CHECK-NOT: call +// CHECK: } + +// CHECK-LABEL: @nonnull_new +#[no_mangle] +pub unsafe fn nonnull_new(ptr: *mut u8) -> NonNull { + // CHECK: ; call core::ptr::non_null::NonNull::new_unchecked + unsafe { + NonNull::new_unchecked(ptr) + } +} diff --git a/tests/codegen/skip-mono-inside-if-false.rs b/tests/codegen/skip-mono-inside-if-false.rs new file mode 100644 index 000000000000..8b95de99dd3b --- /dev/null +++ b/tests/codegen/skip-mono-inside-if-false.rs @@ -0,0 +1,41 @@ +//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 + +#![crate_type = "lib"] + +#[no_mangle] +pub fn demo_for_i32() { + generic_impl::(); +} + +// Two important things here: +// - We replace the "then" block with `unreachable` to avoid linking problems +// - We neither declare nor define the `big_impl` that said block "calls". + +// CHECK-LABEL: ; skip_mono_inside_if_false::generic_impl +// CHECK: start: +// CHECK-NEXT: br label %[[ELSE_BRANCH:bb[0-9]+]] +// CHECK: [[ELSE_BRANCH]]: +// CHECK-NEXT: call skip_mono_inside_if_false::small_impl +// CHECK: bb{{[0-9]+}}: +// CHECK-NEXT: ret void +// CHECK: bb{{[0-9+]}}: +// CHECK-NEXT: unreachable + +fn generic_impl() { + trait MagicTrait { + const IS_BIG: bool; + } + impl MagicTrait for T { + const IS_BIG: bool = std::mem::size_of::() > 10; + } + if T::IS_BIG { + big_impl::(); + } else { + small_impl::(); + } +} + +#[inline(never)] +fn small_impl() {} +#[inline(never)] +fn big_impl() {} diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index 7a5eb4dfcd5c..caaa70962d5b 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -49,7 +49,7 @@ pub fn ptr_to_int(p: *mut u16) -> usize { } // CHECK: define{{.*}}ptr @int_to_ptr([[USIZE]] %i) -// CHECK: %_0 = inttoptr [[USIZE]] %i to ptr +// CHECK: %_0 = getelementptr i8, ptr null, [[USIZE]] %i // CHECK-NEXT: ret ptr %_0 #[no_mangle] pub fn int_to_ptr(i: usize) -> *mut u16 { diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 58cd6ff233a1..f6cdf9552097 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -4,17 +4,41 @@ #![crate_type = "lib"] #![feature(try_blocks)] -// These are now NOPs in LLVM 15, presumably thanks to nikic's change mentioned in -// . -// Unfortunately, as of 2022-08-17 they're not yet nops for `u64`s nor `Option`. - use std::ops::ControlFlow::{self, Continue, Break}; +use std::ptr::NonNull; + +// CHECK-LABEL: @option_nop_match_32 +#[no_mangle] +pub fn option_nop_match_32(x: Option) -> Option { + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } + match x { + Some(x) => Some(x), + None => None, + } +} + +// CHECK-LABEL: @option_nop_traits_32 +#[no_mangle] +pub fn option_nop_traits_32(x: Option) -> Option { + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } + try { + x? + } +} // CHECK-LABEL: @result_nop_match_32 #[no_mangle] pub fn result_nop_match_32(x: Result) -> Result { - // CHECK: start - // CHECK-NEXT: ret i64 %0 + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } match x { Ok(x) => Ok(x), Err(x) => Err(x), @@ -24,8 +48,60 @@ pub fn result_nop_match_32(x: Result) -> Result { // CHECK-LABEL: @result_nop_traits_32 #[no_mangle] pub fn result_nop_traits_32(x: Result) -> Result { - // CHECK: start - // CHECK-NEXT: ret i64 %0 + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } + try { + x? + } +} + +// CHECK-LABEL: @result_nop_match_64 +#[no_mangle] +pub fn result_nop_match_64(x: Result) -> Result { + // CHECK: start: + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: ret { i64, i64 } + match x { + Ok(x) => Ok(x), + Err(x) => Err(x), + } +} + +// CHECK-LABEL: @result_nop_traits_64 +#[no_mangle] +pub fn result_nop_traits_64(x: Result) -> Result { + // CHECK: start: + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: ret { i64, i64 } + try { + x? + } +} + +// CHECK-LABEL: @result_nop_match_ptr +#[no_mangle] +pub fn result_nop_match_ptr(x: Result>) -> Result> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: ret + match x { + Ok(x) => Ok(x), + Err(x) => Err(x), + } +} + +// CHECK-LABEL: @result_nop_traits_ptr +#[no_mangle] +pub fn result_nop_traits_ptr(x: Result>) -> Result> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: ret try { x? } @@ -34,8 +110,10 @@ pub fn result_nop_traits_32(x: Result) -> Result { // CHECK-LABEL: @control_flow_nop_match_32 #[no_mangle] pub fn control_flow_nop_match_32(x: ControlFlow) -> ControlFlow { - // CHECK: start - // CHECK-NEXT: ret i64 %0 + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } match x { Continue(x) => Continue(x), Break(x) => Break(x), @@ -45,8 +123,10 @@ pub fn control_flow_nop_match_32(x: ControlFlow) -> ControlFlow) -> ControlFlow { - // CHECK: start - // CHECK-NEXT: ret i64 %0 + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } try { x? } diff --git a/tests/coverage/auxiliary/used_crate.rs b/tests/coverage/auxiliary/used_crate.rs index 22837ef6d3cb..72d479c74a68 100644 --- a/tests/coverage/auxiliary/used_crate.rs +++ b/tests/coverage/auxiliary/used_crate.rs @@ -76,13 +76,8 @@ fn use_this_lib_crate() { // ``` // // The notice is triggered because the function is unused by the library itself, -// and when the library is compiled, a synthetic function is generated, so -// unused function coverage can be reported. Coverage can be skipped for unused -// generic functions with: -// -// ```shell -// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...` -// ``` +// so when the library is compiled, an "unused" set of mappings for that function +// is included in the library's coverage metadata. // // Even though this function is used by `uses_crate.rs` (and // counted), with substitutions for `T`, those instantiations are only generated @@ -98,6 +93,6 @@ fn use_this_lib_crate() { // another binary that never used this generic function, then it would be valid // to show the unused generic, with unknown substitution (`_`). // -// The alternative is to exclude all generics from being included in the "unused -// functions" list, which would then omit coverage results for -// `unused_generic_function()`, below. +// The alternative would be to exclude all generics from being included in the +// "unused functions" list, which would then omit coverage results for +// `unused_generic_function()`. diff --git a/tests/coverage/uses_crate.coverage b/tests/coverage/uses_crate.coverage index 3ab47dbca79c..a6a570a08502 100644 --- a/tests/coverage/uses_crate.coverage +++ b/tests/coverage/uses_crate.coverage @@ -124,13 +124,8 @@ $DIR/auxiliary/used_crate.rs: LL| |// ``` LL| |// LL| |// The notice is triggered because the function is unused by the library itself, - LL| |// and when the library is compiled, a synthetic function is generated, so - LL| |// unused function coverage can be reported. Coverage can be skipped for unused - LL| |// generic functions with: - LL| |// - LL| |// ```shell - LL| |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...` - LL| |// ``` + LL| |// so when the library is compiled, an "unused" set of mappings for that function + LL| |// is included in the library's coverage metadata. LL| |// LL| |// Even though this function is used by `uses_crate.rs` (and LL| |// counted), with substitutions for `T`, those instantiations are only generated @@ -146,9 +141,9 @@ $DIR/auxiliary/used_crate.rs: LL| |// another binary that never used this generic function, then it would be valid LL| |// to show the unused generic, with unknown substitution (`_`). LL| |// - LL| |// The alternative is to exclude all generics from being included in the "unused - LL| |// functions" list, which would then omit coverage results for - LL| |// `unused_generic_function()`, below. + LL| |// The alternative would be to exclude all generics from being included in the + LL| |// "unused functions" list, which would then omit coverage results for + LL| |// `unused_generic_function()`. $DIR/uses_crate.rs: LL| |// This test was failing on Linux for a while due to #110393 somehow making diff --git a/tests/debuginfo/mutex.rs b/tests/debuginfo/mutex.rs index affc1558ffa9..4f458c0d7e0d 100644 --- a/tests/debuginfo/mutex.rs +++ b/tests/debuginfo/mutex.rs @@ -10,7 +10,7 @@ // // cdb-command:dx m,d // cdb-check:m,d [Type: std::sync::mutex::Mutex] -// cdb-check: [...] inner [Type: std::sys::locks::mutex::futex::Mutex] +// cdb-check: [...] inner [Type: std::sys::sync::mutex::futex::Mutex] // cdb-check: [...] poison [Type: std::sync::poison::Flag] // cdb-check: [...] data : 0 [Type: core::cell::UnsafeCell] diff --git a/tests/debuginfo/rwlock-read.rs b/tests/debuginfo/rwlock-read.rs index 76dbc73a1e94..3fd6ac337265 100644 --- a/tests/debuginfo/rwlock-read.rs +++ b/tests/debuginfo/rwlock-read.rs @@ -16,7 +16,7 @@ // cdb-command:dx r // cdb-check:r [Type: std::sync::rwlock::RwLockReadGuard] // cdb-check: [...] data : NonNull([...]: 0) [Type: core::ptr::non_null::NonNull] -// cdb-check: [...] inner_lock : [...] [Type: std::sys::locks::rwlock::futex::RwLock *] +// cdb-check: [...] inner_lock : [...] [Type: std::sys::sync::rwlock::futex::RwLock *] #[allow(unused_variables)] diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir index 4e91eb6f76fc..194afdf7dd8a 100644 --- a/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.full_tested_match.built.after.mir @@ -28,7 +28,7 @@ fn full_tested_match() -> () { _2 = Option::::Some(const 42_i32); PlaceMention(_2); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1]; + switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1]; } bb1: { @@ -37,20 +37,20 @@ fn full_tested_match() -> () { } bb2: { - _1 = (const 3_i32, const 3_i32); - goto -> bb13; + falseEdge -> [real: bb7, imaginary: bb3]; } bb3: { - goto -> bb1; + falseEdge -> [real: bb12, imaginary: bb5]; } bb4: { - falseEdge -> [real: bb7, imaginary: bb5]; + goto -> bb1; } bb5: { - falseEdge -> [real: bb12, imaginary: bb2]; + _1 = (const 3_i32, const 3_i32); + goto -> bb13; } bb6: { @@ -91,7 +91,7 @@ fn full_tested_match() -> () { bb11: { StorageDead(_7); StorageDead(_6); - goto -> bb5; + goto -> bb3; } bb12: { diff --git a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir index 0c67cc9f71e5..ae83075434f7 100644 --- a/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir +++ b/tests/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir @@ -28,7 +28,7 @@ fn full_tested_match2() -> () { _2 = Option::::Some(const 42_i32); PlaceMention(_2); _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb4, otherwise: bb1]; + switchInt(move _3) -> [0: bb5, 1: bb2, otherwise: bb1]; } bb1: { @@ -37,18 +37,10 @@ fn full_tested_match2() -> () { } bb2: { - falseEdge -> [real: bb12, imaginary: bb5]; + falseEdge -> [real: bb7, imaginary: bb5]; } bb3: { - goto -> bb1; - } - - bb4: { - falseEdge -> [real: bb7, imaginary: bb2]; - } - - bb5: { StorageLive(_9); _9 = ((_2 as Some).0: i32); StorageLive(_10); @@ -59,6 +51,14 @@ fn full_tested_match2() -> () { goto -> bb13; } + bb4: { + goto -> bb1; + } + + bb5: { + falseEdge -> [real: bb12, imaginary: bb3]; + } + bb6: { goto -> bb1; } @@ -97,7 +97,7 @@ fn full_tested_match2() -> () { bb11: { StorageDead(_7); StorageDead(_6); - falseEdge -> [real: bb5, imaginary: bb2]; + falseEdge -> [real: bb3, imaginary: bb5]; } bb12: { diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index 95bcfe71792b..1348bdd739ad 100644 --- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -30,7 +30,7 @@ StorageDead(_5); StorageDead(_4); _8 = discriminant((_3.0: std::option::Option)); -- switchInt(move _8) -> [0: bb2, 1: bb3, otherwise: bb1]; +- switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1]; + StorageLive(_11); + _11 = discriminant((_3.1: std::option::Option)); + StorageLive(_12); @@ -48,12 +48,12 @@ bb2: { - _6 = discriminant((_3.1: std::option::Option)); -- switchInt(move _6) -> [0: bb5, otherwise: bb1]; +- switchInt(move _6) -> [1: bb4, otherwise: bb1]; - } - - bb3: { - _7 = discriminant((_3.1: std::option::Option)); -- switchInt(move _7) -> [1: bb4, otherwise: bb1]; +- switchInt(move _7) -> [0: bb5, otherwise: bb1]; - } - - bb4: { diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff index 7fdd8554e388..350e5fe6db57 100644 --- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff @@ -36,7 +36,7 @@ StorageDead(_5); StorageDead(_4); _8 = discriminant((_3.0: std::option::Option)); - switchInt(move _8) -> [0: bb2, 1: bb4, otherwise: bb1]; + switchInt(move _8) -> [0: bb3, 1: bb2, otherwise: bb1]; } bb1: { @@ -45,17 +45,17 @@ bb2: { _6 = discriminant((_3.1: std::option::Option)); - switchInt(move _6) -> [0: bb3, 1: bb7, otherwise: bb1]; + switchInt(move _6) -> [0: bb6, 1: bb5, otherwise: bb1]; } bb3: { - _0 = const 3_u32; - goto -> bb8; + _7 = discriminant((_3.1: std::option::Option)); + switchInt(move _7) -> [0: bb4, 1: bb7, otherwise: bb1]; } bb4: { - _7 = discriminant((_3.1: std::option::Option)); - switchInt(move _7) -> [0: bb6, 1: bb5, otherwise: bb1]; + _0 = const 3_u32; + goto -> bb8; } bb5: { diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 619fda339a6a..307f7105dd2f 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-abort.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -42,11 +42,15 @@ } bb2: { -- switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4]; +- switchInt((_2.0: bool)) -> [0: bb4, otherwise: bb3]; + switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; } bb3: { +- falseEdge -> [real: bb20, imaginary: bb4]; +- } +- +- bb4: { StorageLive(_15); _15 = (_2.1: bool); StorageLive(_16); @@ -55,12 +59,8 @@ + goto -> bb16; } - bb4: { -- falseEdge -> [real: bb20, imaginary: bb3]; -- } -- - bb5: { -- falseEdge -> [real: bb13, imaginary: bb4]; +- falseEdge -> [real: bb13, imaginary: bb3]; - } - - bb6: { @@ -68,6 +68,7 @@ - } - - bb7: { ++ bb4: { _0 = const 1_i32; - drop(_7) -> [return: bb18, unwind: bb25]; + drop(_7) -> [return: bb15, unwind: bb22]; @@ -183,7 +184,7 @@ StorageDead(_12); StorageDead(_8); StorageDead(_6); -- falseEdge -> [real: bb2, imaginary: bb4]; +- falseEdge -> [real: bb2, imaginary: bb3]; + goto -> bb2; } diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff index 619fda339a6a..307f7105dd2f 100644 --- a/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff +++ b/tests/mir-opt/match_arm_scopes.complicated_match.panic-unwind.SimplifyCfg-initial.after-ElaborateDrops.after.diff @@ -42,11 +42,15 @@ } bb2: { -- switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb4]; +- switchInt((_2.0: bool)) -> [0: bb4, otherwise: bb3]; + switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; } bb3: { +- falseEdge -> [real: bb20, imaginary: bb4]; +- } +- +- bb4: { StorageLive(_15); _15 = (_2.1: bool); StorageLive(_16); @@ -55,12 +59,8 @@ + goto -> bb16; } - bb4: { -- falseEdge -> [real: bb20, imaginary: bb3]; -- } -- - bb5: { -- falseEdge -> [real: bb13, imaginary: bb4]; +- falseEdge -> [real: bb13, imaginary: bb3]; - } - - bb6: { @@ -68,6 +68,7 @@ - } - - bb7: { ++ bb4: { _0 = const 1_i32; - drop(_7) -> [return: bb18, unwind: bb25]; + drop(_7) -> [return: bb15, unwind: bb22]; @@ -183,7 +184,7 @@ StorageDead(_12); StorageDead(_8); StorageDead(_6); -- falseEdge -> [real: bb2, imaginary: bb4]; +- falseEdge -> [real: bb2, imaginary: bb3]; + goto -> bb2; } diff --git a/tests/mir-opt/unnamed-fields/field_access.rs b/tests/mir-opt/unnamed-fields/field_access.rs index 3d33ca26875b..5badfa1646bc 100644 --- a/tests/mir-opt/unnamed-fields/field_access.rs +++ b/tests/mir-opt/unnamed-fields/field_access.rs @@ -1,4 +1,5 @@ -// skip-filecheck +// Tests the correct handling of unnamed fields within structs and unions marked with #[repr(C)]. + // EMIT_MIR field_access.foo.SimplifyCfg-initial.after.mir // EMIT_MIR field_access.bar.SimplifyCfg-initial.after.mir @@ -36,18 +37,36 @@ union Bar { fn access(_: T) {} +// CHECK-LABEL: fn foo( fn foo(foo: Foo) { + // CHECK [[a:_.*]] = (_1.0: u8); + // CHECK _.* = access::(move [[a]]) -> [return: bb1, unwind: bb5]; access(foo.a); + // CHECK [[b:_.*]] = ((_1.1: Foo::{anon_adt#0}).0: i8); + // CHECK _.* = access::(move [[b]]) -> [return: bb2, unwind: bb5]; access(foo.b); + // CHECK [[c:_.*]] = ((_1.1: Foo::{anon_adt#0}).1: bool); + // CHECK _.* = access::(move [[c]]) -> [return: bb3, unwind: bb5]; access(foo.c); + // CHECK [[d:_.*]] = (((_1.2: Foo::{anon_adt#1}).0: Foo::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); + // CHECK _.* = access::<[u8; 1]>(move [[d]]) -> [return: bb4, unwind: bb5]; access(foo.d); } +// CHECK-LABEL: fn bar( fn bar(bar: Bar) { unsafe { + // CHECK [[a:_.*]] = (_1.0: u8); + // CHECK _.* = access::(move [[a]]) -> [return: bb1, unwind: bb5]; access(bar.a); + // CHECK [[b:_.*]] = ((_1.1: Bar::{anon_adt#0}).0: i8); + // CHECK _.* = access::(move [[b]]) -> [return: bb2, unwind: bb5]; access(bar.b); + // CHECK [[c:_.*]] = ((_1.1: Bar::{anon_adt#0}).1: bool); + // CHECK _.* = access::(move [[c]]) -> [return: bb3, unwind: bb5]; access(bar.c); + // CHECK [[d:_.*]] = (((_1.2: Bar::{anon_adt#1}).0: Bar::{anon_adt#1}::{anon_adt#0}).0: [u8; 1]); + // CHECK _.* = access::<[u8; 1]>(move [[d]]) -> [return: bb4, unwind: bb5]; access(bar.d); } } diff --git a/tests/rustdoc/line-breaks.rs b/tests/rustdoc/line-breaks.rs index 29c16fcd4f8a..21aa3a03ce43 100644 --- a/tests/rustdoc/line-breaks.rs +++ b/tests/rustdoc/line-breaks.rs @@ -1,26 +1,37 @@ #![crate_name = "foo"] -use std::ops::Add; use std::fmt::Display; +use std::ops::Add; -//@count foo/fn.function_with_a_really_long_name.html //pre/br 2 -pub fn function_with_a_really_long_name(parameter_one: i32, - parameter_two: i32) - -> Option { +// @matches foo/fn.function_with_a_really_long_name.html '//*[@class="rust item-decl"]//code' "\ +// function_with_a_really_long_name\(\n\ +// \ parameter_one: i32,\n\ +// \ parameter_two: i32\n\ +// \) -> Option$" +pub fn function_with_a_really_long_name(parameter_one: i32, parameter_two: i32) -> Option { Some(parameter_one + parameter_two) } -//@count foo/fn.short_name.html //pre/br 0 -pub fn short_name(param: i32) -> i32 { param + 1 } +// @matches foo/fn.short_name.html '//*[@class="rust item-decl"]//code' \ +// "short_name\(param: i32\) -> i32$" +pub fn short_name(param: i32) -> i32 { + param + 1 +} -//@count foo/fn.where_clause.html //pre/br 4 -pub fn where_clause(param_one: T, - param_two: U) - where T: Add + Display + Copy, - U: Add + Display + Copy, - T::Output: Display + Add + Copy, - >::Output: Display, - U::Output: Display + Copy +// @matches foo/fn.where_clause.html '//*[@class="rust item-decl"]//code' "\ +// where_clause\(param_one: T, param_two: U\)where\n\ +// \ T: Add \+ Display \+ Copy,\n\ +// \ U: Add \+ Display \+ Copy,\n\ +// \ T::Output: Display \+ Add \+ Copy,\n\ +// \ >::Output: Display,\n\ +// \ U::Output: Display \+ Copy,$" +pub fn where_clause(param_one: T, param_two: U) +where + T: Add + Display + Copy, + U: Add + Display + Copy, + T::Output: Display + Add + Copy, + >::Output: Display, + U::Output: Display + Copy, { let x = param_one + param_two; println!("{} + {} = {}", param_one, param_two, x); diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index 27b9b059c209..5bb1053f1879 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -19,6 +19,7 @@ extern crate stable_mir; use std::assert_matches::assert_matches; use mir::{mono::Instance, TerminatorKind::*}; +use stable_mir::mir::mono::InstanceKind; use rustc_smir::rustc_internal; use stable_mir::ty::{RigidTy, TyKind, Ty, UintTy}; use stable_mir::*; @@ -35,9 +36,10 @@ fn test_stable_mir() -> ControlFlow<()> { assert_eq!(main_fn.trimmed_name(), "main"); let instances = get_instances(main_fn.body().unwrap()); - assert_eq!(instances.len(), 2); + assert_eq!(instances.len(), 3); test_fn(instances[0], "from_u32", "std::char::from_u32", "core"); test_fn(instances[1], "Vec::::new", "std::vec::Vec::::new", "alloc"); + test_fn(instances[2], "ctpop::", "std::intrinsics::ctpop::", "core"); test_vec_new(instances[1]); ControlFlow::Continue(()) } @@ -48,6 +50,14 @@ fn test_fn(instance: Instance, expected_trimmed: &str, expected_qualified: &str, assert_eq!(&trimmed, expected_trimmed); assert_eq!(&qualified, expected_qualified); + if instance.kind == InstanceKind::Intrinsic { + let intrinsic = instance.intrinsic_name().unwrap(); + let (trimmed_base, _trimmed_args) = trimmed.split_once("::").unwrap(); + assert_eq!(intrinsic, trimmed_base); + return; + } + assert!(instance.intrinsic_name().is_none()); + let item = CrateItem::try_from(instance).unwrap(); let trimmed = item.trimmed_name(); let qualified = item.name(); @@ -119,10 +129,12 @@ fn generate_input(path: &str) -> std::io::Result<()> { write!( file, r#" + #![feature(core_intrinsics)] fn main() {{ let _c = core::char::from_u32(99); let _v = Vec::::new(); + let _i = std::intrinsics::ctpop::(0); }} "# )?; diff --git a/tests/ui/abi/foreign/foreign-call-no-runtime.rs b/tests/ui/abi/foreign/foreign-call-no-runtime.rs index 42d8d7b1d259..fccd62b6100f 100644 --- a/tests/ui/abi/foreign/foreign-call-no-runtime.rs +++ b/tests/ui/abi/foreign/foreign-call-no-runtime.rs @@ -40,21 +40,21 @@ pub fn main() { extern "C" fn callback_isize(data: libc::uintptr_t) { unsafe { - let data: *const isize = mem::transmute(data); + let data = data as *const isize; assert_eq!(*data, 100); } } extern "C" fn callback_i64(data: libc::uintptr_t) { unsafe { - let data: *const i64 = mem::transmute(data); + let data = data as *const i64; assert_eq!(*data, 100); } } extern "C" fn callback_i32(data: libc::uintptr_t) { unsafe { - let data: *const i32 = mem::transmute(data); + let data = data as *const i32; assert_eq!(*data, 100); } } diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs index c25835c68dd5..33da7d828c79 100644 --- a/tests/ui/async-await/in-trait/early-bound-2.rs +++ b/tests/ui/async-await/in-trait/early-bound-2.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - pub trait Foo { #[allow(async_fn_in_trait)] async fn foo(&mut self); diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs index dab100b2e22d..a67f7fd182c5 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs @@ -1,7 +1,5 @@ //@ edition: 2021 -#![allow(incomplete_features)] - trait MyTrait { async fn foo(&self) -> i32; } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr index 8260cd5271ee..d8a5ff8b1684 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr @@ -1,11 +1,11 @@ error: method should be `async` or return a future, but it is synchronous - --> $DIR/fn-not-async-err.rs:10:5 + --> $DIR/fn-not-async-err.rs:8:5 | LL | fn foo(&self) -> i32 { | ^^^^^^^^^^^^^^^^^^^^ | note: this method is `async` so it expects a future to be returned - --> $DIR/fn-not-async-err.rs:6:5 + --> $DIR/fn-not-async-err.rs:4:5 | LL | async fn foo(&self) -> i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs index 983d650764e9..0af1e8a66b31 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err2.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs @@ -1,8 +1,6 @@ //@ edition: 2021 //@ check-pass -#![allow(incomplete_features)] - use std::future::Future; trait MyTrait { diff --git a/tests/ui/async-await/in-trait/generics-mismatch.rs b/tests/ui/async-await/in-trait/generics-mismatch.rs index 1f7095ae72b5..d3d1284982a9 100644 --- a/tests/ui/async-await/in-trait/generics-mismatch.rs +++ b/tests/ui/async-await/in-trait/generics-mismatch.rs @@ -1,7 +1,5 @@ //@ edition: 2021 -#![allow(incomplete_features)] - trait Foo { async fn foo(); } diff --git a/tests/ui/async-await/in-trait/generics-mismatch.stderr b/tests/ui/async-await/in-trait/generics-mismatch.stderr index 5f7aeb17117b..c0357dc7f3e6 100644 --- a/tests/ui/async-await/in-trait/generics-mismatch.stderr +++ b/tests/ui/async-await/in-trait/generics-mismatch.stderr @@ -1,5 +1,5 @@ error[E0053]: method `foo` has an incompatible generic parameter for trait `Foo` - --> $DIR/generics-mismatch.rs:10:18 + --> $DIR/generics-mismatch.rs:8:18 | LL | trait Foo { | --- diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs index eda4cf5647f9..72ae0ce68a2f 100644 --- a/tests/ui/async-await/in-trait/implied-bounds.rs +++ b/tests/ui/async-await/in-trait/implied-bounds.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition: 2021 -#![allow(incomplete_features)] - trait TcpStack { type Connection<'a>: Sized where Self: 'a; fn connect<'a>(&'a self) -> Self::Connection<'a>; diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs index fde5f36f39c0..ffb23fcc0da9 100644 --- a/tests/ui/async-await/in-trait/issue-102138.rs +++ b/tests/ui/async-await/in-trait/issue-102138.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - use std::future::Future; async fn yield_now() {} diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs index 954e9e8bc5d9..e373b17db4f4 100644 --- a/tests/ui/async-await/in-trait/issue-102219.rs +++ b/tests/ui/async-await/in-trait/issue-102219.rs @@ -2,8 +2,6 @@ //@ edition:2021 //@ check-pass -#![allow(incomplete_features)] - trait T { #[allow(async_fn_in_trait)] async fn foo(); diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs index ea0646edd17c..daaafba56bf7 100644 --- a/tests/ui/async-await/in-trait/issue-102310.rs +++ b/tests/ui/async-await/in-trait/issue-102310.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - pub trait SpiDevice { #[allow(async_fn_in_trait)] async fn transaction(&mut self); diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs index 5265c4486a17..e64315157b2d 100644 --- a/tests/ui/async-await/in-trait/issue-104678.rs +++ b/tests/ui/async-await/in-trait/issue-104678.rs @@ -1,8 +1,6 @@ //@ edition:2021 //@ check-pass -#![allow(incomplete_features)] - use std::future::Future; pub trait Pool { type Conn; diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs index 3a6b9f3760c8..789b751fcc90 100644 --- a/tests/ui/async-await/in-trait/nested-rpit.rs +++ b/tests/ui/async-await/in-trait/nested-rpit.rs @@ -1,8 +1,6 @@ //@ edition: 2021 //@ check-pass -#![allow(incomplete_features)] - use std::future::Future; use std::marker::PhantomData; diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs similarity index 100% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs rename to tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.rs diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr similarity index 84% rename from tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr rename to tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr index 66902f3ca9aa..a020f21e6ca7 100644 --- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-ident-list.stderr @@ -1,5 +1,5 @@ error: malformed `unix_sigpipe` attribute input - --> $DIR/unix_sigpipe-list.rs:3:1 + --> $DIR/unix_sigpipe-ident-list.rs:3:1 | LL | #[unix_sigpipe(sig_dfl)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs new file mode 100644 index 000000000000..22326835623b --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs @@ -0,0 +1,4 @@ +#![feature(unix_sigpipe)] + +#[unix_sigpipe("sig_dfl")] //~ error: malformed `unix_sigpipe` attribute input +fn main() {} diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr new file mode 100644 index 000000000000..b62c086e3605 --- /dev/null +++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-str-list.stderr @@ -0,0 +1,8 @@ +error: malformed `unix_sigpipe` attribute input + --> $DIR/unix_sigpipe-str-list.rs:3:1 + | +LL | #[unix_sigpipe("sig_dfl")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr index 71d03b38cd61..6402e5681884 100644 --- a/tests/ui/binop/issue-77910-1.stderr +++ b/tests/ui/binop/issue-77910-1.stderr @@ -1,16 +1,3 @@ -error[E0381]: used binding `xs` isn't initialized - --> $DIR/issue-77910-1.rs:3:5 - | -LL | let xs; - | -- binding declared here but left uninitialized -LL | xs - | ^^ `xs` used here but it isn't initialized - | -help: consider assigning a value - | -LL | let xs = todo!(); - | +++++++++ - error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}` --> $DIR/issue-77910-1.rs:8:5 | @@ -35,6 +22,19 @@ LL | assert_eq!(foo, y); = help: use parentheses to call this function: `foo(/* &i32 */)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-1.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0369, E0381. diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr index 87f074ff3136..a14560ff188e 100644 --- a/tests/ui/binop/issue-77910-2.stderr +++ b/tests/ui/binop/issue-77910-2.stderr @@ -1,16 +1,3 @@ -error[E0381]: used binding `xs` isn't initialized - --> $DIR/issue-77910-2.rs:3:5 - | -LL | let xs; - | -- binding declared here but left uninitialized -LL | xs - | ^^ `xs` used here but it isn't initialized - | -help: consider assigning a value - | -LL | let xs = todo!(); - | +++++++++ - error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}` --> $DIR/issue-77910-2.rs:7:12 | @@ -24,6 +11,19 @@ help: use parentheses to call this function LL | if foo(/* &i32 */) == y {} | ++++++++++++ +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-2.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + error: aborting due to 2 previous errors Some errors have detailed explanations: E0369, E0381. diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr index c5903b3ab561..098a2964e9fc 100644 --- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr +++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr @@ -13,15 +13,6 @@ help: use `addr_of_mut!` instead to create a raw pointer LL | c1(addr_of_mut!(Y)); | ~~~~~~~~~~~~~~~ -error[E0594]: cannot assign to `x`, as it is not declared as mutable - --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46 - | -LL | pub fn e(x: &'static mut isize) { - | - help: consider changing this to be mutable: `mut x` -LL | static mut Y: isize = 3; -LL | let mut c1 = |y: &'static mut isize| x = y; - | ^^^^^ cannot assign - warning: creating a mutable reference to mutable static is discouraged --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:27:16 | @@ -36,6 +27,29 @@ help: use `addr_of_mut!` instead to create a raw pointer LL | c1(addr_of_mut!(Z)); | ~~~~~~~~~~~~~~~ +warning: creating a mutable reference to mutable static is discouraged + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37 + | +LL | borrowck_closures_unique::e(&mut X); + | ^^^^^^ mutable reference to mutable static + | + = note: for more information, see issue #114447 + = note: this will be a hard error in the 2024 edition + = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior +help: use `addr_of_mut!` instead to create a raw pointer + | +LL | borrowck_closures_unique::e(addr_of_mut!(X)); + | ~~~~~~~~~~~~~~~ + +error[E0594]: cannot assign to `x`, as it is not declared as mutable + --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46 + | +LL | pub fn e(x: &'static mut isize) { + | - help: consider changing this to be mutable: `mut x` +LL | static mut Y: isize = 3; +LL | let mut c1 = |y: &'static mut isize| x = y; + | ^^^^^ cannot assign + error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:22:50 | @@ -81,20 +95,6 @@ LL | || { LL | &mut x.0; | ^^^^^^^^ cannot borrow as mutable -warning: creating a mutable reference to mutable static is discouraged - --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37 - | -LL | borrowck_closures_unique::e(&mut X); - | ^^^^^^ mutable reference to mutable static - | - = note: for more information, see issue #114447 - = note: this will be a hard error in the 2024 edition - = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior -help: use `addr_of_mut!` instead to create a raw pointer - | -LL | borrowck_closures_unique::e(addr_of_mut!(X)); - | ~~~~~~~~~~~~~~~ - error: aborting due to 6 previous errors; 3 warnings emitted Some errors have detailed explanations: E0594, E0596. diff --git a/tests/ui/const-generics/auxiliary/generics_of_parent.rs b/tests/ui/const-generics/auxiliary/generics_of_parent.rs index 5c2b1f4bddf8..5009fe469853 100644 --- a/tests/ui/const-generics/auxiliary/generics_of_parent.rs +++ b/tests/ui/const-generics/auxiliary/generics_of_parent.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] // library portion of regression test for #87674 pub struct Foo([(); N + 1]) diff --git a/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs b/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs index cd5b8161d08b..a66ce817be5e 100644 --- a/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs +++ b/tests/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] // library portion of testing that `impl Trait<{ expr }>` doesnt // ice because of a `DefKind::TyParam` parent diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs index 97be074933d9..8779e20a2af6 100644 --- a/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/anon_const_non_local.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] pub struct Foo; diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs index 15d618caef4b..9890e46e4453 100644 --- a/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] pub fn test1() -> [u8; std::mem::size_of::() - 1] where diff --git a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr index 3a7f3cd0ba00..921314f0c504 100644 --- a/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr +++ b/tests/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr @@ -6,7 +6,7 @@ LL | let _ = const_evaluatable_lib::test1::(); | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + --> $DIR/auxiliary/const_evaluatable_lib.rs:5:10 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] | ----- required by a bound in this function @@ -22,7 +22,7 @@ LL | let _ = const_evaluatable_lib::test1::(); | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + --> $DIR/auxiliary/const_evaluatable_lib.rs:3:27 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` @@ -35,7 +35,7 @@ LL | let _ = const_evaluatable_lib::test1::(); | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10 + --> $DIR/auxiliary/const_evaluatable_lib.rs:5:10 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] | ----- required by a bound in this function @@ -51,7 +51,7 @@ LL | let _ = const_evaluatable_lib::test1::(); | = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::() - 1]:` note: required by a bound in `test1` - --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27 + --> $DIR/auxiliary/const_evaluatable_lib.rs:3:27 | LL | pub fn test1() -> [u8; std::mem::size_of::() - 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1` diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr index bfb40c7e54f6..bb6d650b7ab2 100644 --- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr +++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr @@ -21,12 +21,6 @@ LL | impl Q for [u8; N] {} | | | unsatisfied trait bound introduced here -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:8:31 - | -LL | impl Q for [u8; N] {} - | ^ expected `usize`, found `u64` - error[E0308]: mismatched types --> $DIR/type_mismatch.rs:12:20 | @@ -35,6 +29,12 @@ LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {} | | | implicitly returns `()` as its body has no tail or `return` expression +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:8:31 + | +LL | impl Q for [u8; N] {} + | ^ expected `usize`, found `u64` + error: aborting due to 4 previous errors Some errors have detailed explanations: E0046, E0308. diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr index 557530ebe3d4..77a7da17c131 100644 --- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr @@ -34,6 +34,14 @@ LL + #[derive(ConstParamTy)] LL | struct Foo(u8); | +error: unconstrained generic constant + --> $DIR/unify-op-with-fn-call.rs:30:12 + | +LL | bar2::<{ std::ops::Add::add(N, N) }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` + error[E0015]: cannot call non-const operator in constants --> $DIR/unify-op-with-fn-call.rs:20:39 | @@ -57,14 +65,6 @@ LL | bar::<{ std::ops::Add::add(N, N) }>(); = note: calls in constants are limited to constant functions, tuple structs and tuple variants = help: add `#![feature(effects)]` to the crate attributes to enable -error: unconstrained generic constant - --> $DIR/unify-op-with-fn-call.rs:30:12 - | -LL | bar2::<{ std::ops::Add::add(N, N) }>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:` - error[E0015]: cannot call non-const fn `::add` in constants --> $DIR/unify-op-with-fn-call.rs:30:14 | diff --git a/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs b/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs index 6a10ee267df9..21e6b344586f 100644 --- a/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs +++ b/tests/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs @@ -1,5 +1,4 @@ #![feature(generic_const_exprs)] -#![allow(incomplete_features)] // All of these three items must be in `lib2` to reproduce the error diff --git a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr index 989be74d1b0d..5bef6f3c795e 100644 --- a/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr +++ b/tests/ui/const-generics/parent_generics_of_encoding_impl_trait.stderr @@ -5,7 +5,7 @@ LL | generics_of_parent_impl_trait::foo([()]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `foo` | note: required by a bound in `foo` - --> $DIR/auxiliary/generics_of_parent_impl_trait.rs:6:48 + --> $DIR/auxiliary/generics_of_parent_impl_trait.rs:5:48 | LL | pub fn foo(foo: impl Into<[(); N + 1]>) { | ^^^^^ required by this bound in `foo` diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index 9e308620a9c2..12644b9f36d0 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -16,18 +16,6 @@ LL | std::mem::transmute(v) = note: source type: `[[u32; H]; W]` (this type does not have a fixed size) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) -error[E0308]: mismatched types - --> $DIR/transmute-fail.rs:12:53 - | -LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - | ^ expected `usize`, found `bool` - -error[E0308]: mismatched types - --> $DIR/transmute-fail.rs:12:67 - | -LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { - | ^ expected `usize`, found `bool` - error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/transmute-fail.rs:23:5 | @@ -46,6 +34,18 @@ LL | std::mem::transmute(v) = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:53 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + +error[E0308]: mismatched types + --> $DIR/transmute-fail.rs:12:67 + | +LL | fn bar(v: [[u32; H]; W]) -> [[u32; W]; H] { + | ^ expected `usize`, found `bool` + error: aborting due to 6 previous errors Some errors have detailed explanations: E0308, E0512. diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr index 394dd44d40d3..07476ae76c65 100644 --- a/tests/ui/const-generics/type_mismatch.stderr +++ b/tests/ui/const-generics/type_mismatch.stderr @@ -10,12 +10,6 @@ note: required by a bound in `bar` LL | fn bar() -> [u8; N] {} | ^^^^^^^^^^^ required by this bound in `bar` -error[E0308]: mismatched types - --> $DIR/type_mismatch.rs:2:11 - | -LL | bar::() - | ^ expected `u8`, found `usize` - error[E0308]: mismatched types --> $DIR/type_mismatch.rs:6:26 | @@ -24,6 +18,12 @@ LL | fn bar() -> [u8; N] {} | | | implicitly returns `()` as its body has no tail or `return` expression +error[E0308]: mismatched types + --> $DIR/type_mismatch.rs:2:11 + | +LL | bar::() + | ^ expected `u8`, found `usize` + error[E0308]: mismatched types --> $DIR/type_mismatch.rs:6:31 | diff --git a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs index 411707133a88..8adf3ba433d9 100644 --- a/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs +++ b/tests/ui/consts/auxiliary/closure-in-foreign-crate.rs @@ -1,6 +1,5 @@ #![crate_type = "lib"] #![feature(const_closures, const_trait_impl, effects)] -#![allow(incomplete_features)] pub const fn test() { let cl = const || {}; diff --git a/tests/ui/consts/auxiliary/const_mut_refs_crate.rs b/tests/ui/consts/auxiliary/const_mut_refs_crate.rs new file mode 100644 index 000000000000..8e78748e896e --- /dev/null +++ b/tests/ui/consts/auxiliary/const_mut_refs_crate.rs @@ -0,0 +1,23 @@ +// This is a support file for ../const-mut-refs-crate.rs + +// This is to test that static inners from an external +// crate like this one, still preserves the alloc. +// That is, the address from the standpoint of rustc+llvm +// is the same. +// The need for this test originated from the GH issue +// https://github.com/rust-lang/rust/issues/57349 + +// See also ../const-mut-refs-crate.rs for more details +// about this test. + +#![feature(const_mut_refs)] + +// if we used immutable references here, then promotion would +// turn the `&42` into a promoted, which gets duplicated arbitrarily. +pub static mut FOO: &'static mut i32 = &mut 42; +pub static mut BAR: &'static mut i32 = unsafe { FOO }; + +pub mod inner { + pub static INNER_MOD_FOO: &'static i32 = &43; + pub static INNER_MOD_BAR: &'static i32 = INNER_MOD_FOO; +} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs index 105e8e38d84e..b8fed212c97f 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs @@ -1,9 +1,11 @@ #![feature(core_intrinsics)] #![feature(const_heap)] #![feature(const_mut_refs)] +#![deny(const_eval_mutable_ptr_in_final_value)] use std::intrinsics; const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; //~^ error: mutable pointer in final value of constant +//~| WARNING this was previously accepted by the compiler fn main() {} diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr index bd82e6781be1..bb47adacb9f9 100644 --- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr +++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr @@ -1,8 +1,31 @@ error: encountered mutable pointer in final value of constant - --> $DIR/alloc_intrinsic_untyped.rs:6:1 + --> $DIR/alloc_intrinsic_untyped.rs:7:1 | LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; | ^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/alloc_intrinsic_untyped.rs:4:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/alloc_intrinsic_untyped.rs:7:1 + | +LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 }; + | ^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/alloc_intrinsic_untyped.rs:4:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const-mut-refs-crate.rs b/tests/ui/consts/const-mut-refs-crate.rs new file mode 100644 index 000000000000..dcc8ff370e1e --- /dev/null +++ b/tests/ui/consts/const-mut-refs-crate.rs @@ -0,0 +1,37 @@ +//@ run-pass +//@ aux-build:const_mut_refs_crate.rs + +#![feature(const_mut_refs)] + +//! Regression test for https://github.com/rust-lang/rust/issues/79738 +//! Show how we are not duplicating allocations anymore. Statics that +//! copy their value from another static used to also duplicate +//! memory behind references. + +extern crate const_mut_refs_crate as other; + +use other::{ + inner::{INNER_MOD_BAR, INNER_MOD_FOO}, + BAR, FOO, +}; + +pub static LOCAL_FOO: &'static i32 = &41; +pub static LOCAL_BAR: &'static i32 = LOCAL_FOO; +pub static mut COPY_OF_REMOTE_FOO: &'static mut i32 = unsafe { FOO }; + +static DOUBLE_REF: &&i32 = &&99; +static ONE_STEP_ABOVE: &i32 = *DOUBLE_REF; +static mut DOUBLE_REF_MUT: &mut &mut i32 = &mut &mut 99; +static mut ONE_STEP_ABOVE_MUT: &mut i32 = unsafe { *DOUBLE_REF_MUT }; + +pub fn main() { + unsafe { + assert_eq!(FOO as *const i32, BAR as *const i32); + assert_eq!(INNER_MOD_FOO as *const i32, INNER_MOD_BAR as *const i32); + assert_eq!(LOCAL_FOO as *const i32, LOCAL_BAR as *const i32); + assert_eq!(*DOUBLE_REF as *const i32, ONE_STEP_ABOVE as *const i32); + assert_eq!(*DOUBLE_REF_MUT as *mut i32, ONE_STEP_ABOVE_MUT as *mut i32); + + assert_eq!(FOO as *const i32, COPY_OF_REMOTE_FOO as *const i32); + } +} diff --git a/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs new file mode 100644 index 000000000000..ca119f831b14 --- /dev/null +++ b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.rs @@ -0,0 +1,18 @@ +//@ check-pass +use std::cell::Cell; + +pub enum JsValue { + Undefined, + Object(Cell), +} + +impl ::std::ops::Drop for JsValue { + fn drop(&mut self) {} +} + +const UNDEFINED: &JsValue = &JsValue::Undefined; + //~^ WARN encountered mutable pointer in final value of constant + //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +fn main() { +} diff --git a/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr new file mode 100644 index 000000000000..85de4e7ff32e --- /dev/null +++ b/tests/ui/consts/future-incompat-mutable-in-final-value-issue-121610.stderr @@ -0,0 +1,23 @@ +warning: encountered mutable pointer in final value of constant + --> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1 + | +LL | const UNDEFINED: &JsValue = &JsValue::Undefined; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: encountered mutable pointer in final value of constant + --> $DIR/future-incompat-mutable-in-final-value-issue-121610.rs:13:1 + | +LL | const UNDEFINED: &JsValue = &JsValue::Undefined; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default + diff --git a/tests/ui/consts/miri_unleashed/mutable_references.rs b/tests/ui/consts/miri_unleashed/mutable_references.rs index ce7df4b16208..8878e8eccf12 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references.rs @@ -1,19 +1,25 @@ //@ compile-flags: -Zunleash-the-miri-inside-of-you +//@ normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +//@ normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" +#![deny(const_eval_mutable_ptr_in_final_value)] use std::cell::UnsafeCell; // a test demonstrating what things we could allow with a smarter const qualification static FOO: &&mut u32 = &&mut 42; //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler static BAR: &mut () = &mut (); //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler struct Foo(T); static BOO: &mut Foo<()> = &mut Foo(()); //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler struct Meh { x: &'static UnsafeCell, @@ -21,9 +27,12 @@ struct Meh { unsafe impl Sync for Meh {} static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler static OH_YES: &mut i32 = &mut 42; //~^ ERROR encountered mutable pointer in final value of static +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value fn main() { unsafe { diff --git a/tests/ui/consts/miri_unleashed/mutable_references.stderr b/tests/ui/consts/miri_unleashed/mutable_references.stderr index 532d7408e68f..7122eb609f15 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references.stderr @@ -1,35 +1,66 @@ -error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:7:1 - | -LL | static FOO: &&mut u32 = &&mut 42; - | ^^^^^^^^^^^^^^^^^^^^^ - error: encountered mutable pointer in final value of static --> $DIR/mutable_references.rs:10:1 | -LL | static BAR: &mut () = &mut (); - | ^^^^^^^^^^^^^^^^^^^ +LL | static FOO: &&mut u32 = &&mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:15:1 + --> $DIR/mutable_references.rs:14:1 + | +LL | static BAR: &mut () = &mut (); + | ^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:20:1 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:22:1 + --> $DIR/mutable_references.rs:28:1 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of static - --> $DIR/mutable_references.rs:25:1 + --> $DIR/mutable_references.rs:32:1 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references.rs:32:1 + | +LL | static OH_YES: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item - --> $DIR/mutable_references.rs:32:5 + --> $DIR/mutable_references.rs:41:5 | LL | *OH_YES = 99; | ^^^^^^^^^^^^ cannot assign @@ -37,31 +68,107 @@ LL | *OH_YES = 99; warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:7:26 + --> $DIR/mutable_references.rs:10:26 | LL | static FOO: &&mut u32 = &&mut 42; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:10:23 + --> $DIR/mutable_references.rs:14:23 | LL | static BAR: &mut () = &mut (); | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:15:28 + --> $DIR/mutable_references.rs:20:28 | LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:22:28 + --> $DIR/mutable_references.rs:28:28 | LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:25:27 + --> $DIR/mutable_references.rs:32:27 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^ -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 7 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0080, E0594. +For more information about an error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:10:1 + | +LL | static FOO: &&mut u32 = &&mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:14:1 + | +LL | static BAR: &mut () = &mut (); + | ^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:20:1 + | +LL | static BOO: &mut Foo<()> = &mut Foo(()); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:28:1 + | +LL | static MEH: Meh = Meh { x: &UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/mutable_references.rs:32:1 + | +LL | static OH_YES: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For more information about this error, try `rustc --explain E0594`. diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.rs b/tests/ui/consts/miri_unleashed/mutable_references_err.rs index 3f3e5f571758..97b8a71cafa3 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.rs +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.rs @@ -2,7 +2,7 @@ //@ normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" //@ normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" #![allow(invalid_reference_casting, static_mut_refs)] - +#![deny(const_eval_mutable_ptr_in_final_value)] use std::cell::UnsafeCell; use std::sync::atomic::*; @@ -17,6 +17,8 @@ unsafe impl Sync for Meh {} // all allocs interned here will be marked immutable. const MUH: Meh = Meh { //~^ ERROR encountered mutable pointer in final value of constant + //~| WARNING this was previously accepted by the compiler + //~| ERROR: it is undefined behavior to use this value x: &UnsafeCell::new(42), }; @@ -28,14 +30,19 @@ unsafe impl Sync for Synced {} // Make sure we also catch this behind a type-erased `dyn Trait` reference. const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value // Make sure we also catch mutable references in values that shouldn't have them. static mut FOO: i32 = 0; const SUBTLE: &mut i32 = unsafe { &mut FOO }; //~^ ERROR: it is undefined behavior to use this value //~| static + const BLUNT: &mut i32 = &mut 42; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value // Check for mutable references to read-only memory. static READONLY: i32 = 0; @@ -56,10 +63,15 @@ const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; //~^ ERROR: mutable pointer in final value +//~| WARNING this was previously accepted by the compiler struct SyncPtr { x: *const T, @@ -72,10 +84,15 @@ unsafe impl Sync for SyncPtr {} // (Also see `static-no-inner-mut` for similar tests on `static`.) const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler fn main() { unsafe { diff --git a/tests/ui/consts/miri_unleashed/mutable_references_err.stderr b/tests/ui/consts/miri_unleashed/mutable_references_err.stderr index c86e2ea081ff..45615f523a6f 100644 --- a/tests/ui/consts/miri_unleashed/mutable_references_err.stderr +++ b/tests/ui/consts/miri_unleashed/mutable_references_err.stderr @@ -3,15 +3,48 @@ error: encountered mutable pointer in final value of constant | LL | const MUH: Meh = Meh { | ^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:18:1 + | +LL | const MUH: Meh = Meh { + | ^^^^^^^^^^^^^^ constructing invalid value at .x.: encountered `UnsafeCell` in read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:29:1 + --> $DIR/mutable_references_err.rs:31:1 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references_err.rs:34:1 + --> $DIR/mutable_references_err.rs:31:1 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ...x: encountered `UnsafeCell` in read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:38:1 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` @@ -22,14 +55,28 @@ LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; } error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:37:1 + --> $DIR/mutable_references_err.rs:42:1 | LL | const BLUNT: &mut i32 = &mut 42; | ^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error[E0080]: it is undefined behavior to use this value --> $DIR/mutable_references_err.rs:42:1 | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mutable_references_err.rs:49:1 + | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory | @@ -39,7 +86,7 @@ LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const } error[E0080]: it is undefined behavior to use this value - --> $DIR/mutable_references_err.rs:49:1 + --> $DIR/mutable_references_err.rs:56:1 | LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` @@ -50,131 +97,284 @@ LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; } note: erroneous constant encountered - --> $DIR/mutable_references_err.rs:51:34 + --> $DIR/mutable_references_err.rs:58:34 | LL | const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1; | ^^^^^^^^^^^^^^^^^^ error[E0080]: evaluation of constant value failed - --> $DIR/mutable_references_err.rs:53:43 + --> $DIR/mutable_references_err.rs:60:43 | LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; | ^^^^^^^^^^^^^ constant accesses mutable global memory error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:57:1 + --> $DIR/mutable_references_err.rs:64:1 | LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:59:1 + --> $DIR/mutable_references_err.rs:68:1 | LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:61:1 + --> $DIR/mutable_references_err.rs:72:1 | LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:73:1 + --> $DIR/mutable_references_err.rs:85:1 | LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:75:1 + --> $DIR/mutable_references_err.rs:89:1 | LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of constant - --> $DIR/mutable_references_err.rs:77:1 + --> $DIR/mutable_references_err.rs:93:1 | LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:20:8 + --> $DIR/mutable_references_err.rs:22:8 | LL | x: &UnsafeCell::new(42), | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:29:27 + --> $DIR/mutable_references_err.rs:31:27 | LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:34:40 + --> $DIR/mutable_references_err.rs:38:40 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references_err.rs:34:35 + --> $DIR/mutable_references_err.rs:38:35 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:37:25 + --> $DIR/mutable_references_err.rs:42:25 | LL | const BLUNT: &mut i32 = &mut 42; | ^^^^^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references_err.rs:42:49 + --> $DIR/mutable_references_err.rs:49:49 | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references_err.rs:42:49 + --> $DIR/mutable_references_err.rs:49:49 | LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:49:44 + --> $DIR/mutable_references_err.rs:56:44 | LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE }; | ^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/mutable_references_err.rs:53:45 + --> $DIR/mutable_references_err.rs:60:45 | LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF }; | ^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:57:45 + --> $DIR/mutable_references_err.rs:64:45 | LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:59:46 + --> $DIR/mutable_references_err.rs:68:46 | LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:61:47 + --> $DIR/mutable_references_err.rs:72:47 | LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:73:51 + --> $DIR/mutable_references_err.rs:85:51 | LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:75:49 + --> $DIR/mutable_references_err.rs:89:49 | LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_err.rs:77:51 + --> $DIR/mutable_references_err.rs:93:51 | LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 13 previous errors; 1 warning emitted +error: aborting due to 16 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:18:1 + | +LL | const MUH: Meh = Meh { + | ^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:31:1 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:42:1 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:64:1 + | +LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:68:1 + | +LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:72:1 + | +LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:85:1 + | +LL | const RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:89:1 + | +LL | const RAW_MUT_CAST: SyncPtr = SyncPtr { x: &mut 42 as *mut _ as *const _ }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of constant + --> $DIR/mutable_references_err.rs:93:1 + | +LL | const RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/mutable_references_err.rs:5:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr index e8ed6742fab3..85ed6cbd5383 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.32bit.stderr @@ -3,42 +3,90 @@ error: encountered mutable pointer in final value of static | LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^^^^ - -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:10:1 | -LL | static REFMUT: &mut i32 = &mut 0; - | ^^^^^^^^^^^^^^^^^^^^^^^ + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered mutable pointer in final value of static --> $DIR/static-no-inner-mut.rs:13:1 | -LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; +LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:13:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ + } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:14:1 + --> $DIR/static-no-inner-mut.rs:19:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:23:1 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:23:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC1╼ │ ╾──╼ + } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:29:1 + --> $DIR/static-no-inner-mut.rs:41:1 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:31:1 + --> $DIR/static-no-inner-mut.rs:45:1 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:33:1 + --> $DIR/static-no-inner-mut.rs:49:1 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 warning: skipping const checks | @@ -48,35 +96,141 @@ help: skipping check that does not even have a feature gate LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:10:27 + --> $DIR/static-no-inner-mut.rs:13:27 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:13:56 + --> $DIR/static-no-inner-mut.rs:19:56 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:14:44 + --> $DIR/static-no-inner-mut.rs:23:44 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:29:52 + --> $DIR/static-no-inner-mut.rs:41:52 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:31:51 + --> $DIR/static-no-inner-mut.rs:45:51 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:33:52 + --> $DIR/static-no-inner-mut.rs:49:52 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 9 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:9:1 + | +LL | static REF: &AtomicI32 = &AtomicI32::new(42); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:13:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:19:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:23:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:41:1 + | +LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:45:1 + | +LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:49:1 + | +LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr index e8ed6742fab3..5aa1cd0b15fc 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.64bit.stderr @@ -3,42 +3,90 @@ error: encountered mutable pointer in final value of static | LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^^^^ - -error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:10:1 | -LL | static REFMUT: &mut i32 = &mut 0; - | ^^^^^^^^^^^^^^^^^^^^^^^ + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered mutable pointer in final value of static --> $DIR/static-no-inner-mut.rs:13:1 | -LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; +LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:13:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ + } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:14:1 + --> $DIR/static-no-inner-mut.rs:19:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:23:1 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + +error[E0080]: it is undefined behavior to use this value + --> $DIR/static-no-inner-mut.rs:23:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC1╼ │ ╾──────╼ + } error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:29:1 + --> $DIR/static-no-inner-mut.rs:41:1 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:31:1 + --> $DIR/static-no-inner-mut.rs:45:1 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 error: encountered mutable pointer in final value of static - --> $DIR/static-no-inner-mut.rs:33:1 + --> $DIR/static-no-inner-mut.rs:49:1 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 warning: skipping const checks | @@ -48,35 +96,141 @@ help: skipping check that does not even have a feature gate LL | static REF: &AtomicI32 = &AtomicI32::new(42); | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:10:27 + --> $DIR/static-no-inner-mut.rs:13:27 | LL | static REFMUT: &mut i32 = &mut 0; | ^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:13:56 + --> $DIR/static-no-inner-mut.rs:19:56 | LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; | ^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:14:44 + --> $DIR/static-no-inner-mut.rs:23:44 | LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; | ^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:29:52 + --> $DIR/static-no-inner-mut.rs:41:52 | LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; | ^^^^^^^^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:31:51 + --> $DIR/static-no-inner-mut.rs:45:51 | LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; | ^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/static-no-inner-mut.rs:33:52 + --> $DIR/static-no-inner-mut.rs:49:52 | LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; | ^^^^^^ -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 9 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. +Future incompatibility report: Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:9:1 + | +LL | static REF: &AtomicI32 = &AtomicI32::new(42); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:13:1 + | +LL | static REFMUT: &mut i32 = &mut 0; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:19:1 + | +LL | static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:23:1 + | +LL | static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:41:1 + | +LL | static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:45:1 + | +LL | static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: encountered mutable pointer in final value of static + --> $DIR/static-no-inner-mut.rs:49:1 + | +LL | static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 +note: the lint level is defined here + --> $DIR/static-no-inner-mut.rs:6:9 + | +LL | #![deny(const_eval_mutable_ptr_in_final_value)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs index 4219f6fa683b..e82ca50d8822 100644 --- a/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs +++ b/tests/ui/consts/miri_unleashed/static-no-inner-mut.rs @@ -3,15 +3,27 @@ #![feature(const_refs_to_cell, const_mut_refs)] // All "inner" allocations that come with a `static` are interned immutably. This means it is // crucial that we do not accept any form of (interior) mutability there. - +#![deny(const_eval_mutable_ptr_in_final_value)] use std::sync::atomic::*; -static REF: &AtomicI32 = &AtomicI32::new(42); //~ERROR mutable pointer in final value -static REFMUT: &mut i32 = &mut 0; //~ERROR mutable pointer in final value +static REF: &AtomicI32 = &AtomicI32::new(42); +//~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + +static REFMUT: &mut i32 = &mut 0; +//~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value // Different way of writing this that avoids promotion. -static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; //~ERROR mutable pointer in final value -static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; //~ERROR mutable pointer in final value +static REF2: &AtomicI32 = {let x = AtomicI32::new(42); &{x}}; +//~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + +static REFMUT2: &mut i32 = {let mut x = 0; &mut {x}}; +//~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler +//~| ERROR it is undefined behavior to use this value // This one is obvious, since it is non-Sync. (It also suppresses the other errors, so it is // commented out.) @@ -28,9 +40,14 @@ unsafe impl Sync for SyncPtr {} // non-dangling raw pointers. static RAW_SYNC: SyncPtr = SyncPtr { x: &AtomicI32::new(42) }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + static RAW_MUT_CAST: SyncPtr = SyncPtr { x : &mut 42 as *mut _ as *const _ }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler + static RAW_MUT_COERCE: SyncPtr = SyncPtr { x: &mut 0 }; //~^ ERROR mutable pointer in final value +//~| WARNING this was previously accepted by the compiler fn main() {} diff --git a/tests/ui/consts/refs-to-cell-in-final.rs b/tests/ui/consts/refs-to-cell-in-final.rs index ada56a82a5d1..c7ccd25fc4cb 100644 --- a/tests/ui/consts/refs-to-cell-in-final.rs +++ b/tests/ui/consts/refs-to-cell-in-final.rs @@ -28,7 +28,8 @@ impl Drop for JsValue { fn drop(&mut self) {} } const UNDEFINED: &JsValue = &JsValue::Undefined; -//~^ERROR: mutable pointer in final value of constant +//~^ WARNING: mutable pointer in final value of constant +//~| WARNING: this was previously accepted by the compiler but is being phased out // In contrast, this one works since it is being promoted. const NONE: &'static Option> = &None; diff --git a/tests/ui/consts/refs-to-cell-in-final.stderr b/tests/ui/consts/refs-to-cell-in-final.stderr index b06db3e116ce..2a7a858ebc9b 100644 --- a/tests/ui/consts/refs-to-cell-in-final.stderr +++ b/tests/ui/consts/refs-to-cell-in-final.stderr @@ -12,12 +12,27 @@ error[E0492]: constants cannot refer to interior mutable data LL | const RAW_SYNC_C: SyncPtr> = SyncPtr { x: &Cell::new(42) }; | ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value -error: encountered mutable pointer in final value of constant +warning: encountered mutable pointer in final value of constant --> $DIR/refs-to-cell-in-final.rs:30:1 | LL | const UNDEFINED: &JsValue = &JsValue::Undefined; | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0492`. +Future incompatibility report: Future breakage diagnostic: +warning: encountered mutable pointer in final value of constant + --> $DIR/refs-to-cell-in-final.rs:30:1 + | +LL | const UNDEFINED: &JsValue = &JsValue::Undefined; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 #122153 + = note: `#[warn(const_eval_mutable_ptr_in_final_value)]` on by default + diff --git a/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs b/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs index 7673c7936783..ce892088f500 100644 --- a/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs +++ b/tests/ui/dyn-star/auxiliary/dyn-star-foreign.rs @@ -1,5 +1,4 @@ #![feature(dyn_star)] -#![allow(incomplete_features)] use std::fmt::Display; diff --git a/tests/ui/dyn-star/no-implicit-dyn-star.stderr b/tests/ui/dyn-star/no-implicit-dyn-star.stderr index bea334a8a69a..d1d3da9ca702 100644 --- a/tests/ui/dyn-star/no-implicit-dyn-star.stderr +++ b/tests/ui/dyn-star/no-implicit-dyn-star.stderr @@ -10,7 +10,7 @@ LL | dyn_star_foreign::require_dyn_star_display(1usize); found type `usize` = help: `usize` implements `Display`, `#[feature(dyn_star)]` is likely not enabled; that feature it is currently incomplete note: function defined here - --> $DIR/auxiliary/dyn-star-foreign.rs:6:8 + --> $DIR/auxiliary/dyn-star-foreign.rs:5:8 | LL | pub fn require_dyn_star_display(_: dyn* Display) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/explicit-tail-calls/return-mismatches.stderr b/tests/ui/explicit-tail-calls/return-mismatches.stderr index 147cec499e8b..31c7a46ded91 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.stderr +++ b/tests/ui/explicit-tail-calls/return-mismatches.stderr @@ -16,6 +16,12 @@ LL | become _g1(); = note: expected unit type `()` found type `!` +error[E0308]: mismatched types + --> $DIR/return-mismatches.rs:21:5 + | +LL | become _g2(); + | ^^^^^^^^^^^^ expected `u32`, found `u16` + warning: function cannot return without recursing --> $DIR/return-mismatches.rs:16:1 | @@ -27,12 +33,6 @@ LL | become _g1(); = help: a `loop` may express intention better if this is on purpose = note: `#[warn(unconditional_recursion)]` on by default -error[E0308]: mismatched types - --> $DIR/return-mismatches.rs:21:5 - | -LL | become _g2(); - | ^^^^^^^^^^^^ expected `u32`, found `u16` - error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/expr/if/if-no-match-bindings.stderr b/tests/ui/expr/if/if-no-match-bindings.stderr index 34ba126d9a77..18f3b6b168ec 100644 --- a/tests/ui/expr/if/if-no-match-bindings.stderr +++ b/tests/ui/expr/if/if-no-match-bindings.stderr @@ -1,12 +1,3 @@ -error[E0515]: cannot return reference to temporary value - --> $DIR/if-no-match-bindings.rs:8:38 - | -LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true } - | ^^^^^---- - | | | - | | temporary value created here - | returns a reference to data owned by the current function - error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:19:8 | @@ -99,6 +90,15 @@ LL - while &mut true {} LL + while true {} | +error[E0515]: cannot return reference to temporary value + --> $DIR/if-no-match-bindings.rs:8:38 + | +LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true } + | ^^^^^---- + | | | + | | temporary value created here + | returns a reference to data owned by the current function + error: aborting due to 9 previous errors Some errors have detailed explanations: E0308, E0515. diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr index 7b295c7bd456..d39513ec523a 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.stderr +++ b/tests/ui/generic-associated-types/issue-74684-2.stderr @@ -1,19 +1,3 @@ -error[E0597]: `a` does not live long enough - --> $DIR/issue-74684-2.rs:13:25 - | -LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { - | -- lifetime `'a` defined here -LL | let a = [0; 1]; - | - binding `a` declared here -LL | let x = T::identity(&a); - | ------------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'a` -LL | todo!() -LL | } - | - `a` dropped here while still borrowed - error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]` --> $DIR/issue-74684-2.rs:21:9 | @@ -33,6 +17,22 @@ note: required by a bound in `bug` LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { | ^^^^^^^^^^^^ required by this bound in `bug` +error[E0597]: `a` does not live long enough + --> $DIR/issue-74684-2.rs:13:25 + | +LL | fn bug<'a, T: ?Sized + Fun = [u8]>>(t: Box) -> &'static T::F<'a> { + | -- lifetime `'a` defined here +LL | let a = [0; 1]; + | - binding `a` declared here +LL | let x = T::identity(&a); + | ------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +LL | todo!() +LL | } + | - `a` dropped here while still borrowed + error: aborting due to 2 previous errors Some errors have detailed explanations: E0271, E0597. diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.rs b/tests/ui/generic-associated-types/issue-90014-tait2.rs index 4ba32011c0d6..ef54a89aaae5 100644 --- a/tests/ui/generic-associated-types/issue-90014-tait2.rs +++ b/tests/ui/generic-associated-types/issue-90014-tait2.rs @@ -6,7 +6,6 @@ //@ error-pattern: expected generic lifetime parameter, found `'a` #![feature(type_alias_impl_trait)] -#![allow(incomplete_features)] use std::future::Future; diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr index 58390032d92d..be6f4272ce18 100644 --- a/tests/ui/generic-associated-types/issue-90014-tait2.stderr +++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'a` - --> $DIR/issue-90014-tait2.rs:27:9 + --> $DIR/issue-90014-tait2.rs:26:9 | LL | type Fut<'a> = impl Future; | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr index 6b20a820b730..bb4c2a4c5235 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr @@ -394,17 +394,17 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered +error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12 | LL | m!(0, ..ALMOST_MAX); - | ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered + | ^ pattern `340282366920938463463374607431768211454_u128..` not covered | = note: the matched value is of type `u128` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u128..=u128::MAX => todo!() } - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u128.. => todo!() } + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u128` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12 @@ -754,17 +754,17 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | match $s { $($t)+ => {}, i128::MAX => todo!() } | ++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered +error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12 | LL | m!(0, ..ALMOST_MAX); - | ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered + | ^ pattern `170141183460469231731687303715884105726_i128..` not covered | = note: the matched value is of type `i128` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i128..=i128::MAX => todo!() } - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i128.. => todo!() } + | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `i128::MIN` not covered --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12 diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr index 23dfc77d92ec..f220ba6f3389 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr @@ -18,19 +18,6 @@ help: consider further restricting this bound LL | where F : Foo<'x> + for<'tcx> Foo<'tcx> | +++++++++++++++++++++ -warning: function cannot return without recursing - --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 - | -LL | / fn want_foo_for_any_tcx(f: &F) -LL | | where F : for<'tcx> Foo<'tcx> - | |_________________________________^ cannot return without recursing -... -LL | want_foo_for_any_tcx(f); - | ----------------------- recursive call site - | - = help: a `loop` may express intention better if this is on purpose - = note: `#[warn(unconditional_recursion)]` on by default - error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26 | @@ -51,6 +38,19 @@ help: consider further restricting this bound LL | where B : Bar<'x> + for<'ccx> Bar<'ccx> | +++++++++++++++++++++ +warning: function cannot return without recursing + --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 + | +LL | / fn want_foo_for_any_tcx(f: &F) +LL | | where F : for<'tcx> Foo<'tcx> + | |_________________________________^ cannot return without recursing +... +LL | want_foo_for_any_tcx(f); + | ----------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + warning: function cannot return without recursing --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 | diff --git a/tests/ui/impl-trait/associated-type-cycle.rs b/tests/ui/impl-trait/associated-type-cycle.rs new file mode 100644 index 000000000000..4c1fc1a0fa61 --- /dev/null +++ b/tests/ui/impl-trait/associated-type-cycle.rs @@ -0,0 +1,14 @@ +trait Foo { + type Bar; + fn foo(self) -> Self::Bar; +} + +impl Foo for Box { + //~^ ERROR: the value of the associated type `Bar` in `Foo` must be specified + type Bar = ::Bar; + fn foo(self) -> ::Bar { + (*self).foo() + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/associated-type-cycle.stderr b/tests/ui/impl-trait/associated-type-cycle.stderr new file mode 100644 index 000000000000..7eef8d1e3389 --- /dev/null +++ b/tests/ui/impl-trait/associated-type-cycle.stderr @@ -0,0 +1,12 @@ +error[E0191]: the value of the associated type `Bar` in `Foo` must be specified + --> $DIR/associated-type-cycle.rs:6:22 + | +LL | type Bar; + | -------- `Bar` defined here +... +LL | impl Foo for Box { + | ^^^ help: specify the associated type: `Foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/impl-trait/in-trait/deep-match-works.rs b/tests/ui/impl-trait/in-trait/deep-match-works.rs index 3978b909ed53..02fe5b0e19bf 100644 --- a/tests/ui/impl-trait/in-trait/deep-match-works.rs +++ b/tests/ui/impl-trait/in-trait/deep-match-works.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(lint_reasons)] -#![allow(incomplete_features)] pub struct Wrapper(T); diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs index 9cfac8954305..5deafe5c65ff 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs @@ -1,7 +1,5 @@ //@ edition:2021 -#![allow(incomplete_features)] - pub trait Foo { async fn woopsie_async(&self) -> String { 42 diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr index 9fa73d817ca9..856c92217b92 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/default-body-type-err-2.rs:7:9 + --> $DIR/default-body-type-err-2.rs:5:9 | LL | async fn woopsie_async(&self) -> String { | ------ expected `String` because of return type diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs index 508826e2f77a..c1a78bc23885 100644 --- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs +++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs @@ -1,8 +1,6 @@ //@ edition:2021 //@ check-pass -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs index 631ee2b08434..5674507ad12c 100644 --- a/tests/ui/impl-trait/in-trait/default-body.rs +++ b/tests/ui/impl-trait/in-trait/default-body.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/early.rs b/tests/ui/impl-trait/in-trait/early.rs index 21d629b3ca7f..294be02ad8d7 100644 --- a/tests/ui/impl-trait/in-trait/early.rs +++ b/tests/ui/impl-trait/in-trait/early.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition:2021 -#![allow(incomplete_features)] - pub trait Foo { #[allow(async_fn_in_trait)] async fn bar<'a: 'a>(&'a mut self); diff --git a/tests/ui/impl-trait/in-trait/encode.rs b/tests/ui/impl-trait/in-trait/encode.rs index 8c6a0fdb813f..84dc617cba06 100644 --- a/tests/ui/impl-trait/in-trait/encode.rs +++ b/tests/ui/impl-trait/in-trait/encode.rs @@ -1,8 +1,6 @@ //@ build-pass //@ compile-flags: --crate-type=lib -#![allow(incomplete_features)] - trait Foo { fn bar() -> impl Sized; } diff --git a/tests/ui/impl-trait/in-trait/issue-102301.rs b/tests/ui/impl-trait/in-trait/issue-102301.rs index 2e2a38a29b2b..afd7bf6b1ae7 100644 --- a/tests/ui/impl-trait/in-trait/issue-102301.rs +++ b/tests/ui/impl-trait/in-trait/issue-102301.rs @@ -1,7 +1,5 @@ //@ check-pass -#![allow(incomplete_features)] - trait Foo { fn foo>(self) -> impl Foo; } diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr index 59ffea6fb9f0..2231205327cb 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.lt.stderr @@ -1,5 +1,5 @@ error[E0053]: method `early` has an incompatible type for trait - --> $DIR/method-signature-matches.rs:57:27 + --> $DIR/method-signature-matches.rs:55:27 | LL | fn early<'late, T>(_: &'late ()) {} | - ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | fn early<'late, T>(_: &'late ()) {} | expected this type parameter | note: type in trait - --> $DIR/method-signature-matches.rs:52:28 + --> $DIR/method-signature-matches.rs:50:28 | LL | fn early<'early, T>(x: &'early T) -> impl Sized; | ^^^^^^^^^ diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr index f8980828b89e..ec2a126865d5 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch.stderr @@ -1,5 +1,5 @@ error[E0053]: method `owo` has an incompatible type for trait - --> $DIR/method-signature-matches.rs:13:15 + --> $DIR/method-signature-matches.rs:11:15 | LL | fn owo(_: u8) {} | ^^ @@ -8,7 +8,7 @@ LL | fn owo(_: u8) {} | help: change the parameter type to match the trait: `()` | note: type in trait - --> $DIR/method-signature-matches.rs:8:15 + --> $DIR/method-signature-matches.rs:6:15 | LL | fn owo(x: ()) -> impl Sized; | ^^ diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr index a6fb1a200e69..4d3e64e8050f 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.mismatch_async.stderr @@ -1,5 +1,5 @@ error[E0053]: method `owo` has an incompatible type for trait - --> $DIR/method-signature-matches.rs:24:21 + --> $DIR/method-signature-matches.rs:22:21 | LL | async fn owo(_: u8) {} | ^^ @@ -8,7 +8,7 @@ LL | async fn owo(_: u8) {} | help: change the parameter type to match the trait: `()` | note: type in trait - --> $DIR/method-signature-matches.rs:19:21 + --> $DIR/method-signature-matches.rs:17:21 | LL | async fn owo(x: ()) {} | ^^ diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.rs b/tests/ui/impl-trait/in-trait/method-signature-matches.rs index e6ab932e18e8..e44425d72283 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.rs +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.rs @@ -1,8 +1,6 @@ //@ edition: 2021 //@ revisions: mismatch mismatch_async too_many too_few lt -#![allow(incomplete_features)] - #[cfg(mismatch)] trait Uwu { fn owo(x: ()) -> impl Sized; diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr index 0b26e039e6b2..799d476ab23a 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.too_few.stderr @@ -1,5 +1,5 @@ error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3 - --> $DIR/method-signature-matches.rs:46:5 + --> $DIR/method-signature-matches.rs:44:5 | LL | fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized; | ---------------- trait requires 3 parameters diff --git a/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr b/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr index 9226e1f8b983..e8eac9468a8d 100644 --- a/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr +++ b/tests/ui/impl-trait/in-trait/method-signature-matches.too_many.stderr @@ -1,5 +1,5 @@ error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 - --> $DIR/method-signature-matches.rs:35:28 + --> $DIR/method-signature-matches.rs:33:28 | LL | fn calm_down_please() -> impl Sized; | ------------------------------------ trait requires 0 parameters diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit.rs b/tests/ui/impl-trait/in-trait/nested-rpitit.rs index b19f378cdc16..91fb5331f769 100644 --- a/tests/ui/impl-trait/in-trait/nested-rpitit.rs +++ b/tests/ui/impl-trait/in-trait/nested-rpitit.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(lint_reasons)] -#![allow(incomplete_features)] use std::fmt::Display; use std::ops::Deref; diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs index b0279168fde7..f69f93b92197 100644 --- a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs @@ -1,7 +1,5 @@ //@ check-pass -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/reveal.rs b/tests/ui/impl-trait/in-trait/reveal.rs index a63e7c457d4b..f949077a1317 100644 --- a/tests/ui/impl-trait/in-trait/reveal.rs +++ b/tests/ui/impl-trait/in-trait/reveal.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(lint_reasons)] -#![allow(incomplete_features)] pub trait Foo { fn f() -> Box; diff --git a/tests/ui/impl-trait/in-trait/success.rs b/tests/ui/impl-trait/in-trait/success.rs index 750804f79206..c99291def034 100644 --- a/tests/ui/impl-trait/in-trait/success.rs +++ b/tests/ui/impl-trait/in-trait/success.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(lint_reasons)] -#![allow(incomplete_features)] use std::fmt::Display; diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.rs b/tests/ui/impl-trait/in-trait/wf-bounds.rs index f1e372b196ae..5c34cd037b5c 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.rs +++ b/tests/ui/impl-trait/in-trait/wf-bounds.rs @@ -1,7 +1,5 @@ // issue #101663 -#![allow(incomplete_features)] - use std::fmt::Display; trait Wf { diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr index 7d42659d81ed..634557094ced 100644 --- a/tests/ui/impl-trait/in-trait/wf-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/wf-bounds.rs:14:22 + --> $DIR/wf-bounds.rs:12:22 | LL | fn nya() -> impl Wf>; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -9,14 +9,14 @@ note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/wf-bounds.rs:17:23 + --> $DIR/wf-bounds.rs:15:23 | LL | fn nya2() -> impl Wf<[u8]>; | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` note: required by an implicit `Sized` bound in `Wf` - --> $DIR/wf-bounds.rs:7:10 + --> $DIR/wf-bounds.rs:5:10 | LL | trait Wf { | ^ required by the implicit `Sized` requirement on this type parameter in `Wf` @@ -26,7 +26,7 @@ LL | trait Wf { | ++++++++ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/wf-bounds.rs:20:44 + --> $DIR/wf-bounds.rs:18:44 | LL | fn nya3() -> impl Wf<(), Output = impl Wf>>; | ^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -36,14 +36,14 @@ note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/wf-bounds.rs:23:26 + --> $DIR/wf-bounds.rs:21:26 | LL | fn nya4() -> impl Wf>; | ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter | = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `NeedsDisplay` - --> $DIR/wf-bounds.rs:11:24 + --> $DIR/wf-bounds.rs:9:24 | LL | struct NeedsDisplay(T); | ^^^^^^^ required by this bound in `NeedsDisplay` diff --git a/tests/ui/impl-trait/in-trait/where-clause.rs b/tests/ui/impl-trait/in-trait/where-clause.rs index e502f67c2b7e..3ab3d1496944 100644 --- a/tests/ui/impl-trait/in-trait/where-clause.rs +++ b/tests/ui/impl-trait/in-trait/where-clause.rs @@ -1,8 +1,6 @@ //@ check-pass //@ edition: 2021 -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/impl-trait/stranded-opaque.rs b/tests/ui/impl-trait/stranded-opaque.rs new file mode 100644 index 000000000000..c7ab390e1fd0 --- /dev/null +++ b/tests/ui/impl-trait/stranded-opaque.rs @@ -0,0 +1,13 @@ +trait Trait {} + +impl Trait for i32 {} + +// Since `Assoc` doesn't actually exist, it's "stranded", and won't show up in +// the list of opaques that may be defined by the function. Make sure we don't +// ICE in this case. +fn produce() -> impl Trait { + //~^ ERROR associated type `Assoc` not found for `Trait` + 16 +} + +fn main () {} diff --git a/tests/ui/impl-trait/stranded-opaque.stderr b/tests/ui/impl-trait/stranded-opaque.stderr new file mode 100644 index 000000000000..75f5480bc8b8 --- /dev/null +++ b/tests/ui/impl-trait/stranded-opaque.stderr @@ -0,0 +1,9 @@ +error[E0220]: associated type `Assoc` not found for `Trait` + --> $DIR/stranded-opaque.rs:8:31 + | +LL | fn produce() -> impl Trait { + | ^^^^^ associated type `Assoc` not found + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/instrument-coverage/bad-value.bad.stderr b/tests/ui/instrument-coverage/bad-value.bad.stderr index 0411a1f98a3e..d3415fb35d06 100644 --- a/tests/ui/instrument-coverage/bad-value.bad.stderr +++ b/tests/ui/instrument-coverage/bad-value.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad-value` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected +error: incorrect value `bad-value` for codegen option `instrument-coverage` - one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false` was expected diff --git a/tests/ui/instrument-coverage/bad-value.blank.stderr b/tests/ui/instrument-coverage/bad-value.blank.stderr index b3a8e7cf9478..04c0eab28489 100644 --- a/tests/ui/instrument-coverage/bad-value.blank.stderr +++ b/tests/ui/instrument-coverage/bad-value.blank.stderr @@ -1,2 +1,2 @@ -error: incorrect value `` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected +error: incorrect value `` for codegen option `instrument-coverage` - one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false` was expected diff --git a/tests/ui/instrument-coverage/coverage-options.bad.stderr b/tests/ui/instrument-coverage/coverage-options.bad.stderr new file mode 100644 index 000000000000..ca82dc5bdb93 --- /dev/null +++ b/tests/ui/instrument-coverage/coverage-options.bad.stderr @@ -0,0 +1,2 @@ +error: incorrect value `bad` for unstable option `coverage-options` - `branch` or `no-branch` was expected + diff --git a/tests/ui/instrument-coverage/coverage-options.rs b/tests/ui/instrument-coverage/coverage-options.rs new file mode 100644 index 000000000000..a62e0554f769 --- /dev/null +++ b/tests/ui/instrument-coverage/coverage-options.rs @@ -0,0 +1,14 @@ +//@ needs-profiler-support +//@ revisions: branch no-branch bad +//@ compile-flags -Cinstrument-coverage + +//@ [branch] check-pass +//@ [branch] compile-flags: -Zcoverage-options=branch + +//@ [no-branch] check-pass +//@ [no-branch] compile-flags: -Zcoverage-options=no-branch + +//@ [bad] check-fail +//@ [bad] compile-flags: -Zcoverage-options=bad + +fn main() {} diff --git a/tests/ui/instrument-coverage/unstable.branch.stderr b/tests/ui/instrument-coverage/unstable.branch.stderr deleted file mode 100644 index acc633a2a6d2..000000000000 --- a/tests/ui/instrument-coverage/unstable.branch.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` - diff --git a/tests/ui/instrument-coverage/unstable.except-unused-functions.stderr b/tests/ui/instrument-coverage/unstable.except-unused-functions.stderr deleted file mode 100644 index acc633a2a6d2..000000000000 --- a/tests/ui/instrument-coverage/unstable.except-unused-functions.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` - diff --git a/tests/ui/instrument-coverage/unstable.except-unused-generics.stderr b/tests/ui/instrument-coverage/unstable.except-unused-generics.stderr deleted file mode 100644 index acc633a2a6d2..000000000000 --- a/tests/ui/instrument-coverage/unstable.except-unused-generics.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` - diff --git a/tests/ui/instrument-coverage/unstable.rs b/tests/ui/instrument-coverage/unstable.rs deleted file mode 100644 index ea2279aaf0cd..000000000000 --- a/tests/ui/instrument-coverage/unstable.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ revisions: branch except-unused-functions except-unused-generics -//@ [branch] compile-flags: -Cinstrument-coverage=branch -//@ [except-unused-functions] compile-flags: -Cinstrument-coverage=except-unused-functions -//@ [except-unused-generics] compile-flags: -Cinstrument-coverage=except-unused-generics - -fn main() {} diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr index c5dca7a9313d..3ae5cfc79f87 100644 --- a/tests/ui/issues/issue-11374.stderr +++ b/tests/ui/issues/issue-11374.stderr @@ -1,12 +1,3 @@ -error[E0515]: cannot return value referencing local variable `r` - --> $DIR/issue-11374.rs:20:5 - | -LL | Container::wrap(&mut r as &mut dyn io::Read) - | ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | `r` is borrowed here - | returns a value referencing data owned by the current function - error[E0308]: mismatched types --> $DIR/issue-11374.rs:27:15 | @@ -27,6 +18,15 @@ help: consider mutably borrowing here LL | c.read_to(&mut v); | ++++ +error[E0515]: cannot return value referencing local variable `r` + --> $DIR/issue-11374.rs:20:5 + | +LL | Container::wrap(&mut r as &mut dyn io::Read) + | ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `r` is borrowed here + | returns a value referencing data owned by the current function + error: aborting due to 2 previous errors Some errors have detailed explanations: E0308, E0515. diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index ca3a90f46a72..aad020e4ec97 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -74,15 +74,6 @@ help: consider restricting type parameter `T` LL | fn g(val: T) { | +++++++++++++++++++ -error: lifetime may not live long enough - --> $DIR/kindck-impl-type-params.rs:30:13 - | -LL | fn foo<'a>() { - | -- lifetime `'a` defined here -LL | let t: S<&'a isize> = S(marker::PhantomData); -LL | let a = &t as &dyn Gettable<&'a isize>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - error[E0277]: the trait bound `String: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:36:13 | @@ -120,6 +111,15 @@ LL + #[derive(Copy)] LL | struct Foo; // does not impl Copy | +error: lifetime may not live long enough + --> $DIR/kindck-impl-type-params.rs:30:13 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let t: S<&'a isize> = S(marker::PhantomData); +LL | let a = &t as &dyn Gettable<&'a isize>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index 5d06a2ab4daf..f2aa814676fc 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -12,14 +12,6 @@ note: required by a bound in `assert_send` LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` -error: lifetime may not live long enough - --> $DIR/kindck-send-object1.rs:14:5 - | -LL | fn test52<'a>() { - | -- lifetime `'a` defined here -LL | assert_send::<&'a (dyn Dummy + Sync)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` - error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely --> $DIR/kindck-send-object1.rs:29:19 | @@ -36,6 +28,14 @@ note: required by a bound in `assert_send` LL | fn assert_send() { } | ^^^^ required by this bound in `assert_send` +error: lifetime may not live long enough + --> $DIR/kindck-send-object1.rs:14:5 + | +LL | fn test52<'a>() { + | -- lifetime `'a` defined here +LL | assert_send::<&'a (dyn Dummy + Sync)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/enum-scalar-pair-int-ptr.rs b/tests/ui/layout/enum-scalar-pair-int-ptr.rs new file mode 100644 index 000000000000..a1aec094d802 --- /dev/null +++ b/tests/ui/layout/enum-scalar-pair-int-ptr.rs @@ -0,0 +1,24 @@ +//@ normalize-stderr-test "pref: Align\([1-8] bytes\)" -> "pref: $$PREF_ALIGN" +//@ normalize-stderr-test "Int\(I[0-9]+," -> "Int(I?," +//@ normalize-stderr-test "valid_range: 0..=[0-9]+" -> "valid_range: $$VALID_RANGE" + +//! Enum layout tests related to scalar pairs with an int/ptr common primitive. + +#![feature(rustc_attrs)] +#![feature(never_type)] +#![crate_type = "lib"] + +#[rustc_layout(abi)] +enum ScalarPairPointerWithInt { //~ERROR: abi: ScalarPair + A(usize), + B(Box<()>), +} + +// Negative test--ensure that pointers are not commoned with integers +// of a different size. (Assumes that no target has 8 bit pointers, which +// feels pretty safe.) +#[rustc_layout(abi)] +enum NotScalarPairPointerWithSmallerInt { //~ERROR: abi: Aggregate + A(u8), + B(Box<()>), +} diff --git a/tests/ui/layout/enum-scalar-pair-int-ptr.stderr b/tests/ui/layout/enum-scalar-pair-int-ptr.stderr new file mode 100644 index 000000000000..b25eda628cd6 --- /dev/null +++ b/tests/ui/layout/enum-scalar-pair-int-ptr.stderr @@ -0,0 +1,14 @@ +error: abi: ScalarPair(Initialized { value: Int(I?, false), valid_range: $VALID_RANGE }, Initialized { value: Pointer(AddressSpace(0)), valid_range: $VALID_RANGE }) + --> $DIR/enum-scalar-pair-int-ptr.rs:12:1 + | +LL | enum ScalarPairPointerWithInt { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: abi: Aggregate { sized: true } + --> $DIR/enum-scalar-pair-int-ptr.rs:21:1 + | +LL | enum NotScalarPairPointerWithSmallerInt { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/layout/enum.rs b/tests/ui/layout/enum.rs index bde8450b9d56..e0a7fc328df3 100644 --- a/tests/ui/layout/enum.rs +++ b/tests/ui/layout/enum.rs @@ -16,3 +16,9 @@ enum UninhabitedVariantSpace { //~ERROR: size: Size(16 bytes) A, B([u8; 15], !), // make sure there is space being reserved for this field. } + +#[rustc_layout(abi)] +enum ScalarPairDifferingSign { //~ERROR: abi: ScalarPair + A(u8), + B(i8), +} diff --git a/tests/ui/layout/enum.stderr b/tests/ui/layout/enum.stderr index d6bc7780ce20..7f0b38d0a07c 100644 --- a/tests/ui/layout/enum.stderr +++ b/tests/ui/layout/enum.stderr @@ -10,5 +10,11 @@ error: size: Size(16 bytes) LL | enum UninhabitedVariantSpace { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: abi: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=1 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }) + --> $DIR/enum.rs:21:1 + | +LL | enum ScalarPairDifferingSign { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/lazy-type-alias/auxiliary/lazy.rs b/tests/ui/lazy-type-alias/auxiliary/lazy.rs index caa7999b4f71..2b678226a8ac 100644 --- a/tests/ui/lazy-type-alias/auxiliary/lazy.rs +++ b/tests/ui/lazy-type-alias/auxiliary/lazy.rs @@ -1,4 +1,3 @@ #![feature(lazy_type_alias)] -#![allow(incomplete_features)] pub type Alias = Option; diff --git a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr index fdc5bae15379..887b9e36008e 100644 --- a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr +++ b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_eager.stderr @@ -5,7 +5,7 @@ LL | let _: lazy::Alias; | ^^^^^^ the trait `Copy` is not implemented for `String` | note: required by a bound in `lazy::Alias` - --> $DIR/auxiliary/lazy.rs:4:19 + --> $DIR/auxiliary/lazy.rs:3:19 | LL | pub type Alias = Option; | ^^^^ required by this bound in `Alias` diff --git a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr index fdc5bae15379..887b9e36008e 100644 --- a/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr +++ b/tests/ui/lazy-type-alias/extern-crate-has-lazy-type-aliases.locally_lazy.stderr @@ -5,7 +5,7 @@ LL | let _: lazy::Alias; | ^^^^^^ the trait `Copy` is not implemented for `String` | note: required by a bound in `lazy::Alias` - --> $DIR/auxiliary/lazy.rs:4:19 + --> $DIR/auxiliary/lazy.rs:3:19 | LL | pub type Alias = Option; | ^^^^ required by this bound in `Alias` diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr index 811d8c899910..23547f722a11 100644 --- a/tests/ui/lifetimes/issue-17728.stderr +++ b/tests/ui/lifetimes/issue-17728.stderr @@ -1,19 +1,3 @@ -error: lifetime may not live long enough - --> $DIR/issue-17728.rs:15:28 - | -LL | fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> { - | - - let's call the lifetime of this reference `'1` - | | - | let's call the lifetime of this reference `'2` -... -LL | Some(entry) => Ok(entry), - | ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` - | -help: consider introducing a named lifetime parameter - | -LL | fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> { - | ++++ ++ ++ - error[E0308]: `match` arms have incompatible types --> $DIR/issue-17728.rs:108:14 | @@ -32,6 +16,22 @@ LL | | } = note: expected enum `RoomDirection` found enum `Option<_>` +error: lifetime may not live long enough + --> $DIR/issue-17728.rs:15:28 + | +LL | fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +... +LL | Some(entry) => Ok(entry), + | ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter + | +LL | fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> { + | ++++ ++ ++ + error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-consts.stderr b/tests/ui/liveness/liveness-consts.stderr index ceff62de5d29..34ce39473379 100644 --- a/tests/ui/liveness/liveness-consts.stderr +++ b/tests/ui/liveness/liveness-consts.stderr @@ -40,6 +40,12 @@ LL | b += 1; = help: maybe it is overwritten before being read? = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]` +warning: unused variable: `z` + --> $DIR/liveness-consts.rs:60:13 + | +LL | let z = 42; + | ^ help: if this is intentional, prefix it with an underscore: `_z` + warning: value assigned to `t` is never read --> $DIR/liveness-consts.rs:42:9 | @@ -54,11 +60,5 @@ warning: unused variable: `w` LL | let w = 10; | ^ help: if this is intentional, prefix it with an underscore: `_w` -warning: unused variable: `z` - --> $DIR/liveness-consts.rs:60:13 - | -LL | let z = 42; - | ^ help: if this is intentional, prefix it with an underscore: `_z` - warning: 8 warnings emitted diff --git a/tests/ui/liveness/liveness-forgot-ret.stderr b/tests/ui/liveness/liveness-forgot-ret.stderr index 8f26bbf16d9c..f72a30fc4e9c 100644 --- a/tests/ui/liveness/liveness-forgot-ret.stderr +++ b/tests/ui/liveness/liveness-forgot-ret.stderr @@ -1,14 +1,3 @@ -warning: function cannot return without recursing - --> $DIR/liveness-forgot-ret.rs:1:1 - | -LL | fn god_exists(a: isize) -> bool { return god_exists(a); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------- recursive call site - | | - | cannot return without recursing - | - = help: a `loop` may express intention better if this is on purpose - = note: `#[warn(unconditional_recursion)]` on by default - error[E0308]: mismatched types --> $DIR/liveness-forgot-ret.rs:4:19 | @@ -22,6 +11,17 @@ help: consider returning the local binding `a` LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a } | + +warning: function cannot return without recursing + --> $DIR/liveness-forgot-ret.rs:1:1 + | +LL | fn god_exists(a: isize) -> bool { return god_exists(a); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------- recursive call site + | | + | cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/liveness/liveness-unused.stderr b/tests/ui/liveness/liveness-unused.stderr index 9f9be8c897b5..f6c478ddbc72 100644 --- a/tests/ui/liveness/liveness-unused.stderr +++ b/tests/ui/liveness/liveness-unused.stderr @@ -1,3 +1,18 @@ +warning: unreachable statement + --> $DIR/liveness-unused.rs:92:9 + | +LL | continue; + | -------- any code following this expression is unreachable +LL | drop(*x as i32); + | ^^^^^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/liveness-unused.rs:1:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` + error: unused variable: `x` --> $DIR/liveness-unused.rs:8:7 | @@ -75,21 +90,6 @@ error: unused variable: `x` LL | for (x, _) in [1, 2, 3].iter().enumerate() { } | ^ help: if this is intentional, prefix it with an underscore: `_x` -warning: unreachable statement - --> $DIR/liveness-unused.rs:92:9 - | -LL | continue; - | -------- any code following this expression is unreachable -LL | drop(*x as i32); - | ^^^^^^^^^^^^^^^^ unreachable statement - | -note: the lint level is defined here - --> $DIR/liveness-unused.rs:1:9 - | -LL | #![warn(unused)] - | ^^^^^^ - = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` - error: unused variable: `x` --> $DIR/liveness-unused.rs:89:13 | diff --git a/tests/ui/macros/expand-full-asm.rs b/tests/ui/macros/expand-full-asm.rs new file mode 100644 index 000000000000..0b61aa718f30 --- /dev/null +++ b/tests/ui/macros/expand-full-asm.rs @@ -0,0 +1,27 @@ +//@only-aarch64 +//@check-pass +//@edition: 2018 + +// https://github.com/rust-lang/rust/issues/98291 + +use std::arch::{asm, global_asm}; + +macro_rules! wrap { + () => { + macro_rules! _a { + () => { + "nop" + }; + } + }; +} + +wrap!(); + +use _a as a; + +fn main() { + unsafe { asm!(a!()); } +} + +global_asm!(a!()); diff --git a/tests/ui/macros/expand-full-in-format-str.rs b/tests/ui/macros/expand-full-in-format-str.rs new file mode 100644 index 000000000000..f47f7651a812 --- /dev/null +++ b/tests/ui/macros/expand-full-in-format-str.rs @@ -0,0 +1,33 @@ +//@check-pass +//@edition: 2018 + +// https://github.com/rust-lang/rust/issues/98291 + +macro_rules! wrap { + () => { + macro_rules! _a { + () => { + "auxiliary/macro-include-items-expr.rs" + }; + } + macro_rules! _env_name { + () => { + "PATH" + } + } + }; +} + +wrap!(); + +use _a as a; +use _env_name as env_name; + +fn main() { + format_args!(a!()); + include!(a!()); + include_str!(a!()); + include_bytes!(a!()); + env!(env_name!()); + option_env!(env_name!()); +} diff --git a/tests/ui/macros/expand-full-no-resolution.rs b/tests/ui/macros/expand-full-no-resolution.rs new file mode 100644 index 000000000000..4d90b8e2a531 --- /dev/null +++ b/tests/ui/macros/expand-full-no-resolution.rs @@ -0,0 +1,20 @@ +//@edition: 2018 + +// https://github.com/rust-lang/rust/issues/98291 + +macro_rules! wrap { + () => { + macro_rules! _a { + () => { + "" + }; + } + }; +} + +wrap!(); + +fn main() { + format_args!(a!()); //~ ERROR: cannot find macro `a` in this scope + env!(a!()); //~ ERROR: cannot find macro `a` in this scope +} diff --git a/tests/ui/macros/expand-full-no-resolution.stderr b/tests/ui/macros/expand-full-no-resolution.stderr new file mode 100644 index 000000000000..2537a5032a92 --- /dev/null +++ b/tests/ui/macros/expand-full-no-resolution.stderr @@ -0,0 +1,30 @@ +error: cannot find macro `a` in this scope + --> $DIR/expand-full-no-resolution.rs:18:18 + | +LL | macro_rules! _a { + | --------------- similarly named macro `_a` defined here +... +LL | format_args!(a!()); + | ^ + | +help: a macro with a similar name exists, consider renaming `_a` into `a` + | +LL | macro_rules! a { + | ~ + +error: cannot find macro `a` in this scope + --> $DIR/expand-full-no-resolution.rs:19:10 + | +LL | macro_rules! _a { + | --------------- similarly named macro `_a` defined here +... +LL | env!(a!()); + | ^ + | +help: a macro with a similar name exists, consider renaming `_a` into `a` + | +LL | macro_rules! a { + | ~ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs new file mode 100644 index 000000000000..47df107a2612 --- /dev/null +++ b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs @@ -0,0 +1,7 @@ +fn main() { + unsafe { + dealloc(ptr2, Layout::(x: !)(1, 1)); //~ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` + //~^ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` + //~| while parsing this parenthesized list of type arguments starting here + } +} diff --git a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr new file mode 100644 index 000000000000..8067c97ae4b5 --- /dev/null +++ b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr @@ -0,0 +1,16 @@ +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:3:33 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | --- ^ expected one of 7 possible tokens + | | + | while parsing this parenthesized list of type arguments starting here + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:3:43 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr index 90d0fd7483a9..68976c1b0576 100644 --- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr +++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr @@ -107,17 +107,17 @@ help: ensure that all possible cases are being handled by adding a match arm wit LL | match $s { $($t)+ => {}, u128::MAX => todo!() } | ++++++++++++++++++++++ -error[E0004]: non-exhaustive patterns: `5_u128..=u128::MAX` not covered +error[E0004]: non-exhaustive patterns: `5_u128..` not covered --> $DIR/exhaustiveness.rs:61:8 | LL | m!(0u128, 0..=4); - | ^^^^^ pattern `5_u128..=u128::MAX` not covered + | ^^^^^ pattern `5_u128..` not covered | = note: the matched value is of type `u128` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | match $s { $($t)+ => {}, 5_u128..=u128::MAX => todo!() } - | +++++++++++++++++++++++++++++++ +LL | match $s { $($t)+ => {}, 5_u128.. => todo!() } + | +++++++++++++++++++++ error[E0004]: non-exhaustive patterns: `0_u128` not covered --> $DIR/exhaustiveness.rs:62:8 diff --git a/tests/ui/pattern/usefulness/integer-ranges/regression-switchint-sorting-with-ranges.rs b/tests/ui/pattern/usefulness/integer-ranges/regression-switchint-sorting-with-ranges.rs new file mode 100644 index 000000000000..bacb60a108bf --- /dev/null +++ b/tests/ui/pattern/usefulness/integer-ranges/regression-switchint-sorting-with-ranges.rs @@ -0,0 +1,14 @@ +//@ run-pass +// +// Regression test for match lowering to MIR: when gathering candidates, by the time we get to the +// range we know the range will only match on the failure case of the switchint. Hence we mustn't +// add the `1` to the switchint or the range would be incorrectly sorted. +#![allow(unreachable_patterns)] +fn main() { + match 1 { + 10 => unreachable!(), + 0..=5 => {} + 1 => unreachable!(), + _ => unreachable!(), + } +} diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index ab13b4876b10..5a02d01b4e1c 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -1,3 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 + | +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ---------------------------- ^ one type is more general than the other + | | + | expected due to this + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` + found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` + error: lifetime may not live long enough --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 | @@ -27,17 +38,6 @@ LL | a(x, y); = note: mutable references are invariant over their type parameter = help: see for more information about variance -error[E0308]: mismatched types - --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43 - | -LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ one type is more general than the other - | | - | expected due to this - | - = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` - found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index f1ed0a6bb154..063ff46bb6c4 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -1,3 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 + | +LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; + | ----------------------------------------- ^ one type is more general than the other + | | + | expected due to this + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)` + found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}` + error: lifetime may not live long enough --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 | @@ -27,17 +38,6 @@ LL | a(x, y, z); = note: mutable references are invariant over their type parameter = help: see for more information about variance -error[E0308]: mismatched types - --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56 - | -LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; - | ----------------------------------------- ^ one type is more general than the other - | | - | expected due to this - | - = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)` - found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}` - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr index 807e8172d538..830a61a21f9d 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -1,3 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 + | +LL | let _: fn(&mut &isize, &mut &isize) = a; + | ---------------------------- ^ one type is more general than the other + | | + | expected due to this + | + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` + found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` + error: lifetime may not live long enough --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 | @@ -27,17 +38,6 @@ LL | a(x, y); = note: mutable references are invariant over their type parameter = help: see for more information about variance -error[E0308]: mismatched types - --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43 - | -LL | let _: fn(&mut &isize, &mut &isize) = a; - | ---------------------------- ^ one type is more general than the other - | | - | expected due to this - | - = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` - found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` - error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs index 1933a68c2216..37bd0ce06f0b 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - mod child { trait Main { fn main() -> impl std::process::Termination; diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr index b17700ec6325..f1f53e300abf 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Something: Termination` is not satisfied - --> $DIR/issue-103052-2.rs:11:22 + --> $DIR/issue-103052-2.rs:9:22 | LL | fn main() -> Something { | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` | note: required by a bound in `Main::{synthetic#0}` - --> $DIR/issue-103052-2.rs:5:27 + --> $DIR/issue-103052-2.rs:3:27 | LL | fn main() -> impl std::process::Termination; | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{synthetic#0}` diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs index 02915a5dc372..2ff571a66155 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/coerce-in-base-expr.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(type_changing_struct_update)] -#![allow(incomplete_features)] use std::any::Any; diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs index 15907bc2ddbf..a15312f1119b 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-96878.rs @@ -1,7 +1,6 @@ //@ check-pass #![feature(type_changing_struct_update)] -#![allow(incomplete_features)] use std::borrow::Cow; use std::marker::PhantomData; diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs index df2fef55dd2d..cc0795ff49a7 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.rs @@ -1,5 +1,4 @@ #![feature(type_changing_struct_update)] -#![allow(incomplete_features)] #[derive(Clone)] struct Machine<'a, S> { diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr index 8ae7691a4848..5aae82769ab8 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/lifetime-update.stderr @@ -1,5 +1,5 @@ error[E0597]: `s` does not live long enough - --> $DIR/lifetime-update.rs:20:17 + --> $DIR/lifetime-update.rs:19:17 | LL | let s = String::from("hello"); | - binding `s` declared here diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs index dae1241d35a5..7e8a0e50fdf3 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.rs @@ -1,5 +1,4 @@ #![feature(type_changing_struct_update)] -#![allow(incomplete_features)] struct Machine<'a, S, M> { state: S, diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr index f31b311c732d..88779c8005c2 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/type-generic-update.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/type-generic-update.rs:46:11 + --> $DIR/type-generic-update.rs:45:11 | LL | ..m1 | ^^ expected `Machine<'_, i32, f64>`, found `Machine<'_, f64, f64>` @@ -8,7 +8,7 @@ LL | ..m1 found struct `Machine<'_, f64, _>` error[E0308]: mismatched types - --> $DIR/type-generic-update.rs:51:11 + --> $DIR/type-generic-update.rs:50:11 | LL | ..m1 | ^^ expected `Machine<'_, i32, i32>`, found `Machine<'_, f64, f64>` diff --git a/tests/ui/statics/nested_struct.rs b/tests/ui/statics/nested_struct.rs new file mode 100644 index 000000000000..f5819f50789c --- /dev/null +++ b/tests/ui/statics/nested_struct.rs @@ -0,0 +1,24 @@ +//@ check-pass +/// oli-obk added this test after messing up the interner logic +/// around mutability of nested allocations. This was not caught +/// by the test suite, but by trying to build stage2 rustc. +/// There is no real explanation for this test, as it was just +/// a bug during a refactoring. + +pub struct Lint { + pub name: &'static str, + pub desc: &'static str, + pub report_in_external_macro: bool, + pub is_loaded: bool, + pub crate_level_only: bool, +} + +static FOO: &Lint = &Lint { + name: &"foo", + desc: "desc", + report_in_external_macro: false, + is_loaded: true, + crate_level_only: false, +}; + +fn main() {} diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index 579a5d5180ef..dc24833c267c 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -17,7 +17,7 @@ ast-stats-1 - Fn 96 ( 1.4%) 1 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 FieldDef 160 ( 2.4%) 2 80 ast-stats-1 Stmt 160 ( 2.4%) 5 32 -ast-stats-1 - Local 32 ( 0.5%) 1 +ast-stats-1 - Let 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.4%) 3 ast-stats-1 Param 160 ( 2.4%) 4 40 @@ -75,7 +75,7 @@ ast-stats-2 - DocComment 32 ( 0.4%) 1 ast-stats-2 - Normal 96 ( 1.3%) 3 ast-stats-2 FieldDef 160 ( 2.2%) 2 80 ast-stats-2 Stmt 160 ( 2.2%) 5 32 -ast-stats-2 - Local 32 ( 0.4%) 1 +ast-stats-2 - Let 32 ( 0.4%) 1 ast-stats-2 - Semi 32 ( 0.4%) 1 ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Param 160 ( 2.2%) 4 40 @@ -131,7 +131,7 @@ hir-stats ImplItemRef 72 ( 0.8%) 2 36 hir-stats Arm 80 ( 0.9%) 2 40 hir-stats FieldDef 96 ( 1.1%) 2 48 hir-stats Stmt 96 ( 1.1%) 3 32 -hir-stats - Local 32 ( 0.4%) 1 +hir-stats - Let 32 ( 0.4%) 1 hir-stats - Semi 32 ( 0.4%) 1 hir-stats - Expr 32 ( 0.4%) 1 hir-stats FnDecl 120 ( 1.3%) 3 40 diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr index 58b201d1c774..38f19b332188 100644 --- a/tests/ui/suggestions/issue-102892.stderr +++ b/tests/ui/suggestions/issue-102892.stderr @@ -1,19 +1,3 @@ -error[E0507]: cannot move out of an `Arc` - --> $DIR/issue-102892.rs:11:18 - | -LL | let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! - | - - ^^^^^ - | | | - | | ...and here - | data moved here - | - = note: move occurs because these variables have types that don't implement the `Copy` trait -help: consider removing the dereference here - | -LL - let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! -LL + let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed! - | - error[E0308]: mismatched types --> $DIR/issue-102892.rs:16:26 | @@ -68,6 +52,22 @@ help: alternatively, consider changing the type annotation LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | + +error[E0507]: cannot move out of an `Arc` + --> $DIR/issue-102892.rs:11:18 + | +LL | let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! + | - - ^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the dereference here + | +LL - let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! +LL + let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed! + | + error: aborting due to 4 previous errors Some errors have detailed explanations: E0308, E0507. diff --git a/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs new file mode 100644 index 000000000000..a08407683d8f --- /dev/null +++ b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs @@ -0,0 +1,5 @@ +fn function() { + foo == 2; //~ ERROR cannot find value `foo` in this scope [E0425] +} + +fn main() {} diff --git a/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr new file mode 100644 index 000000000000..2da731dcc4b1 --- /dev/null +++ b/tests/ui/traits/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/dont-match-error-ty-with-calller-supplied-obligation-issue-121941.rs:2:5 + | +LL | foo == 2; + | ^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs b/tests/ui/traits/next-solver/normalize/normalize-async-closure-in-trait.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-async-closure-in-trait.rs rename to tests/ui/traits/next-solver/normalize/normalize-async-closure-in-trait.rs diff --git a/tests/ui/traits/next-solver/normalize-param-env-1.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-1.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-1.rs rename to tests/ui/traits/next-solver/normalize/normalize-param-env-1.rs diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-2.rs rename to tests/ui/traits/next-solver/normalize/normalize-param-env-2.rs diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-2.stderr rename to tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr diff --git a/tests/ui/traits/next-solver/normalize-param-env-3.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-3.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-3.rs rename to tests/ui/traits/next-solver/normalize/normalize-param-env-3.rs diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-4.next.stderr rename to tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.rs b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-param-env-4.rs rename to tests/ui/traits/next-solver/normalize/normalize-param-env-4.rs diff --git a/tests/ui/traits/next-solver/normalize-path-for-method.rs b/tests/ui/traits/next-solver/normalize/normalize-path-for-method.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-path-for-method.rs rename to tests/ui/traits/next-solver/normalize/normalize-path-for-method.rs diff --git a/tests/ui/traits/next-solver/normalize-rcvr-for-inherent.rs b/tests/ui/traits/next-solver/normalize/normalize-rcvr-for-inherent.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-rcvr-for-inherent.rs rename to tests/ui/traits/next-solver/normalize/normalize-rcvr-for-inherent.rs diff --git a/tests/ui/traits/next-solver/normalize-region-obligations.rs b/tests/ui/traits/next-solver/normalize/normalize-region-obligations.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-region-obligations.rs rename to tests/ui/traits/next-solver/normalize/normalize-region-obligations.rs diff --git a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs new file mode 100644 index 000000000000..0ece8f8321ce --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.rs @@ -0,0 +1,24 @@ +//@ check-pass + +// This goal is also possible w/ a GAT, but lazy_type_alias +// makes the behavior a bit more readable. +#![feature(lazy_type_alias)] +//~^ WARN the feature `lazy_type_alias` is incomplete + +struct Wr(T); +trait Foo {} +impl Foo for Wr {} + +type Alias = (T,) + where Wr: Foo; + +fn hello() where Alias: Into<(T,)>, Wr: Foo {} + +fn main() { + // When calling `hello`, proving `Alias: Into<(?0,)>` will require + // normalizing the self type of the goal. This will emit the where + // clause `Wr: Foo`, which constrains `?0` in both the self type + // *and* the non-self part of the goal. That used to trigger a debug + // assertion. + hello::<_>(); +} diff --git a/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr new file mode 100644 index 000000000000..5554f0ccc0aa --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/normalize-self-type-constrains-trait-args.stderr @@ -0,0 +1,11 @@ +warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/normalize-self-type-constrains-trait-args.rs:5:12 + | +LL | #![feature(lazy_type_alias)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #112792 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs b/tests/ui/traits/next-solver/normalize/normalize-type-outlives-in-param-env.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs rename to tests/ui/traits/next-solver/normalize/normalize-type-outlives-in-param-env.rs diff --git a/tests/ui/traits/next-solver/normalize-type-outlives.rs b/tests/ui/traits/next-solver/normalize/normalize-type-outlives.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-type-outlives.rs rename to tests/ui/traits/next-solver/normalize/normalize-type-outlives.rs diff --git a/tests/ui/traits/next-solver/normalize-unsize-rhs.rs b/tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs similarity index 100% rename from tests/ui/traits/next-solver/normalize-unsize-rhs.rs rename to tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs diff --git a/tests/ui/traits/next-solver/normalized-const-built-in-op.rs b/tests/ui/traits/next-solver/normalize/normalized-const-built-in-op.rs similarity index 100% rename from tests/ui/traits/next-solver/normalized-const-built-in-op.rs rename to tests/ui/traits/next-solver/normalize/normalized-const-built-in-op.rs diff --git a/tests/ui/traits/next-solver/projection/param-env-trait-candidate-1.rs b/tests/ui/traits/next-solver/normalize/param-env-trait-candidate-1.rs similarity index 100% rename from tests/ui/traits/next-solver/projection/param-env-trait-candidate-1.rs rename to tests/ui/traits/next-solver/normalize/param-env-trait-candidate-1.rs diff --git a/tests/ui/traits/next-solver/projection/param-env-trait-candidate-2.rs b/tests/ui/traits/next-solver/normalize/param-env-trait-candidate-2.rs similarity index 100% rename from tests/ui/traits/next-solver/projection/param-env-trait-candidate-2.rs rename to tests/ui/traits/next-solver/normalize/param-env-trait-candidate-2.rs diff --git a/tests/ui/transmutability/primitives/numbers.current.stderr b/tests/ui/transmutability/primitives/numbers.current.stderr index 009e377af99a..7a80e444149d 100644 --- a/tests/ui/transmutability/primitives/numbers.current.stderr +++ b/tests/ui/transmutability/primitives/numbers.current.stderr @@ -1,11 +1,11 @@ error[E0277]: `i8` cannot be safely transmuted into `i16` - --> $DIR/numbers.rs:65:40 + --> $DIR/numbers.rs:64:40 | LL | assert::is_transmutable::< i8, i16>(); | ^^^ The size of `i8` is smaller than the size of `i16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -14,13 +14,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` - --> $DIR/numbers.rs:66:40 + --> $DIR/numbers.rs:65:40 | LL | assert::is_transmutable::< i8, u16>(); | ^^^ The size of `i8` is smaller than the size of `u16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -29,13 +29,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:67:40 + --> $DIR/numbers.rs:66:40 | LL | assert::is_transmutable::< i8, i32>(); | ^^^ The size of `i8` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -44,13 +44,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:68:40 + --> $DIR/numbers.rs:67:40 | LL | assert::is_transmutable::< i8, f32>(); | ^^^ The size of `i8` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -59,13 +59,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:69:40 + --> $DIR/numbers.rs:68:40 | LL | assert::is_transmutable::< i8, u32>(); | ^^^ The size of `i8` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -74,13 +74,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:70:40 + --> $DIR/numbers.rs:69:40 | LL | assert::is_transmutable::< i8, u64>(); | ^^^ The size of `i8` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -89,13 +89,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:71:40 + --> $DIR/numbers.rs:70:40 | LL | assert::is_transmutable::< i8, i64>(); | ^^^ The size of `i8` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -104,13 +104,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:72:40 + --> $DIR/numbers.rs:71:40 | LL | assert::is_transmutable::< i8, f64>(); | ^^^ The size of `i8` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -119,13 +119,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:73:39 + --> $DIR/numbers.rs:72:39 | LL | assert::is_transmutable::< i8, u128>(); | ^^^^ The size of `i8` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -134,13 +134,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:74:39 + --> $DIR/numbers.rs:73:39 | LL | assert::is_transmutable::< i8, i128>(); | ^^^^ The size of `i8` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -149,13 +149,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` - --> $DIR/numbers.rs:76:40 + --> $DIR/numbers.rs:75:40 | LL | assert::is_transmutable::< u8, i16>(); | ^^^ The size of `u8` is smaller than the size of `i16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -164,13 +164,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` - --> $DIR/numbers.rs:77:40 + --> $DIR/numbers.rs:76:40 | LL | assert::is_transmutable::< u8, u16>(); | ^^^ The size of `u8` is smaller than the size of `u16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -179,13 +179,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:78:40 + --> $DIR/numbers.rs:77:40 | LL | assert::is_transmutable::< u8, i32>(); | ^^^ The size of `u8` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -194,13 +194,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:79:40 + --> $DIR/numbers.rs:78:40 | LL | assert::is_transmutable::< u8, f32>(); | ^^^ The size of `u8` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -209,13 +209,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:80:40 + --> $DIR/numbers.rs:79:40 | LL | assert::is_transmutable::< u8, u32>(); | ^^^ The size of `u8` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -224,13 +224,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:81:40 + --> $DIR/numbers.rs:80:40 | LL | assert::is_transmutable::< u8, u64>(); | ^^^ The size of `u8` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -239,13 +239,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:82:40 + --> $DIR/numbers.rs:81:40 | LL | assert::is_transmutable::< u8, i64>(); | ^^^ The size of `u8` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -254,13 +254,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:83:40 + --> $DIR/numbers.rs:82:40 | LL | assert::is_transmutable::< u8, f64>(); | ^^^ The size of `u8` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -269,13 +269,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:84:39 + --> $DIR/numbers.rs:83:39 | LL | assert::is_transmutable::< u8, u128>(); | ^^^^ The size of `u8` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -284,13 +284,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:85:39 + --> $DIR/numbers.rs:84:39 | LL | assert::is_transmutable::< u8, i128>(); | ^^^^ The size of `u8` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -299,13 +299,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:87:40 + --> $DIR/numbers.rs:86:40 | LL | assert::is_transmutable::< i16, i32>(); | ^^^ The size of `i16` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -314,13 +314,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:88:40 + --> $DIR/numbers.rs:87:40 | LL | assert::is_transmutable::< i16, f32>(); | ^^^ The size of `i16` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -329,13 +329,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:89:40 + --> $DIR/numbers.rs:88:40 | LL | assert::is_transmutable::< i16, u32>(); | ^^^ The size of `i16` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -344,13 +344,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:90:40 + --> $DIR/numbers.rs:89:40 | LL | assert::is_transmutable::< i16, u64>(); | ^^^ The size of `i16` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -359,13 +359,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:91:40 + --> $DIR/numbers.rs:90:40 | LL | assert::is_transmutable::< i16, i64>(); | ^^^ The size of `i16` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -374,13 +374,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:92:40 + --> $DIR/numbers.rs:91:40 | LL | assert::is_transmutable::< i16, f64>(); | ^^^ The size of `i16` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -389,13 +389,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:93:39 + --> $DIR/numbers.rs:92:39 | LL | assert::is_transmutable::< i16, u128>(); | ^^^^ The size of `i16` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -404,13 +404,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:94:39 + --> $DIR/numbers.rs:93:39 | LL | assert::is_transmutable::< i16, i128>(); | ^^^^ The size of `i16` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -419,13 +419,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:96:40 + --> $DIR/numbers.rs:95:40 | LL | assert::is_transmutable::< u16, i32>(); | ^^^ The size of `u16` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -434,13 +434,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:97:40 + --> $DIR/numbers.rs:96:40 | LL | assert::is_transmutable::< u16, f32>(); | ^^^ The size of `u16` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -449,13 +449,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:98:40 + --> $DIR/numbers.rs:97:40 | LL | assert::is_transmutable::< u16, u32>(); | ^^^ The size of `u16` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -464,13 +464,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:99:40 + --> $DIR/numbers.rs:98:40 | LL | assert::is_transmutable::< u16, u64>(); | ^^^ The size of `u16` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -479,13 +479,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:100:40 + --> $DIR/numbers.rs:99:40 | LL | assert::is_transmutable::< u16, i64>(); | ^^^ The size of `u16` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -494,13 +494,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:101:40 + --> $DIR/numbers.rs:100:40 | LL | assert::is_transmutable::< u16, f64>(); | ^^^ The size of `u16` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -509,13 +509,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:102:39 + --> $DIR/numbers.rs:101:39 | LL | assert::is_transmutable::< u16, u128>(); | ^^^^ The size of `u16` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -524,13 +524,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:103:39 + --> $DIR/numbers.rs:102:39 | LL | assert::is_transmutable::< u16, i128>(); | ^^^^ The size of `u16` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -539,13 +539,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:105:40 + --> $DIR/numbers.rs:104:40 | LL | assert::is_transmutable::< i32, u64>(); | ^^^ The size of `i32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -554,13 +554,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:106:40 + --> $DIR/numbers.rs:105:40 | LL | assert::is_transmutable::< i32, i64>(); | ^^^ The size of `i32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -569,13 +569,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:107:40 + --> $DIR/numbers.rs:106:40 | LL | assert::is_transmutable::< i32, f64>(); | ^^^ The size of `i32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -584,13 +584,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:108:39 + --> $DIR/numbers.rs:107:39 | LL | assert::is_transmutable::< i32, u128>(); | ^^^^ The size of `i32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -599,13 +599,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:109:39 + --> $DIR/numbers.rs:108:39 | LL | assert::is_transmutable::< i32, i128>(); | ^^^^ The size of `i32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -614,13 +614,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:111:40 + --> $DIR/numbers.rs:110:40 | LL | assert::is_transmutable::< f32, u64>(); | ^^^ The size of `f32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -629,13 +629,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:112:40 + --> $DIR/numbers.rs:111:40 | LL | assert::is_transmutable::< f32, i64>(); | ^^^ The size of `f32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -644,13 +644,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:113:40 + --> $DIR/numbers.rs:112:40 | LL | assert::is_transmutable::< f32, f64>(); | ^^^ The size of `f32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -659,13 +659,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:114:39 + --> $DIR/numbers.rs:113:39 | LL | assert::is_transmutable::< f32, u128>(); | ^^^^ The size of `f32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -674,13 +674,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:115:39 + --> $DIR/numbers.rs:114:39 | LL | assert::is_transmutable::< f32, i128>(); | ^^^^ The size of `f32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -689,13 +689,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:117:40 + --> $DIR/numbers.rs:116:40 | LL | assert::is_transmutable::< u32, u64>(); | ^^^ The size of `u32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -704,13 +704,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:118:40 + --> $DIR/numbers.rs:117:40 | LL | assert::is_transmutable::< u32, i64>(); | ^^^ The size of `u32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -719,13 +719,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:119:40 + --> $DIR/numbers.rs:118:40 | LL | assert::is_transmutable::< u32, f64>(); | ^^^ The size of `u32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -734,13 +734,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:120:39 + --> $DIR/numbers.rs:119:39 | LL | assert::is_transmutable::< u32, u128>(); | ^^^^ The size of `u32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -749,13 +749,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:121:39 + --> $DIR/numbers.rs:120:39 | LL | assert::is_transmutable::< u32, i128>(); | ^^^^ The size of `u32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -764,13 +764,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:123:39 + --> $DIR/numbers.rs:122:39 | LL | assert::is_transmutable::< u64, u128>(); | ^^^^ The size of `u64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -779,13 +779,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:124:39 + --> $DIR/numbers.rs:123:39 | LL | assert::is_transmutable::< u64, i128>(); | ^^^^ The size of `u64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -794,13 +794,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:126:39 + --> $DIR/numbers.rs:125:39 | LL | assert::is_transmutable::< i64, u128>(); | ^^^^ The size of `i64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -809,13 +809,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:127:39 + --> $DIR/numbers.rs:126:39 | LL | assert::is_transmutable::< i64, i128>(); | ^^^^ The size of `i64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -824,13 +824,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:129:39 + --> $DIR/numbers.rs:128:39 | LL | assert::is_transmutable::< f64, u128>(); | ^^^^ The size of `f64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -839,13 +839,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:130:39 + --> $DIR/numbers.rs:129:39 | LL | assert::is_transmutable::< f64, i128>(); | ^^^^ The size of `f64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function diff --git a/tests/ui/transmutability/primitives/numbers.next.stderr b/tests/ui/transmutability/primitives/numbers.next.stderr index 009e377af99a..7a80e444149d 100644 --- a/tests/ui/transmutability/primitives/numbers.next.stderr +++ b/tests/ui/transmutability/primitives/numbers.next.stderr @@ -1,11 +1,11 @@ error[E0277]: `i8` cannot be safely transmuted into `i16` - --> $DIR/numbers.rs:65:40 + --> $DIR/numbers.rs:64:40 | LL | assert::is_transmutable::< i8, i16>(); | ^^^ The size of `i8` is smaller than the size of `i16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -14,13 +14,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u16` - --> $DIR/numbers.rs:66:40 + --> $DIR/numbers.rs:65:40 | LL | assert::is_transmutable::< i8, u16>(); | ^^^ The size of `i8` is smaller than the size of `u16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -29,13 +29,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:67:40 + --> $DIR/numbers.rs:66:40 | LL | assert::is_transmutable::< i8, i32>(); | ^^^ The size of `i8` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -44,13 +44,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:68:40 + --> $DIR/numbers.rs:67:40 | LL | assert::is_transmutable::< i8, f32>(); | ^^^ The size of `i8` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -59,13 +59,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:69:40 + --> $DIR/numbers.rs:68:40 | LL | assert::is_transmutable::< i8, u32>(); | ^^^ The size of `i8` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -74,13 +74,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:70:40 + --> $DIR/numbers.rs:69:40 | LL | assert::is_transmutable::< i8, u64>(); | ^^^ The size of `i8` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -89,13 +89,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:71:40 + --> $DIR/numbers.rs:70:40 | LL | assert::is_transmutable::< i8, i64>(); | ^^^ The size of `i8` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -104,13 +104,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:72:40 + --> $DIR/numbers.rs:71:40 | LL | assert::is_transmutable::< i8, f64>(); | ^^^ The size of `i8` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -119,13 +119,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:73:39 + --> $DIR/numbers.rs:72:39 | LL | assert::is_transmutable::< i8, u128>(); | ^^^^ The size of `i8` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -134,13 +134,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i8` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:74:39 + --> $DIR/numbers.rs:73:39 | LL | assert::is_transmutable::< i8, i128>(); | ^^^^ The size of `i8` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -149,13 +149,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i16` - --> $DIR/numbers.rs:76:40 + --> $DIR/numbers.rs:75:40 | LL | assert::is_transmutable::< u8, i16>(); | ^^^ The size of `u8` is smaller than the size of `i16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -164,13 +164,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u16` - --> $DIR/numbers.rs:77:40 + --> $DIR/numbers.rs:76:40 | LL | assert::is_transmutable::< u8, u16>(); | ^^^ The size of `u8` is smaller than the size of `u16` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -179,13 +179,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:78:40 + --> $DIR/numbers.rs:77:40 | LL | assert::is_transmutable::< u8, i32>(); | ^^^ The size of `u8` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -194,13 +194,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:79:40 + --> $DIR/numbers.rs:78:40 | LL | assert::is_transmutable::< u8, f32>(); | ^^^ The size of `u8` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -209,13 +209,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:80:40 + --> $DIR/numbers.rs:79:40 | LL | assert::is_transmutable::< u8, u32>(); | ^^^ The size of `u8` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -224,13 +224,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:81:40 + --> $DIR/numbers.rs:80:40 | LL | assert::is_transmutable::< u8, u64>(); | ^^^ The size of `u8` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -239,13 +239,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:82:40 + --> $DIR/numbers.rs:81:40 | LL | assert::is_transmutable::< u8, i64>(); | ^^^ The size of `u8` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -254,13 +254,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:83:40 + --> $DIR/numbers.rs:82:40 | LL | assert::is_transmutable::< u8, f64>(); | ^^^ The size of `u8` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -269,13 +269,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:84:39 + --> $DIR/numbers.rs:83:39 | LL | assert::is_transmutable::< u8, u128>(); | ^^^^ The size of `u8` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -284,13 +284,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u8` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:85:39 + --> $DIR/numbers.rs:84:39 | LL | assert::is_transmutable::< u8, i128>(); | ^^^^ The size of `u8` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -299,13 +299,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:87:40 + --> $DIR/numbers.rs:86:40 | LL | assert::is_transmutable::< i16, i32>(); | ^^^ The size of `i16` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -314,13 +314,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:88:40 + --> $DIR/numbers.rs:87:40 | LL | assert::is_transmutable::< i16, f32>(); | ^^^ The size of `i16` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -329,13 +329,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:89:40 + --> $DIR/numbers.rs:88:40 | LL | assert::is_transmutable::< i16, u32>(); | ^^^ The size of `i16` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -344,13 +344,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:90:40 + --> $DIR/numbers.rs:89:40 | LL | assert::is_transmutable::< i16, u64>(); | ^^^ The size of `i16` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -359,13 +359,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:91:40 + --> $DIR/numbers.rs:90:40 | LL | assert::is_transmutable::< i16, i64>(); | ^^^ The size of `i16` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -374,13 +374,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:92:40 + --> $DIR/numbers.rs:91:40 | LL | assert::is_transmutable::< i16, f64>(); | ^^^ The size of `i16` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -389,13 +389,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:93:39 + --> $DIR/numbers.rs:92:39 | LL | assert::is_transmutable::< i16, u128>(); | ^^^^ The size of `i16` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -404,13 +404,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i16` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:94:39 + --> $DIR/numbers.rs:93:39 | LL | assert::is_transmutable::< i16, i128>(); | ^^^^ The size of `i16` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -419,13 +419,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i32` - --> $DIR/numbers.rs:96:40 + --> $DIR/numbers.rs:95:40 | LL | assert::is_transmutable::< u16, i32>(); | ^^^ The size of `u16` is smaller than the size of `i32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -434,13 +434,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f32` - --> $DIR/numbers.rs:97:40 + --> $DIR/numbers.rs:96:40 | LL | assert::is_transmutable::< u16, f32>(); | ^^^ The size of `u16` is smaller than the size of `f32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -449,13 +449,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u32` - --> $DIR/numbers.rs:98:40 + --> $DIR/numbers.rs:97:40 | LL | assert::is_transmutable::< u16, u32>(); | ^^^ The size of `u16` is smaller than the size of `u32` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -464,13 +464,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:99:40 + --> $DIR/numbers.rs:98:40 | LL | assert::is_transmutable::< u16, u64>(); | ^^^ The size of `u16` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -479,13 +479,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:100:40 + --> $DIR/numbers.rs:99:40 | LL | assert::is_transmutable::< u16, i64>(); | ^^^ The size of `u16` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -494,13 +494,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:101:40 + --> $DIR/numbers.rs:100:40 | LL | assert::is_transmutable::< u16, f64>(); | ^^^ The size of `u16` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -509,13 +509,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:102:39 + --> $DIR/numbers.rs:101:39 | LL | assert::is_transmutable::< u16, u128>(); | ^^^^ The size of `u16` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -524,13 +524,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u16` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:103:39 + --> $DIR/numbers.rs:102:39 | LL | assert::is_transmutable::< u16, i128>(); | ^^^^ The size of `u16` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -539,13 +539,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:105:40 + --> $DIR/numbers.rs:104:40 | LL | assert::is_transmutable::< i32, u64>(); | ^^^ The size of `i32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -554,13 +554,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:106:40 + --> $DIR/numbers.rs:105:40 | LL | assert::is_transmutable::< i32, i64>(); | ^^^ The size of `i32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -569,13 +569,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:107:40 + --> $DIR/numbers.rs:106:40 | LL | assert::is_transmutable::< i32, f64>(); | ^^^ The size of `i32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -584,13 +584,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:108:39 + --> $DIR/numbers.rs:107:39 | LL | assert::is_transmutable::< i32, u128>(); | ^^^^ The size of `i32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -599,13 +599,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:109:39 + --> $DIR/numbers.rs:108:39 | LL | assert::is_transmutable::< i32, i128>(); | ^^^^ The size of `i32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -614,13 +614,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:111:40 + --> $DIR/numbers.rs:110:40 | LL | assert::is_transmutable::< f32, u64>(); | ^^^ The size of `f32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -629,13 +629,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:112:40 + --> $DIR/numbers.rs:111:40 | LL | assert::is_transmutable::< f32, i64>(); | ^^^ The size of `f32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -644,13 +644,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:113:40 + --> $DIR/numbers.rs:112:40 | LL | assert::is_transmutable::< f32, f64>(); | ^^^ The size of `f32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -659,13 +659,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:114:39 + --> $DIR/numbers.rs:113:39 | LL | assert::is_transmutable::< f32, u128>(); | ^^^^ The size of `f32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -674,13 +674,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:115:39 + --> $DIR/numbers.rs:114:39 | LL | assert::is_transmutable::< f32, i128>(); | ^^^^ The size of `f32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -689,13 +689,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u64` - --> $DIR/numbers.rs:117:40 + --> $DIR/numbers.rs:116:40 | LL | assert::is_transmutable::< u32, u64>(); | ^^^ The size of `u32` is smaller than the size of `u64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -704,13 +704,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i64` - --> $DIR/numbers.rs:118:40 + --> $DIR/numbers.rs:117:40 | LL | assert::is_transmutable::< u32, i64>(); | ^^^ The size of `u32` is smaller than the size of `i64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -719,13 +719,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `f64` - --> $DIR/numbers.rs:119:40 + --> $DIR/numbers.rs:118:40 | LL | assert::is_transmutable::< u32, f64>(); | ^^^ The size of `u32` is smaller than the size of `f64` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -734,13 +734,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:120:39 + --> $DIR/numbers.rs:119:39 | LL | assert::is_transmutable::< u32, u128>(); | ^^^^ The size of `u32` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -749,13 +749,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u32` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:121:39 + --> $DIR/numbers.rs:120:39 | LL | assert::is_transmutable::< u32, i128>(); | ^^^^ The size of `u32` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -764,13 +764,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:123:39 + --> $DIR/numbers.rs:122:39 | LL | assert::is_transmutable::< u64, u128>(); | ^^^^ The size of `u64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -779,13 +779,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `u64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:124:39 + --> $DIR/numbers.rs:123:39 | LL | assert::is_transmutable::< u64, i128>(); | ^^^^ The size of `u64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -794,13 +794,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:126:39 + --> $DIR/numbers.rs:125:39 | LL | assert::is_transmutable::< i64, u128>(); | ^^^^ The size of `i64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -809,13 +809,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `i64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:127:39 + --> $DIR/numbers.rs:126:39 | LL | assert::is_transmutable::< i64, i128>(); | ^^^^ The size of `i64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -824,13 +824,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `u128` - --> $DIR/numbers.rs:129:39 + --> $DIR/numbers.rs:128:39 | LL | assert::is_transmutable::< f64, u128>(); | ^^^^ The size of `f64` is smaller than the size of `u128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function @@ -839,13 +839,13 @@ LL | Dst: BikeshedIntrinsicFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` error[E0277]: `f64` cannot be safely transmuted into `i128` - --> $DIR/numbers.rs:130:39 + --> $DIR/numbers.rs:129:39 | LL | assert::is_transmutable::< f64, i128>(); | ^^^^ The size of `f64` is smaller than the size of `i128` | note: required by a bound in `is_transmutable` - --> $DIR/numbers.rs:15:14 + --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() | --------------- required by a bound in this function diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs index 896f5f49f67f..401502474cfb 100644 --- a/tests/ui/transmutability/primitives/numbers.rs +++ b/tests/ui/transmutability/primitives/numbers.rs @@ -5,7 +5,6 @@ #![crate_type = "lib"] #![feature(transmutability)] #![allow(dead_code)] -#![allow(incomplete_features)] mod assert { use std::mem::BikeshedIntrinsicFrom; diff --git a/tests/ui/transmutability/references/reject_extension.rs b/tests/ui/transmutability/references/reject_extension.rs new file mode 100644 index 000000000000..161da5772e87 --- /dev/null +++ b/tests/ui/transmutability/references/reject_extension.rs @@ -0,0 +1,49 @@ +//@ check-fail + +//! Reject extensions behind references. + +#![crate_type = "lib"] +#![feature(transmutability)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable() + where + Dst: BikeshedIntrinsicFrom< + Src, + { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }, + >, + { + } +} + +#[repr(C, packed)] +struct Packed(T); + +fn reject_extension() { + #[repr(C, align(2))] + struct Two(u8); + + #[repr(C, align(4))] + struct Four(u8); + + // These two types differ in the number of trailing padding bytes they have. + type Src = Packed; + type Dst = Packed; + + const _: () = { + use std::mem::size_of; + assert!(size_of::() == 2); + assert!(size_of::() == 4); + }; + + assert::is_transmutable::<&Src, &Dst>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/references/reject_extension.stderr b/tests/ui/transmutability/references/reject_extension.stderr new file mode 100644 index 000000000000..e02ef89c4a03 --- /dev/null +++ b/tests/ui/transmutability/references/reject_extension.stderr @@ -0,0 +1,25 @@ +error[E0277]: `&Packed` cannot be safely transmuted into `&Packed` + --> $DIR/reject_extension.rs:48:37 + | +LL | assert::is_transmutable::<&Src, &Dst>(); + | ^^^^ The referent size of `&Packed` (2 bytes) is smaller than that of `&Packed` (4 bytes) + | +note: required by a bound in `is_transmutable` + --> $DIR/reject_extension.rs:13:14 + | +LL | pub fn is_transmutable() + | --------------- required by a bound in this function +LL | where +LL | Dst: BikeshedIntrinsicFrom< + | ______________^ +LL | | Src, +LL | | { +LL | | Assume { +... | +LL | | }, +LL | | >, + | |_________^ required by this bound in `is_transmutable` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/references/unit-to-u8.stderr b/tests/ui/transmutability/references/unit-to-u8.stderr index e2eb50442caf..7cb45e24e0a4 100644 --- a/tests/ui/transmutability/references/unit-to-u8.stderr +++ b/tests/ui/transmutability/references/unit-to-u8.stderr @@ -1,8 +1,8 @@ -error[E0277]: `Unit` cannot be safely transmuted into `u8` +error[E0277]: `&Unit` cannot be safely transmuted into `&u8` --> $DIR/unit-to-u8.rs:22:52 | LL | assert::is_maybe_transmutable::<&'static Unit, &'static u8>(); - | ^^^^^^^^^^^ The size of `Unit` is smaller than the size of `u8` + | ^^^^^^^^^^^ The referent size of `&Unit` (0 bytes) is smaller than that of `&u8` (1 bytes) | note: required by a bound in `is_maybe_transmutable` --> $DIR/unit-to-u8.rs:9:14 diff --git a/tests/ui/transmutability/unions/boolish.rs b/tests/ui/transmutability/unions/boolish.rs index 0ba59bcaa9f2..c829f83149e3 100644 --- a/tests/ui/transmutability/unions/boolish.rs +++ b/tests/ui/transmutability/unions/boolish.rs @@ -4,7 +4,6 @@ #![feature(transmutability)] #![feature(marker_trait_attr)] #![allow(dead_code)] -#![allow(incomplete_features)] mod assert { use std::mem::{Assume, BikeshedIntrinsicFrom}; diff --git a/tests/ui/type-alias-impl-trait/issue-65384.rs b/tests/ui/type-alias-impl-trait/issue-65384.rs index 9a9b2269f802..44ca5cb94b0f 100644 --- a/tests/ui/type-alias-impl-trait/issue-65384.rs +++ b/tests/ui/type-alias-impl-trait/issue-65384.rs @@ -1,5 +1,4 @@ #![feature(type_alias_impl_trait)] -#![allow(incomplete_features)] trait MyTrait {} diff --git a/tests/ui/type-alias-impl-trait/issue-65384.stderr b/tests/ui/type-alias-impl-trait/issue-65384.stderr index 6accd45bad65..5653ee324be1 100644 --- a/tests/ui/type-alias-impl-trait/issue-65384.stderr +++ b/tests/ui/type-alias-impl-trait/issue-65384.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `MyTrait` for type `()` - --> $DIR/issue-65384.rs:10:1 + --> $DIR/issue-65384.rs:9:1 | LL | impl MyTrait for () {} | ------------------- first implementation here diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr index 3daacacdb4a3..1aaf36223b7f 100644 --- a/tests/ui/type-alias-impl-trait/variance.stderr +++ b/tests/ui/type-alias-impl-trait/variance.stderr @@ -1,69 +1,3 @@ -error: [*, o] - --> $DIR/variance.rs:8:29 - | -LL | type NotCapturedEarly<'a> = impl Sized; - | ^^^^^^^^^^ - -error: [*, o] - --> $DIR/variance.rs:11:26 - | -LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, o, o] - --> $DIR/variance.rs:14:56 - | -LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; - | ^^^^^^^^^^ - -error: [*, o, o] - --> $DIR/variance.rs:18:49 - | -LL | type Captured<'a> = dyn for<'b> Iterator>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, *, o, o, o] - --> $DIR/variance.rs:22:27 - | -LL | type Bar<'a, 'b: 'b, T> = impl Sized; - | ^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:34:32 - | -LL | type ImplicitCapture<'a> = impl Sized; - | ^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:37:42 - | -LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:40:39 - | -LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:45:32 - | -LL | type ImplicitCapture<'a> = impl Sized; - | ^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:48:42 - | -LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, *, o, o] - --> $DIR/variance.rs:51:39 - | -LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type --> $DIR/variance.rs:14:56 | @@ -176,6 +110,72 @@ LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; | = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl +error: [*, o] + --> $DIR/variance.rs:8:29 + | +LL | type NotCapturedEarly<'a> = impl Sized; + | ^^^^^^^^^^ + +error: [*, o] + --> $DIR/variance.rs:11:26 + | +LL | type CapturedEarly<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, o, o] + --> $DIR/variance.rs:14:56 + | +LL | type NotCapturedLate<'a> = dyn for<'b> Iterator; + | ^^^^^^^^^^ + +error: [*, o, o] + --> $DIR/variance.rs:18:49 + | +LL | type Captured<'a> = dyn for<'b> Iterator>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, *, o, o, o] + --> $DIR/variance.rs:22:27 + | +LL | type Bar<'a, 'b: 'b, T> = impl Sized; + | ^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:34:32 + | +LL | type ImplicitCapture<'a> = impl Sized; + | ^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:37:42 + | +LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:40:39 + | +LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:45:32 + | +LL | type ImplicitCapture<'a> = impl Sized; + | ^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:48:42 + | +LL | type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, *, o, o] + --> $DIR/variance.rs:51:39 + | +LL | type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 24 previous errors For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr index b910f668db52..f41574ca3a37 100644 --- a/tests/ui/variance/variance-associated-consts.stderr +++ b/tests/ui/variance/variance-associated-consts.stderr @@ -1,9 +1,3 @@ -error: [o] - --> $DIR/variance-associated-consts.rs:13:1 - | -LL | struct Foo { - | ^^^^^^^^^^^^^^^^^^^^ - error: unconstrained generic constant --> $DIR/variance-associated-consts.rs:14:12 | @@ -12,5 +6,11 @@ LL | field: [u8; ::Const] | = help: try adding a `where` bound using this expression: `where [(); ::Const]:` +error: [o] + --> $DIR/variance-associated-consts.rs:13:1 + | +LL | struct Foo { + | ^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 2 previous errors diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr index 5ac538982aa8..edfc888f6566 100644 --- a/tests/ui/variance/variance-regions-direct.stderr +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -1,3 +1,11 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/variance-regions-direct.rs:52:14 + | +LL | struct Test7<'a> { + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + error: [+, +, +] --> $DIR/variance-regions-direct.rs:9:1 | @@ -40,14 +48,6 @@ error: [-, +, o] LL | enum Test8<'a, 'b, 'c:'b> { | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0392]: lifetime parameter `'a` is never used - --> $DIR/variance-regions-direct.rs:52:14 - | -LL | struct Test7<'a> { - | ^^ unused lifetime parameter - | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` - error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr index b6b943026ebe..901ec0c6a762 100644 --- a/tests/ui/variance/variance-regions-indirect.stderr +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -1,33 +1,3 @@ -error: [-, +, o, *] - --> $DIR/variance-regions-indirect.rs:8:1 - | -LL | enum Base<'a, 'b, 'c:'b, 'd> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, o, +, -] - --> $DIR/variance-regions-indirect.rs:16:1 - | -LL | struct Derived1<'w, 'x:'y, 'y, 'z> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [o, o, *] - --> $DIR/variance-regions-indirect.rs:22:1 - | -LL | struct Derived2<'a, 'b:'a, 'c> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [o, +, *] - --> $DIR/variance-regions-indirect.rs:28:1 - | -LL | struct Derived3<'a:'b, 'b, 'c> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [-, +, o] - --> $DIR/variance-regions-indirect.rs:34:1 - | -LL | struct Derived4<'a, 'b, 'c:'b> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0392]: lifetime parameter `'d` is never used --> $DIR/variance-regions-indirect.rs:8:26 | @@ -60,6 +30,36 @@ LL | struct Derived3<'a:'b, 'b, 'c> { | = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` +error: [-, +, o, *] + --> $DIR/variance-regions-indirect.rs:8:1 + | +LL | enum Base<'a, 'b, 'c:'b, 'd> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, o, +, -] + --> $DIR/variance-regions-indirect.rs:16:1 + | +LL | struct Derived1<'w, 'x:'y, 'y, 'z> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, o, *] + --> $DIR/variance-regions-indirect.rs:22:1 + | +LL | struct Derived2<'a, 'b:'a, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [o, +, *] + --> $DIR/variance-regions-indirect.rs:28:1 + | +LL | struct Derived3<'a:'b, 'b, 'c> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [-, +, o] + --> $DIR/variance-regions-indirect.rs:34:1 + | +LL | struct Derived4<'a, 'b, 'c:'b> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr index 9d106fb11f6a..95ed18c1ad2b 100644 --- a/tests/ui/variance/variance-trait-bounds.stderr +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -1,27 +1,3 @@ -error: [+, +] - --> $DIR/variance-trait-bounds.rs:16:1 - | -LL | struct TestStruct> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, +] - --> $DIR/variance-trait-bounds.rs:21:1 - | -LL | enum TestEnum> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, +] - --> $DIR/variance-trait-bounds.rs:27:1 - | -LL | struct TestContraStruct> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: [*, +] - --> $DIR/variance-trait-bounds.rs:33:1 - | -LL | struct TestBox+Setter> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0392]: type parameter `U` is never used --> $DIR/variance-trait-bounds.rs:21:15 | @@ -49,6 +25,30 @@ LL | struct TestBox+Setter> { = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead +error: [+, +] + --> $DIR/variance-trait-bounds.rs:16:1 + | +LL | struct TestStruct> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:21:1 + | +LL | enum TestEnum> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:27:1 + | +LL | struct TestContraStruct> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [*, +] + --> $DIR/variance-trait-bounds.rs:33:1 + | +LL | struct TestBox+Setter> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0392`. diff --git a/triagebot.toml b/triagebot.toml index 98f31743d4aa..c972dce1a022 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -377,6 +377,25 @@ trigger_files = [ "compiler/rustc_middle/src/traits/solve" ] +[autolabel."PG-exploit-mitigations"] +trigger_files = [ + "compiler/rustc_symbol_mangling/src/typeid", + "src/doc/rustc/src/exploit-mitigations.md", + "src/doc/unstable-book/src/compiler-flags/branch-protection.md", + "src/doc/unstable-book/src/compiler-flags/cf-protection.md", + "src/doc/unstable-book/src/compiler-flags/control-flow-guard.md", + "src/doc/unstable-book/src/compiler-flags/sanitizer.md", + "src/doc/unstable-book/src/language-features/cfg-sanitize.md", + "src/doc/unstable-book/src/language-features/cfi-encoding.md", + "src/doc/unstable-book/src/language-features/no-sanitize.md", + "tests/codegen/sanitizer", + "tests/codegen/split-lto-unit.rs", + "tests/codegen/stack-probes-inline.rs", + "tests/codegen/stack-protector.rs", + "tests/ui/sanitizer", + "tests/ui/stack-protector" +] + [notify-zulip."I-prioritize"] zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts topic = "#{number} {title}" @@ -642,6 +661,51 @@ cc = ["@nnethercote"] message = "Changes to the size of AST and/or HIR nodes." cc = ["@nnethercote"] +[mentions."compiler/rustc_symbol_mangling/src/typeid"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/rustc/src/exploit-mitigations.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/compiler-flags/branch-protection.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/compiler-flags/cf-protection.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/compiler-flags/control-flow-guard.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/compiler-flags/sanitizer.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/language-features/cfg-sanitize.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/language-features/cfi-encoding.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."src/doc/unstable-book/src/language-features/no-sanitize.md"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/codegen/sanitizer"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/codegen/split-lto-unit.rs"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/codegen/stack-probes-inline.rs"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/codegen/stack-protector.rs"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/ui/sanitizer"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + +[mentions."tests/ui/stack-protector"] +cc = ["@rust-lang/project-exploit-mitigations", "@rcvalle"] + [assign] warn_non_default_branch = true contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html" @@ -783,6 +847,11 @@ project-stable-mir = [ "@ouz-a", ] +project-exploit-mitigations = [ + "@cuviper", + "@rcvalle", +] + [assign.owners] "/.github/workflows" = ["infra-ci"] "/Cargo.lock" = ["@Mark-Simulacrum"] @@ -854,3 +923,7 @@ project-stable-mir = [ "/src/tools/tidy" = ["bootstrap"] "/src/tools/x" = ["bootstrap"] "/src/tools/rustdoc-gui-test" = ["bootstrap", "@onur-ozkan"] + +# Enable tracking of PR review assignment +# Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment-tracking.html +[pr-tracking]