diff options
96 files changed, 717 insertions, 1083 deletions
diff --git a/Cargo.lock b/Cargo.lock index f08a95380c4..20b715e59a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1997,7 +1997,7 @@ dependencies = [ "anyhow", "clap", "fs-err", - "rustc-hash 2.1.0", + "rustc-hash 2.1.1", "rustdoc-json-types", "serde", "serde_json", @@ -3188,7 +3188,7 @@ dependencies = [ "proc-macro2", "quote", "rinja_parser", - "rustc-hash 2.1.0", + "rustc-hash 2.1.1", "serde", "syn 2.0.96", ] @@ -3252,9 +3252,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc-hash" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc-main" @@ -3654,7 +3654,7 @@ dependencies = [ "memmap2", "parking_lot", "portable-atomic", - "rustc-hash 2.1.0", + "rustc-hash 2.1.1", "rustc-rayon", "rustc-stable-hash", "rustc_arena", @@ -4362,7 +4362,7 @@ dependencies = [ name = "rustc_pattern_analysis" version = "0.0.0" dependencies = [ - "rustc-hash 2.1.0", + "rustc-hash 2.1.1", "rustc_abi", "rustc_apfloat", "rustc_arena", @@ -4757,7 +4757,7 @@ name = "rustdoc-json-types" version = "0.1.0" dependencies = [ "bincode", - "rustc-hash 2.1.0", + "rustc-hash 2.1.1", "serde", "serde_json", ] @@ -5408,7 +5408,7 @@ dependencies = [ "ignore", "miropt-test-tools", "regex", - "rustc-hash 2.1.0", + "rustc-hash 2.1.1", "semver", "serde", "similar", diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index f96c9fe8e32..1b91c33742d 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -112,7 +112,8 @@ ast_lowering_invalid_register = invalid register `{$reg}`: {$error} ast_lowering_invalid_register_class = - invalid register class `{$reg_class}`: {$error} + invalid register class `{$reg_class}`: unknown register class + .note = the following register classes are supported on this target: {$supported_register_classes} ast_lowering_match_arm_with_no_body = `match` arm with no body diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 2f1f1269ece..96c230ec243 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -152,11 +152,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { InlineAsmRegOrRegClass::RegClass(reg_class) => { asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch { asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else( - |error| { + |supported_register_classes| { + let mut register_classes = + format!("`{}`", supported_register_classes[0]); + for m in &supported_register_classes[1..] { + let _ = write!(register_classes, ", `{m}`"); + } self.dcx().emit_err(InvalidRegisterClass { op_span: *op_sp, reg_class, - error, + supported_register_classes: register_classes, }); asm::InlineAsmRegClass::Err }, diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index 9f69387b7b7..f31e2db051d 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -197,12 +197,13 @@ pub(crate) struct InvalidRegister<'a> { } #[derive(Diagnostic)] +#[note] #[diag(ast_lowering_invalid_register_class)] -pub(crate) struct InvalidRegisterClass<'a> { +pub(crate) struct InvalidRegisterClass { #[primary_span] pub op_span: Span, pub reg_class: Symbol, - pub error: &'a str, + pub supported_register_classes: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 923fd65dcca..af53c7ec215 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -379,16 +379,16 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } - /// Create an `ExprKind::Ret` that is preceded by a call to check contract ensures clause. + /// Create an `ExprKind::Ret` that is optionally wrapped by a call to check + /// a contract ensures clause, if it exists. fn checked_return(&mut self, opt_expr: Option<&'hir hir::Expr<'hir>>) -> hir::ExprKind<'hir> { - let checked_ret = if let Some(Some((span, fresh_ident))) = - self.contract.as_ref().map(|c| c.ensures.as_ref().map(|e| (e.expr.span, e.fresh_ident))) - { - let expr = opt_expr.unwrap_or_else(|| self.expr_unit(span)); - Some(self.inject_ensures_check(expr, span, fresh_ident.0, fresh_ident.2)) - } else { - opt_expr - }; + let checked_ret = + if let Some((check_span, check_ident, check_hir_id)) = self.contract_ensures { + let expr = opt_expr.unwrap_or_else(|| self.expr_unit(check_span)); + Some(self.inject_ensures_check(expr, check_span, check_ident, check_hir_id)) + } else { + opt_expr + }; hir::ExprKind::Ret(checked_ret) } @@ -1090,7 +1090,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } else { None }; - let body_id = this.lower_fn_body(decl, |this| { + // FIXME(contracts): Support contracts on closures? + let body_id = this.lower_fn_body(decl, None, |this| { this.coroutine_kind = coroutine_kind; let e = this.lower_expr_mut(body); coroutine_kind = this.coroutine_kind; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 75b08e16cdb..85642c8ccb5 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -211,36 +211,6 @@ impl<'hir> LoweringContext<'_, 'hir> { .. }) => { self.with_new_scopes(*fn_sig_span, |this| { - assert!(this.contract.is_none()); - if let Some(contract) = contract { - let requires = contract.requires.clone(); - let ensures = contract.ensures.clone(); - let ensures = ensures.map(|ens| { - // FIXME: this needs to be a fresh (or illegal) identifier to prevent - // accidental capture of a parameter or global variable. - let checker_ident: Ident = - Ident::from_str_and_span("__ensures_checker", ens.span); - let (checker_pat, checker_hir_id) = this.pat_ident_binding_mode_mut( - ens.span, - checker_ident, - hir::BindingMode::NONE, - ); - - crate::FnContractLoweringEnsures { - expr: ens, - fresh_ident: (checker_ident, checker_pat, checker_hir_id), - } - }); - - // Note: `with_new_scopes` will reinstall the outer - // item's contract (if any) after its callback finishes. - this.contract.replace(crate::FnContractLoweringInfo { - span, - requires, - ensures, - }); - } - // Note: we don't need to change the return type from `T` to // `impl Future<Output = T>` here because lower_body // only cares about the input argument patterns in the function @@ -254,6 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> { coroutine_kind, body.as_deref(), attrs, + contract.as_deref(), ); let itctx = ImplTraitContext::Universal; @@ -803,6 +774,8 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, kind, expr.is_some()) } AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => { + // FIXME(contracts): Deny contract here since it won't apply to + // any impl method or callees. let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig( generics, @@ -814,7 +787,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } - AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => { + AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), contract, .. }) => { let body_id = self.lower_maybe_coroutine_body( sig.span, i.span, @@ -823,6 +796,7 @@ impl<'hir> LoweringContext<'_, 'hir> { sig.header.coroutine_kind, Some(body), attrs, + contract.as_deref(), ); let (generics, sig) = self.lower_method_sig( generics, @@ -931,7 +905,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ImplItemKind::Const(ty, body) }, ), - AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => { + AssocItemKind::Fn(box Fn { sig, generics, body, contract, .. }) => { let body_id = self.lower_maybe_coroutine_body( sig.span, i.span, @@ -940,6 +914,7 @@ impl<'hir> LoweringContext<'_, 'hir> { sig.header.coroutine_kind, body.as_deref(), attrs, + contract.as_deref(), ); let (generics, sig) = self.lower_method_sig( generics, @@ -1088,72 +1063,89 @@ impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_fn_body( &mut self, decl: &FnDecl, + contract: Option<&FnContract>, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::BodyId { self.lower_body(|this| { let params = this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x))); - let result = body(this); - - let opt_contract = this.contract.take(); + // Optionally lower the fn contract, which turns: + // // { body } - // ==> - // { contract_requires(PRECOND); { body } } - let Some(contract) = opt_contract else { return (params, result) }; - let result_ref = this.arena.alloc(result); - let lit_unit = |this: &mut LoweringContext<'_, 'hir>| { - this.expr(contract.span, hir::ExprKind::Tup(&[])) - }; - - let precond: hir::Stmt<'hir> = if let Some(req) = contract.requires { - let lowered_req = this.lower_expr_mut(&req); - let precond = this.expr_call_lang_item_fn_mut( - req.span, - hir::LangItem::ContractCheckRequires, - &*arena_vec![this; lowered_req], - ); - this.stmt_expr(req.span, precond) - } else { - let u = lit_unit(this); - this.stmt_expr(contract.span, u) - }; - - let (postcond_checker, result) = if let Some(ens) = contract.ensures { - let crate::FnContractLoweringEnsures { expr: ens, fresh_ident } = ens; - let lowered_ens: hir::Expr<'hir> = this.lower_expr_mut(&ens); - let postcond_checker = this.expr_call_lang_item_fn( - ens.span, - hir::LangItem::ContractBuildCheckEnsures, - &*arena_vec![this; lowered_ens], - ); - let checker_binding_pat = fresh_ident.1; - ( - this.stmt_let_pat( + // + // into: + // + // { contract_requires(PRECOND); let __postcond = |ret_val| POSTCOND; postcond({ body }) } + if let Some(contract) = contract { + let precond = if let Some(req) = &contract.requires { + // Lower the precondition check intrinsic. + let lowered_req = this.lower_expr_mut(&req); + let precond = this.expr_call_lang_item_fn_mut( + req.span, + hir::LangItem::ContractCheckRequires, + &*arena_vec![this; lowered_req], + ); + Some(this.stmt_expr(req.span, precond)) + } else { + None + }; + let (postcond, body) = if let Some(ens) = &contract.ensures { + let ens_span = this.lower_span(ens.span); + // Set up the postcondition `let` statement. + let check_ident: Ident = + Ident::from_str_and_span("__ensures_checker", ens_span); + let (checker_pat, check_hir_id) = this.pat_ident_binding_mode_mut( + ens_span, + check_ident, + hir::BindingMode::NONE, + ); + let lowered_ens = this.lower_expr_mut(&ens); + let postcond_checker = this.expr_call_lang_item_fn( + ens_span, + hir::LangItem::ContractBuildCheckEnsures, + &*arena_vec![this; lowered_ens], + ); + let postcond = this.stmt_let_pat( None, - ens.span, + ens_span, Some(postcond_checker), - this.arena.alloc(checker_binding_pat), + this.arena.alloc(checker_pat), hir::LocalSource::Contract, - ), - this.inject_ensures_check(result_ref, ens.span, fresh_ident.0, fresh_ident.2), - ) - } else { - let u = lit_unit(this); - (this.stmt_expr(contract.span, u), &*result_ref) - }; + ); - let block = this.block_all( - contract.span, - arena_vec![this; precond, postcond_checker], - Some(result), - ); - (params, this.expr_block(block)) + // Install contract_ensures so we will intercept `return` statements, + // then lower the body. + this.contract_ensures = Some((ens_span, check_ident, check_hir_id)); + let body = this.arena.alloc(body(this)); + + // Finally, inject an ensures check on the implicit return of the body. + let body = this.inject_ensures_check(body, ens_span, check_ident, check_hir_id); + (Some(postcond), body) + } else { + let body = &*this.arena.alloc(body(this)); + (None, body) + }; + // Flatten the body into precond, then postcond, then wrapped body. + let wrapped_body = this.block_all( + body.span, + this.arena.alloc_from_iter([precond, postcond].into_iter().flatten()), + Some(body), + ); + (params, this.expr_block(wrapped_body)) + } else { + (params, body(this)) + } }) } - fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId { - self.lower_fn_body(decl, |this| this.lower_block_expr(body)) + fn lower_fn_body_block( + &mut self, + decl: &FnDecl, + body: &Block, + contract: Option<&FnContract>, + ) -> hir::BodyId { + self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body)) } pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId { @@ -1179,12 +1171,13 @@ impl<'hir> LoweringContext<'_, 'hir> { coroutine_kind: Option<CoroutineKind>, body: Option<&Block>, attrs: &'hir [hir::Attribute], + contract: Option<&FnContract>, ) -> hir::BodyId { let Some(body) = body else { // Functions without a body are an error, except if this is an intrinsic. For those we // create a fake body so that the entire rest of the compiler doesn't have to deal with // this as a special case. - return self.lower_fn_body(decl, |this| { + return self.lower_fn_body(decl, contract, |this| { if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) { let span = this.lower_span(span); let empty_block = hir::Block { @@ -1209,8 +1202,9 @@ impl<'hir> LoweringContext<'_, 'hir> { }; let Some(coroutine_kind) = coroutine_kind else { // Typical case: not a coroutine. - return self.lower_fn_body_block(decl, body); + return self.lower_fn_body_block(decl, body, contract); }; + // FIXME(contracts): Support contracts on async fn. self.lower_body(|this| { let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments( decl, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3fecb9e9c7e..facc9414b20 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -88,19 +88,6 @@ pub mod stability; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } -#[derive(Debug, Clone)] -struct FnContractLoweringInfo<'hir> { - pub span: Span, - pub requires: Option<ast::ptr::P<ast::Expr>>, - pub ensures: Option<FnContractLoweringEnsures<'hir>>, -} - -#[derive(Debug, Clone)] -struct FnContractLoweringEnsures<'hir> { - expr: ast::ptr::P<ast::Expr>, - fresh_ident: (Ident, hir::Pat<'hir>, HirId), -} - struct LoweringContext<'a, 'hir> { tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering, @@ -115,7 +102,7 @@ struct LoweringContext<'a, 'hir> { /// Collect items that were created by lowering the current owner. children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>, - contract: Option<FnContractLoweringInfo<'hir>>, + contract_ensures: Option<(Span, Ident, HirId)>, coroutine_kind: Option<hir::CoroutineKind>, @@ -165,7 +152,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bodies: Vec::new(), attrs: SortedMap::default(), children: Vec::default(), - contract: None, + contract_ensures: None, current_hir_id_owner: hir::CRATE_OWNER_ID, item_local_id_counter: hir::ItemLocalId::ZERO, ident_and_label_to_local_id: Default::default(), @@ -852,7 +839,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; - let old_contract = self.contract.take(); + let old_contract = self.contract_ensures.take(); let catch_scope = self.catch_scope.take(); let loop_scope = self.loop_scope.take(); @@ -860,7 +847,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.catch_scope = catch_scope; self.loop_scope = loop_scope; - self.contract = old_contract; + self.contract_ensures = old_contract; self.is_in_loop_condition = was_in_loop_condition; diff --git a/compiler/rustc_builtin_macros/src/contracts.rs b/compiler/rustc_builtin_macros/src/contracts.rs index 85a30f7bdc9..6a24af361fe 100644 --- a/compiler/rustc_builtin_macros/src/contracts.rs +++ b/compiler/rustc_builtin_macros/src/contracts.rs @@ -1,11 +1,9 @@ -#![allow(unused_imports, unused_variables)] - use rustc_ast::token; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_errors::ErrorGuaranteed; use rustc_expand::base::{AttrProcMacro, ExtCtxt}; use rustc_span::Span; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; +use rustc_span::symbol::{Ident, Symbol, kw}; pub(crate) struct ExpandRequires; @@ -121,23 +119,19 @@ fn expand_contract_clause( } } - // Record the span as a contract attribute expansion. - // This is used later to stop users from using the extended syntax directly - // which is gated via `contracts_internals`. - ecx.psess().contract_attribute_spans.push(attr_span); - Ok(new_tts) } fn expand_requires_tts( - _ecx: &mut ExtCtxt<'_>, + ecx: &mut ExtCtxt<'_>, attr_span: Span, annotation: TokenStream, annotated: TokenStream, ) -> Result<TokenStream, ErrorGuaranteed> { - expand_contract_clause(_ecx, attr_span, annotated, |new_tts| { + let feature_span = ecx.with_def_site_ctxt(attr_span); + expand_contract_clause(ecx, attr_span, annotated, |new_tts| { new_tts.push_tree(TokenTree::Token( - token::Token::from_ast_ident(Ident::new(kw::ContractRequires, attr_span)), + token::Token::from_ast_ident(Ident::new(kw::ContractRequires, feature_span)), Spacing::Joint, )); new_tts.push_tree(TokenTree::Token( @@ -155,14 +149,15 @@ fn expand_requires_tts( } fn expand_ensures_tts( - _ecx: &mut ExtCtxt<'_>, + ecx: &mut ExtCtxt<'_>, attr_span: Span, annotation: TokenStream, annotated: TokenStream, ) -> Result<TokenStream, ErrorGuaranteed> { - expand_contract_clause(_ecx, attr_span, annotated, |new_tts| { + let feature_span = ecx.with_def_site_ctxt(attr_span); + expand_contract_clause(ecx, attr_span, annotated, |new_tts| { new_tts.push_tree(TokenTree::Token( - token::Token::from_ast_ident(Ident::new(kw::ContractEnsures, attr_span)), + token::Token::from_ast_ident(Ident::new(kw::ContractEnsures, feature_span)), Spacing::Joint, )); new_tts.push_tree(TokenTree::Delimited( diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 4a1db8d662a..f3552d9b12f 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -400,7 +400,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { conv: Conv::C, can_unwind: false, }; - fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }).unwrap(); + fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 685b2f37c9c..13846c8ab4b 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -664,7 +664,7 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } impl llvm::CallConv { - pub fn from_conv(conv: Conv, arch: &str) -> Self { + pub(crate) fn from_conv(conv: Conv, arch: &str) -> Self { match conv { Conv::C | Conv::Rust diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 149ded28356..66723cbf882 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -81,13 +81,13 @@ pub(crate) unsafe fn codegen( llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); let val = tcx.sess.opts.unstable_opts.oom.should_panic(); let llval = llvm::LLVMConstInt(i8, val as u64, False); - llvm::LLVMSetInitializer(ll_g, llval); + llvm::set_initializer(ll_g, llval); let name = NO_ALLOC_SHIM_IS_UNSTABLE; let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8); llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); let llval = llvm::LLVMConstInt(i8, 0, False); - llvm::LLVMSetInitializer(ll_g, llval); + llvm::set_initializer(ll_g, llval); } if tcx.sess.opts.debuginfo != DebugInfo::None { diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 33a956e552f..93553f3f364 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -11,7 +11,7 @@ use rustc_codegen_ssa::back::archive::{ use rustc_session::Session; use crate::llvm::archive_ro::{ArchiveRO, Child}; -use crate::llvm::{self, ArchiveKind}; +use crate::llvm::{self, ArchiveKind, last_error}; /// Helper for adding many files to an archive. #[must_use = "must call build() to finish building the archive"] @@ -169,6 +169,8 @@ impl<'a> LlvmArchiveBuilder<'a> { .unwrap_or_else(|kind| self.sess.dcx().emit_fatal(UnknownArchiveKind { kind })); let mut additions = mem::take(&mut self.additions); + // Values in the `members` list below will contain pointers to the strings allocated here. + // So they need to get dropped after all elements of `members` get freed. let mut strings = Vec::new(); let mut members = Vec::new(); @@ -229,12 +231,7 @@ impl<'a> LlvmArchiveBuilder<'a> { self.sess.target.arch == "arm64ec", ); let ret = if r.into_result().is_err() { - let err = llvm::LLVMRustGetLastError(); - let msg = if err.is_null() { - "failed to write archive".into() - } else { - String::from_utf8_lossy(CStr::from_ptr(err).to_bytes()) - }; + let msg = last_error().unwrap_or_else(|| "failed to write archive".into()); Err(io::Error::new(io::ErrorKind::Other, msg)) } else { Ok(!members.is_empty()) diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 8bad437eeb7..7262fce4911 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -642,7 +642,7 @@ unsafe impl Send for ModuleBuffer {} unsafe impl Sync for ModuleBuffer {} impl ModuleBuffer { - pub fn new(m: &llvm::Module) -> ModuleBuffer { + pub(crate) fn new(m: &llvm::Module) -> ModuleBuffer { ModuleBuffer(unsafe { llvm::LLVMRustModuleBufferCreate(m) }) } } @@ -684,7 +684,7 @@ unsafe impl Send for ThinBuffer {} unsafe impl Sync for ThinBuffer {} impl ThinBuffer { - pub fn new(m: &llvm::Module, is_thin: bool, emit_summary: bool) -> ThinBuffer { + pub(crate) fn new(m: &llvm::Module, is_thin: bool, emit_summary: bool) -> ThinBuffer { unsafe { let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin, emit_summary); ThinBuffer(buffer) diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs index 4cbd49aa44d..f075f332462 100644 --- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs +++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs @@ -17,7 +17,7 @@ pub struct OwnedTargetMachine { } impl OwnedTargetMachine { - pub fn new( + pub(crate) fn new( triple: &CStr, cpu: &CStr, features: &CStr, diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index ae4c4d5876e..58933a77e53 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -40,7 +40,7 @@ use crate::errors::{ WithLlvmError, WriteBytecode, }; use crate::llvm::diagnostic::OptimizationDiagnosticKind::*; -use crate::llvm::{self, DiagnosticInfo, PassManager}; +use crate::llvm::{self, DiagnosticInfo}; use crate::type_::Type; use crate::{LlvmCodegenBackend, ModuleLlvm, base, common, llvm_util}; @@ -54,7 +54,7 @@ pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> Fatal fn write_output_file<'ll>( dcx: DiagCtxtHandle<'_>, target: &'ll llvm::TargetMachine, - pm: &llvm::PassManager<'ll>, + no_builtins: bool, m: &'ll llvm::Module, output: &Path, dwo_output: Option<&Path>, @@ -63,16 +63,19 @@ fn write_output_file<'ll>( verify_llvm_ir: bool, ) -> Result<(), FatalError> { debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output); - unsafe { - let output_c = path_to_c_string(output); - let dwo_output_c; - let dwo_output_ptr = if let Some(dwo_output) = dwo_output { - dwo_output_c = path_to_c_string(dwo_output); - dwo_output_c.as_ptr() - } else { - std::ptr::null() - }; - let result = llvm::LLVMRustWriteOutputFile( + let output_c = path_to_c_string(output); + let dwo_output_c; + let dwo_output_ptr = if let Some(dwo_output) = dwo_output { + dwo_output_c = path_to_c_string(dwo_output); + dwo_output_c.as_ptr() + } else { + std::ptr::null() + }; + let result = unsafe { + let pm = llvm::LLVMCreatePassManager(); + llvm::LLVMAddAnalysisPasses(target, pm); + llvm::LLVMRustAddLibraryInfo(pm, m, no_builtins); + llvm::LLVMRustWriteOutputFile( target, pm, m, @@ -80,22 +83,22 @@ fn write_output_file<'ll>( dwo_output_ptr, file_type, verify_llvm_ir, - ); + ) + }; - // Record artifact sizes for self-profiling - if result == llvm::LLVMRustResult::Success { - let artifact_kind = match file_type { - llvm::FileType::ObjectFile => "object_file", - llvm::FileType::AssemblyFile => "assembly_file", - }; - record_artifact_size(self_profiler_ref, artifact_kind, output); - if let Some(dwo_file) = dwo_output { - record_artifact_size(self_profiler_ref, "dwo_file", dwo_file); - } + // Record artifact sizes for self-profiling + if result == llvm::LLVMRustResult::Success { + let artifact_kind = match file_type { + llvm::FileType::ObjectFile => "object_file", + llvm::FileType::AssemblyFile => "assembly_file", + }; + record_artifact_size(self_profiler_ref, artifact_kind, output); + if let Some(dwo_file) = dwo_output { + record_artifact_size(self_profiler_ref, "dwo_file", dwo_file); } - - result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output })) } + + result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output })) } pub(crate) fn create_informational_target_machine( @@ -325,13 +328,17 @@ pub(crate) fn save_temp_bitcode( if !cgcx.save_temps { return; } + let ext = format!("{name}.bc"); + let cgu = Some(&module.name[..]); + let path = cgcx.output_filenames.temp_path_ext(&ext, cgu); + write_bitcode_to_file(module, &path) +} + +fn write_bitcode_to_file(module: &ModuleCodegen<ModuleLlvm>, path: &Path) { unsafe { - let ext = format!("{name}.bc"); - let cgu = Some(&module.name[..]); - let path = cgcx.output_filenames.temp_path_ext(&ext, cgu); - let cstr = path_to_c_string(&path); + let path = path_to_c_string(&path); let llmod = module.module_llvm.llmod(); - llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr()); + llvm::LLVMWriteBitcodeToFile(llmod, path.as_ptr()); } } @@ -676,7 +683,6 @@ pub(crate) unsafe fn optimize( ) -> Result<(), FatalError> { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name); - let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt); @@ -685,8 +691,7 @@ pub(crate) unsafe fn optimize( if config.emit_no_opt_bc { let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); - let out = path_to_c_string(&out); - unsafe { llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()) }; + write_bitcode_to_file(module, &out) } // FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts @@ -755,31 +760,6 @@ pub(crate) unsafe fn codegen( create_msvc_imps(cgcx, llcx, llmod); } - // A codegen-specific pass manager is used to generate object - // files for an LLVM module. - // - // Apparently each of these pass managers is a one-shot kind of - // thing, so we create a new one for each type of output. The - // pass manager passed to the closure should be ensured to not - // escape the closure itself, and the manager should only be - // used once. - unsafe fn with_codegen<'ll, F, R>( - tm: &'ll llvm::TargetMachine, - llmod: &'ll llvm::Module, - no_builtins: bool, - f: F, - ) -> R - where - F: FnOnce(&'ll mut PassManager<'ll>) -> R, - { - unsafe { - let cpm = llvm::LLVMCreatePassManager(); - llvm::LLVMAddAnalysisPasses(tm, cpm); - llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); - f(cpm) - } - } - // Note that if object files are just LLVM bitcode we write bitcode, // copy it to the .o file, and delete the bitcode if it wasn't // otherwise requested. @@ -898,21 +878,17 @@ pub(crate) unsafe fn codegen( } else { llmod }; - unsafe { - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file( - dcx, - tm, - cpm, - llmod, - &path, - None, - llvm::FileType::AssemblyFile, - &cgcx.prof, - config.verify_llvm_ir, - ) - })?; - } + write_output_file( + dcx, + tm, + config.no_builtins, + llmod, + &path, + None, + llvm::FileType::AssemblyFile, + &cgcx.prof, + config.verify_llvm_ir, + )?; } match config.emit_obj { @@ -936,21 +912,17 @@ pub(crate) unsafe fn codegen( (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()), }; - unsafe { - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file( - dcx, - tm, - cpm, - llmod, - &obj_out, - dwo_out, - llvm::FileType::ObjectFile, - &cgcx.prof, - config.verify_llvm_ir, - ) - })?; - } + write_output_file( + dcx, + tm, + config.no_builtins, + llmod, + &obj_out, + dwo_out, + llvm::FileType::ObjectFile, + &cgcx.prof, + config.verify_llvm_ir, + )?; } EmitObj::Bitcode => { @@ -1077,24 +1049,18 @@ unsafe fn embed_bitcode( { // We don't need custom section flags, create LLVM globals. let llconst = common::bytes_in_context(llcx, bitcode); - let llglobal = llvm::LLVMAddGlobal( - llmod, - common::val_ty(llconst), - c"rustc.embedded.module".as_ptr(), - ); - llvm::LLVMSetInitializer(llglobal, llconst); + let llglobal = + llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module"); + llvm::set_initializer(llglobal, llconst); llvm::set_section(llglobal, bitcode_section_name(cgcx)); llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetGlobalConstant(llglobal, llvm::True); let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); - let llglobal = llvm::LLVMAddGlobal( - llmod, - common::val_ty(llconst), - c"rustc.embedded.cmdline".as_ptr(), - ); - llvm::LLVMSetInitializer(llglobal, llconst); + let llglobal = + llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline"); + llvm::set_initializer(llglobal, llconst); let section = if cgcx.target_is_like_osx { c"__LLVM,__cmdline" } else if cgcx.target_is_like_aix { @@ -1134,31 +1100,29 @@ fn create_msvc_imps( // underscores added in front). let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" }; - unsafe { - let ptr_ty = Type::ptr_llcx(llcx); - let globals = base::iter_globals(llmod) - .filter(|&val| { - llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage - && llvm::LLVMIsDeclaration(val) == 0 - }) - .filter_map(|val| { - // Exclude some symbols that we know are not Rust symbols. - let name = llvm::get_value_name(val); - if ignored(name) { None } else { Some((val, name)) } - }) - .map(move |(val, name)| { - let mut imp_name = prefix.as_bytes().to_vec(); - imp_name.extend(name); - let imp_name = CString::new(imp_name).unwrap(); - (imp_name, val) - }) - .collect::<Vec<_>>(); + let ptr_ty = Type::ptr_llcx(llcx); + let globals = base::iter_globals(llmod) + .filter(|&val| { + llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage && !llvm::is_declaration(val) + }) + .filter_map(|val| { + // Exclude some symbols that we know are not Rust symbols. + let name = llvm::get_value_name(val); + if ignored(name) { None } else { Some((val, name)) } + }) + .map(move |(val, name)| { + let mut imp_name = prefix.as_bytes().to_vec(); + imp_name.extend(name); + let imp_name = CString::new(imp_name).unwrap(); + (imp_name, val) + }) + .collect::<Vec<_>>(); - for (imp_name, val) in globals { - let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr()); - llvm::LLVMSetInitializer(imp, val); - llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage); - } + for (imp_name, val) in globals { + let imp = llvm::add_global(llmod, ptr_ty, &imp_name); + + llvm::set_initializer(imp, val); + llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage); } // Use this function to exclude certain symbols from `__imp` generation. diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 8c94a46ebf3..78b3a7f8541 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -219,8 +219,8 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| { bug!("symbol `{}` is already defined", sym); }); + llvm::set_initializer(g, sc); unsafe { - llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetGlobalConstant(g, True); llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global); } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index c6855dd42e5..4a5491ec7a1 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -191,7 +191,7 @@ fn check_and_apply_linkage<'ll, 'tcx>( }) }); llvm::set_linkage(g2, llvm::Linkage::InternalLinkage); - unsafe { llvm::LLVMSetInitializer(g2, g1) }; + llvm::set_initializer(g2, g1); g2 } else if cx.tcx.sess.target.arch == "x86" && common::is_mingw_gnu_toolchain(&cx.tcx.sess.target) @@ -235,7 +235,7 @@ impl<'ll> CodegenCx<'ll, '_> { } _ => self.define_private_global(self.val_ty(cv)), }; - unsafe { llvm::LLVMSetInitializer(gv, cv) }; + llvm::set_initializer(gv, cv); set_global_alignment(self, gv, align); llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global); gv @@ -458,7 +458,7 @@ impl<'ll> CodegenCx<'ll, '_> { new_g }; set_global_alignment(self, g, alloc.align); - llvm::LLVMSetInitializer(g, v); + llvm::set_initializer(g, v); if self.should_assume_dso_local(g, true) { llvm::LLVMRustSetDSOLocal(g, true); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index ba4fd75fb94..7fe527a4c07 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -616,12 +616,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) { let array = self.const_array(self.type_ptr(), values); - unsafe { - let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); - llvm::LLVMSetInitializer(g, array); - llvm::set_linkage(g, llvm::Linkage::AppendingLinkage); - llvm::set_section(g, c"llvm.metadata"); - } + let g = llvm::add_global(self.llmod, self.val_ty(array), name); + llvm::set_initializer(g, array); + llvm::set_linkage(g, llvm::Linkage::AppendingLinkage); + llvm::set_section(g, c"llvm.metadata"); } } impl<'ll> SimpleCx<'ll> { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 2c9f1cda13a..54c5d445f66 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -73,7 +73,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>( .define_global(section_var_name, llvm_type) .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name)); llvm::set_section(section_var, c".debug_gdb_scripts"); - llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); + llvm::set_initializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage); diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index bdc83267cca..cebceef1b93 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -235,7 +235,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// name. pub(crate) fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { self.get_declared_value(name).and_then(|val| { - let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 }; + let declaration = llvm::is_declaration(val); if !declaration { Some(val) } else { None } }) } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 3200c94d977..8b976885904 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -824,7 +824,7 @@ fn codegen_msvc_try<'ll>( if bx.cx.tcx.sess.target.supports_comdat() { llvm::SetUniqueComdat(bx.llmod, tydesc); } - unsafe { llvm::LLVMSetInitializer(tydesc, type_info) }; + llvm::set_initializer(tydesc, type_info); // The flag value of 8 indicates that we are catching the exception by // reference instead of by value. We can't use catch by value because diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index f0d04b2b644..bcb1cc72b56 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -30,7 +30,7 @@ use std::mem::ManuallyDrop; use back::owned_target_machine::OwnedTargetMachine; use back::write::{create_informational_target_machine, create_target_machine}; use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig}; -pub use llvm_util::target_features_cfg; +pub(crate) use llvm_util::target_features_cfg; use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::expand::autodiff_attrs::AutoDiffItem; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4d6a76b23ea..441d144ce50 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2359,7 +2359,7 @@ unsafe extern "C" { ); pub fn LLVMRustWriteOutputFile<'a>( T: &'a TargetMachine, - PM: &PassManager<'a>, + PM: *mut PassManager<'a>, M: &'a Module, Output: *const c_char, DwoOutput: *const c_char, diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 707aeba22cc..7becba4ccd4 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -241,6 +241,10 @@ pub fn set_linkage(llglobal: &Value, linkage: Linkage) { } } +pub fn is_declaration(llglobal: &Value) -> bool { + unsafe { LLVMIsDeclaration(llglobal) == ffi::True } +} + pub fn get_visibility(llglobal: &Value) -> Visibility { unsafe { LLVMGetVisibility(llglobal) }.to_rust() } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 53611c746a7..b4b5d6a5b19 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -271,6 +271,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea ("aarch64", "fp16") => Some(LLVMFeature::new("fullfp16")), // Filter out features that are not supported by the current LLVM version ("aarch64", "fpmr") if get_version().0 != 18 => None, + ("arm", "fp16") => Some(LLVMFeature::new("fullfp16")), // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single // feature called `fast-unaligned-access`. In LLVM 19, it was split back out. ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => { @@ -303,7 +304,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea /// Must express features in the way Rust understands them. /// /// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen. -pub fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { +pub(crate) fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<Symbol> { let mut features: FxHashSet<Symbol> = Default::default(); // Add base features for the target. diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 34cede54aaf..d61ce417562 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -237,11 +237,11 @@ impl<'ll, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { impl Type { /// Creates an integer type with the given number of bits, e.g., i24 - pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type { + pub(crate) fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type { unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) } } - pub fn ptr_llcx(llcx: &llvm::Context) -> &Type { + pub(crate) fn ptr_llcx(llcx: &llvm::Context) -> &Type { unsafe { llvm::LLVMPointerTypeInContext(llcx, AddressSpace::DATA.0) } } } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 8df9877cabc..c08495c012f 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -16,7 +16,6 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::ty::{self, Mutability, Ty}; use rustc_span::{Span, Symbol}; -use rustc_target::callconv::AdjustForForeignAbiError; use crate::interpret::InternKind; @@ -936,9 +935,6 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { InvalidProgramInfo::TooGeneric => const_eval_too_generic, InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported, InvalidProgramInfo::Layout(e) => e.diagnostic_message(), - InvalidProgramInfo::FnAbiAdjustForForeignAbi(_) => { - rustc_middle::error::middle_adjust_for_foreign_abi_error - } } } fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { @@ -953,12 +949,6 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { } dummy_diag.cancel(); } - InvalidProgramInfo::FnAbiAdjustForForeignAbi( - AdjustForForeignAbiError::Unsupported { arch, abi }, - ) => { - diag.arg("arch", arch); - diag.arg("abi", abi.name()); - } } } } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 95a72d3cbc1..66a75113652 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -106,9 +106,6 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> { ) -> InterpErrorKind<'tcx> { match err { FnAbiError::Layout(err) => err_inval!(Layout(err)), - FnAbiError::AdjustForForeignAbi(err) => { - err_inval!(FnAbiAdjustForForeignAbi(err)) - } } } } diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index eb98e3b5380..ba579e25f03 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,12 +1,8 @@ -use std::ops::ControlFlow; - use rustc_hir::def_id::LocalDefId; use rustc_middle::mir; use rustc_middle::mir::interpret::{AllocInit, Allocation, InterpResult, Pointer}; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, -}; +use rustc_middle::ty::{TyCtxt, TypeVisitable, TypeVisitableExt}; use tracing::debug; use super::{InterpCx, MPlaceTy, MemoryKind, interp_ok, throw_inval}; @@ -20,44 +16,10 @@ where T: TypeVisitable<TyCtxt<'tcx>>, { debug!("ensure_monomorphic_enough: ty={:?}", ty); - if !ty.has_param() { - return interp_ok(()); - } - - struct FoundParam; - struct UsedParamsNeedInstantiationVisitor {} - - impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UsedParamsNeedInstantiationVisitor { - type Result = ControlFlow<FoundParam>; - - fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { - if !ty.has_param() { - return ControlFlow::Continue(()); - } - - match *ty.kind() { - ty::Param(_) => ControlFlow::Break(FoundParam), - ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::FnDef(..) => { - ControlFlow::Continue(()) - } - _ => ty.super_visit_with(self), - } - } - - fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { - match c.kind() { - ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), - _ => c.super_visit_with(self), - } - } - } - - let mut vis = UsedParamsNeedInstantiationVisitor {}; - if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) { + if ty.has_param() { throw_inval!(TooGeneric); - } else { - interp_ok(()) } + interp_ok(()) } impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> { diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index d179396398f..14baf7554bc 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -108,13 +108,13 @@ impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTrait } impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst<I> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self) -> DiagArgValue { format!("{self:?}").into_diag_arg() } } impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::FnSig<I> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + fn into_diag_arg(self) -> DiagArgValue { format!("{self:?}").into_diag_arg() } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 4df4624971d..83c7bb0f52f 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -10,11 +10,10 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit::Visitor; use rustc_hir::*; use rustc_hir_pretty as pprust_hir; -use rustc_middle::hir::nested_filter; use rustc_span::def_id::StableCrateId; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spans}; -use crate::hir::ModuleItems; +use crate::hir::{ModuleItems, nested_filter}; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 77a7da2c74b..93bbf6d7fa4 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -13,7 +13,6 @@ use rustc_feature::GateIssue; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::{self as hir, HirId}; use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic}; -use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::Session; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer}; @@ -23,6 +22,7 @@ use tracing::debug; pub use self::StabilityLevel::*; use crate::ty::TyCtxt; +use crate::ty::print::with_no_trimmed_paths; #[derive(PartialEq, Clone, Copy, Debug)] pub enum StabilityLevel { diff --git a/compiler/rustc_middle/src/mir/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs index a52ec58a1ee..3fd73712b09 100644 --- a/compiler/rustc_middle/src/mir/generic_graph.rs +++ b/compiler/rustc_middle/src/mir/generic_graph.rs @@ -1,5 +1,6 @@ use gsgdt::{Edge, Graph, Node, NodeStyle}; -use rustc_middle::mir::*; + +use crate::mir::*; /// Convert an MIR function into a gsgdt Graph pub(crate) fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph { diff --git a/compiler/rustc_middle/src/mir/generic_graphviz.rs b/compiler/rustc_middle/src/mir/generic_graphviz.rs index e1c3d8156d8..bce7beb521d 100644 --- a/compiler/rustc_middle/src/mir/generic_graphviz.rs +++ b/compiler/rustc_middle/src/mir/generic_graphviz.rs @@ -2,7 +2,8 @@ use std::io::{self, Write}; use rustc_data_structures::graph::{self, iterate}; use rustc_graphviz as dot; -use rustc_middle::ty::TyCtxt; + +use crate::ty::TyCtxt; pub struct GraphvizWriter< 'a, diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs index 7bb41193d5c..a64b122fbc9 100644 --- a/compiler/rustc_middle/src/mir/graphviz.rs +++ b/compiler/rustc_middle/src/mir/graphviz.rs @@ -2,10 +2,10 @@ use std::io::{self, Write}; use gsgdt::GraphvizSettings; use rustc_graphviz as dot; -use rustc_middle::mir::*; use super::generic_graph::mir_fn_to_generic_graph; use super::pretty::dump_mir_def_ids; +use crate::mir::*; /// Write a graphviz DOT graph of a list of MIRs. pub fn write_mir_graphviz<W>(tcx: TyCtxt<'_>, single: Option<DefId>, w: &mut W) -> io::Result<()> diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 1222ba052cc..8861e31b099 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -216,10 +216,6 @@ pub enum InvalidProgramInfo<'tcx> { AlreadyReported(ReportedErrorInfo), /// An error occurred during layout computation. Layout(layout::LayoutError<'tcx>), - /// An error occurred during FnAbi computation: the passed --target lacks FFI support - /// (which unfortunately typeck does not reject). - /// Not using `FnAbiError` as that contains a nested `LayoutError`. - FnAbiAdjustForForeignAbi(rustc_target::callconv::AdjustForForeignAbiError), } /// Details of why a pointer had to be in-bounds. diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 45c862e0d34..c48cfffa05c 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -20,7 +20,6 @@ use rustc_data_structures::sync::{AtomicU64, Lock}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; -use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; use tracing::{debug, trace}; // Also make the error macros available from this module. @@ -46,6 +45,7 @@ pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; pub use self::value::Scalar; use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; +use crate::ty::print::with_no_trimmed_paths; use crate::ty::{self, Instance, Ty, TyCtxt}; /// Uniquely identifies one of the following: diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs index 18c48d99b81..748797fbb8d 100644 --- a/compiler/rustc_middle/src/mir/patch.rs +++ b/compiler/rustc_middle/src/mir/patch.rs @@ -1,6 +1,7 @@ -use rustc_middle::mir::*; use tracing::debug; +use crate::mir::*; + /// This struct represents a patch to MIR, which can add /// new statements and basic blocks and patch over block /// terminators. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 11ebbbe807d..b0df6c71014 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -5,17 +5,16 @@ use std::{fs, io}; use rustc_abi::Size; use rustc_ast::InlineAsmTemplatePiece; -use rustc_middle::mir::interpret::{ - AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, alloc_range, - read_target_uint, -}; -use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::*; use tracing::trace; use ty::print::PrettyPrinter; use super::graphviz::write_mir_fn_graphviz; -use crate::mir::interpret::ConstAllocation; +use crate::mir::interpret::{ + AllocBytes, AllocId, Allocation, ConstAllocation, GlobalAlloc, Pointer, Provenance, + alloc_range, read_target_uint, +}; +use crate::mir::visit::Visitor; +use crate::mir::*; const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 14f871cbbdc..cbd60920bc5 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -101,9 +101,9 @@ impl<T> EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> { type Result = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()]; } -impl<T> EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> { +impl<T> EraseType for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> { type Result = [u8; size_of::< - Result<(&'static (), rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed>, + Result<(&'static (), crate::thir::ExprId), rustc_errors::ErrorGuaranteed>, >()]; } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 3247bdbf105..d9035efaf56 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -11,12 +11,6 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, Stab use rustc_hir::definitions::DefPathHash; use rustc_index::{Idx, IndexVec}; use rustc_macros::{Decodable, Encodable}; -use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; -use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; -use rustc_middle::mir::mono::MonoItem; -use rustc_middle::mir::{self, interpret}; -use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; -use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_query_system::query::QuerySideEffects; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -30,6 +24,13 @@ use rustc_span::{ SpanDecoder, SpanEncoder, StableSourceFileId, Symbol, }; +use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex}; +use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; +use crate::mir::mono::MonoItem; +use crate::mir::{self, interpret}; +use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; +use crate::ty::{self, Ty, TyCtxt}; + const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; // A normal span encoded with both location information and a `SyntaxContext` @@ -563,7 +564,7 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> { } } -rustc_middle::implement_ty_decoder!(CacheDecoder<'a, 'tcx>); +crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>); // This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used // when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 4dc8f279553..2ab8750f727 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -20,20 +20,21 @@ use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; use rustc_index::{IndexVec, newtype_index}; use rustc_macros::{HashStable, TypeVisitable}; -use rustc_middle::middle::region; -use rustc_middle::mir::interpret::AllocId; -use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; -use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{ - self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty, - TyCtxt, UpvarArgs, -}; use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol}; use rustc_target::asm::InlineAsmRegOrRegClass; use tracing::instrument; +use crate::middle::region; +use crate::mir::interpret::AllocId; +use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; +use crate::ty::adjustment::PointerCoercion; +use crate::ty::layout::IntegerExt; +use crate::ty::{ + self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty, + TyCtxt, UpvarArgs, +}; + pub mod visit; macro_rules! thir_with_elements { diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index b1316ceef5a..10f7d589636 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -2,8 +2,8 @@ // typeck and codegen. use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_middle::mir; +use crate::mir; use crate::ty::{self, Ty}; /// Types that are represented as ints. diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 94bf1aa4f03..6b6e0ffc656 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -13,8 +13,6 @@ use std::marker::DiscriminantKind; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; -use rustc_middle::mir::mono::MonoItem; -use rustc_middle::ty::TyCtxt; use rustc_serialize::{Decodable, Encodable}; use rustc_span::Span; use rustc_span::source_map::Spanned; @@ -23,9 +21,10 @@ pub use rustc_type_ir::{TyDecoder, TyEncoder}; use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance}; +use crate::mir::mono::MonoItem; use crate::mir::{self}; use crate::traits; -use crate::ty::{self, AdtDef, GenericArgsRef, Ty}; +use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt}; /// The shorthand encoding uses an enum's variant index `usize` /// and is offset by this value so it never matches a real variant. diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index b7a648aae3f..e9c19331e4a 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -10,13 +10,13 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::FiniteBitSet; use rustc_macros::{Decodable, Encodable, HashStable, Lift, TyDecodable, TyEncodable}; -use rustc_middle::ty::normalize_erasing_regions::NormalizationError; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{DUMMY_SP, Span, Symbol}; use tracing::{debug, instrument}; use crate::error; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::print::{FmtPrinter, Printer, shrunk_instance_name}; use crate::ty::{ self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e5015ea3c3d..4b3e29b7c6c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -24,7 +24,6 @@ use rustc_target::spec::{ use tracing::debug; use {rustc_abi as abi, rustc_hir as hir}; -use crate::error::UnsupportedFnAbi; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; @@ -1275,18 +1274,12 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi) pub enum FnAbiError<'tcx> { /// Error produced by a `layout_of` call, while computing `FnAbi` initially. Layout(LayoutError<'tcx>), - - /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. - AdjustForForeignAbi(rustc_target::callconv::AdjustForForeignAbiError), } impl<'a, 'b, G: EmissionGuarantee> Diagnostic<'a, G> for FnAbiError<'b> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { match self { Self::Layout(e) => e.into_diagnostic().into_diag(dcx, level), - Self::AdjustForForeignAbi( - rustc_target::callconv::AdjustForForeignAbiError::Unsupported { arch, abi }, - ) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diag(dcx, level), } } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index feae8ea312e..343aabd7bbb 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1512,7 +1512,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::ExprKind::Binop(op) => { let (_, _, c1, c2) = expr.binop_args(); - let precedence = |binop: rustc_middle::mir::BinOp| { + let precedence = |binop: crate::mir::BinOp| { use rustc_ast::util::parser::AssocOp; AssocOp::from_ast_binop(binop.to_hir_binop()).precedence() }; @@ -1558,7 +1558,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::ExprKind::UnOp(op) => { let (_, ct) = expr.unop_args(); - use rustc_middle::mir::UnOp; + use crate::mir::UnOp; let formatted_op = match op { UnOp::Not => "!", UnOp::Neg => "-", diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 49bdb5e9dc3..1b5b791bb24 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -14,13 +14,13 @@ use rustc_hir::{ }; use rustc_index::IndexVec; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; -use rustc_middle::mir::FakeReadCause; use rustc_session::Session; use rustc_span::Span; use super::RvalueScopes; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::Canonical; +use crate::mir::FakeReadCause; use crate::traits::ObligationCause; use crate::ty::{ self, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, GenericArgs, diff --git a/compiler/rustc_middle/src/util/mod.rs b/compiler/rustc_middle/src/util/mod.rs index 8c875007b7f..85519fb0a7d 100644 --- a/compiler/rustc_middle/src/util/mod.rs +++ b/compiler/rustc_middle/src/util/mod.rs @@ -2,9 +2,9 @@ pub mod bug; #[derive(Default, Copy, Clone)] pub struct Providers { - pub queries: rustc_middle::query::Providers, - pub extern_queries: rustc_middle::query::ExternProviders, - pub hooks: rustc_middle::hooks::Providers, + pub queries: crate::query::Providers, + pub extern_queries: crate::query::ExternProviders, + pub hooks: crate::hooks::Providers, } /// Backwards compatibility hack to keep the diff small. This @@ -17,7 +17,7 @@ impl std::ops::DerefMut for Providers { } impl std::ops::Deref for Providers { - type Target = rustc_middle::query::Providers; + type Target = crate::query::Providers; fn deref(&self) -> &Self::Target { &self.queries diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 867f8f63969..433f7542bd7 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -7,7 +7,6 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; use rustc_query_system::Value; use rustc_query_system::query::{CycleError, report_cycle}; use rustc_span::def_id::LocalDefId; @@ -15,6 +14,7 @@ use rustc_span::{ErrorGuaranteed, Span}; use crate::dep_graph::dep_kinds; use crate::query::plumbing::CyclePlaceholder; +use crate::ty::{self, Representability, Ty, TyCtxt}; impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> { fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self { diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs deleted file mode 100644 index 63257df66fb..00000000000 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ /dev/null @@ -1,195 +0,0 @@ -//! This pass finds basic blocks that are completely equal, -//! and replaces all uses with just one of them. - -use std::collections::hash_map::Entry; -use std::hash::{Hash, Hasher}; -use std::iter; - -use rustc_data_structures::fx::FxHashMap; -use rustc_middle::mir::visit::MutVisitor; -use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; -use tracing::debug; - -use super::simplify::simplify_cfg; - -pub(super) struct DeduplicateBlocks; - -impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks { - fn is_enabled(&self, sess: &rustc_session::Session) -> bool { - sess.mir_opt_level() >= 4 - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - debug!("Running DeduplicateBlocks on `{:?}`", body.source); - let duplicates = find_duplicates(body); - let has_opts_to_apply = !duplicates.is_empty(); - - if has_opts_to_apply { - let mut opt_applier = OptApplier { tcx, duplicates }; - opt_applier.visit_body(body); - simplify_cfg(body); - } - } - - fn is_required(&self) -> bool { - false - } -} - -struct OptApplier<'tcx> { - tcx: TyCtxt<'tcx>, - duplicates: FxHashMap<BasicBlock, BasicBlock>, -} - -impl<'tcx> MutVisitor<'tcx> for OptApplier<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { - for target in terminator.successors_mut() { - if let Some(replacement) = self.duplicates.get(target) { - debug!("SUCCESS: Replacing: `{:?}` with `{:?}`", target, replacement); - *target = *replacement; - } - } - - self.super_terminator(terminator, location); - } -} - -fn find_duplicates(body: &Body<'_>) -> FxHashMap<BasicBlock, BasicBlock> { - let mut duplicates = FxHashMap::default(); - - let bbs_to_go_through = - body.basic_blocks.iter_enumerated().filter(|(_, bbd)| !bbd.is_cleanup).count(); - - let mut same_hashes = - FxHashMap::with_capacity_and_hasher(bbs_to_go_through, Default::default()); - - // Go through the basic blocks backwards. This means that in case of duplicates, - // we can use the basic block with the highest index as the replacement for all lower ones. - // For example, if bb1, bb2 and bb3 are duplicates, we will first insert bb3 in same_hashes. - // Then we will see that bb2 is a duplicate of bb3, - // and insert bb2 with the replacement bb3 in the duplicates list. - // When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the - // duplicates list with replacement bb3. - // When the duplicates are removed, we will end up with only bb3. - for (bb, bbd) in body.basic_blocks.iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) { - // Basic blocks can get really big, so to avoid checking for duplicates in basic blocks - // that are unlikely to have duplicates, we stop early. The early bail number has been - // found experimentally by eprintln while compiling the crates in the rustc-perf suite. - if bbd.statements.len() > 10 { - continue; - } - - let to_hash = BasicBlockHashable { basic_block_data: bbd }; - let entry = same_hashes.entry(to_hash); - match entry { - Entry::Occupied(occupied) => { - // The basic block was already in the hashmap, which means we have a duplicate - let value = *occupied.get(); - debug!("Inserting {:?} -> {:?}", bb, value); - duplicates.try_insert(bb, value).expect("key was already inserted"); - } - Entry::Vacant(vacant) => { - vacant.insert(bb); - } - } - } - - duplicates -} - -struct BasicBlockHashable<'a, 'tcx> { - basic_block_data: &'a BasicBlockData<'tcx>, -} - -impl Hash for BasicBlockHashable<'_, '_> { - fn hash<H: Hasher>(&self, state: &mut H) { - hash_statements(state, self.basic_block_data.statements.iter()); - // Note that since we only hash the kind, we lose span information if we deduplicate the - // blocks. - self.basic_block_data.terminator().kind.hash(state); - } -} - -impl Eq for BasicBlockHashable<'_, '_> {} - -impl PartialEq for BasicBlockHashable<'_, '_> { - fn eq(&self, other: &Self) -> bool { - self.basic_block_data.statements.len() == other.basic_block_data.statements.len() - && &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind - && iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements) - .all(|(x, y)| statement_eq(&x.kind, &y.kind)) - } -} - -fn hash_statements<'a, 'tcx, H: Hasher>( - hasher: &mut H, - iter: impl Iterator<Item = &'a Statement<'tcx>>, -) where - 'tcx: 'a, -{ - for stmt in iter { - statement_hash(hasher, &stmt.kind); - } -} - -fn statement_hash<H: Hasher>(hasher: &mut H, stmt: &StatementKind<'_>) { - match stmt { - StatementKind::Assign(box (place, rvalue)) => { - place.hash(hasher); - rvalue_hash(hasher, rvalue) - } - x => x.hash(hasher), - }; -} - -fn rvalue_hash<H: Hasher>(hasher: &mut H, rvalue: &Rvalue<'_>) { - match rvalue { - Rvalue::Use(op) => operand_hash(hasher, op), - x => x.hash(hasher), - }; -} - -fn operand_hash<H: Hasher>(hasher: &mut H, operand: &Operand<'_>) { - match operand { - Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }) => const_.hash(hasher), - x => x.hash(hasher), - }; -} - -fn statement_eq<'tcx>(lhs: &StatementKind<'tcx>, rhs: &StatementKind<'tcx>) -> bool { - let res = match (lhs, rhs) { - ( - StatementKind::Assign(box (place, rvalue)), - StatementKind::Assign(box (place2, rvalue2)), - ) => place == place2 && rvalue_eq(rvalue, rvalue2), - (x, y) => x == y, - }; - debug!("statement_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res); - res -} - -fn rvalue_eq<'tcx>(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool { - let res = match (lhs, rhs) { - (Rvalue::Use(op1), Rvalue::Use(op2)) => operand_eq(op1, op2), - (x, y) => x == y, - }; - debug!("rvalue_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res); - res -} - -fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool { - let res = match (lhs, rhs) { - ( - Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }), - Operand::Constant(box ConstOperand { user_ty: _, const_: const2, span: _ }), - ) => const_ == const2, - (x, y) => x == y, - }; - debug!("operand_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res); - res -} diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index b572f6ca0b3..397d21a857f 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -135,7 +135,6 @@ declare_passes! { Initial, Final }; - mod deduplicate_blocks : DeduplicateBlocks; mod deref_separator : Derefer; mod dest_prop : DestinationPropagation; pub mod dump_mir : Marker; @@ -700,7 +699,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &nrvo::RenameReturnPlace, &simplify::SimplifyLocals::Final, &multiple_return_terminators::MultipleReturnTerminators, - &deduplicate_blocks::DeduplicateBlocks, &large_enums::EnumSizeOpt { discrepancy: 128 }, // Some cleanup necessary at least for LLVM and potentially other codegen backends. &add_call_guards::CriticalCallEdges, diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 86816819be2..11f0e579de5 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -302,26 +302,16 @@ impl<'a> Parser<'a> { pub(super) fn parse_contract( &mut self, ) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> { - let gate = |span| { - if self.psess.contract_attribute_spans.contains(span) { - // span was generated via a builtin contracts attribute, so gate as end-user visible - self.psess.gated_spans.gate(sym::contracts, span); - } else { - // span was not generated via a builtin contracts attribute, so gate as internal machinery - self.psess.gated_spans.gate(sym::contracts_internals, span); - } - }; - let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) { + self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span); let precond = self.parse_expr()?; - gate(precond.span); Some(precond) } else { None }; let ensures = if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) { + self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span); let postcond = self.parse_expr()?; - gate(postcond.span); Some(postcond) } else { None diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 4601bb87b76..671b7d7ad76 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -46,15 +46,6 @@ fn unwrap_fn_abi<'tcx>( span: tcx.def_span(item_def_id), }); } - Err(FnAbiError::AdjustForForeignAbi(e)) => { - // Sadly there seems to be no `into_diagnostic` for this case... and I am not sure if - // this can even be reached. Anyway this is a perma-unstable debug attribute, an ICE - // isn't the worst thing. Also this matches what codegen does. - span_bug!( - tcx.def_span(item_def_id), - "error computing fn_abi_of_instance, cannot adjust for foreign ABI: {e:?}", - ) - } } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 8d42b478647..5db6f83f3ee 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1127,7 +1127,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }); // Make sure error reporting is deterministic. - suggestions.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap()); + suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); match find_best_match_for_name( &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(), @@ -2256,14 +2256,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { mut path: Vec<Segment>, parent_scope: &ParentScope<'ra>, ) -> Option<(Vec<Segment>, Option<String>)> { - match (path.get(0), path.get(1)) { + match path[..] { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) - if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {} + [first, second, ..] + if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {} // `ident::...` on 2018. - (Some(fst), _) - if fst.ident.span.at_least_rust_2018() && !fst.ident.is_path_segment_keyword() => + [first, ..] + if first.ident.span.at_least_rust_2018() + && !first.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. path.insert(0, Segment::from_ident(Ident::empty())); @@ -2374,7 +2375,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // 2) `std` suggestions before `core` suggestions. let mut extern_crate_names = self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>(); - extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap()); + extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str())); for name in extern_crate_names.into_iter() { // Replace first ident with a crate name and check if that is valid. diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 4762281c329..aa9ebdd9cea 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -9,7 +9,7 @@ //! //! ## Adding a new cfg //! -//! Adding a new feature requires two new symbols one for the cfg it-self +//! Adding a new feature requires two new symbols one for the cfg itself //! and the second one for the unstable feature gate, those are defined in //! `rustc_span::symbol`. //! diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index d4db05ce139..e0405a71f65 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -208,10 +208,6 @@ pub struct ParseSess { pub config: Cfg, pub check_config: CheckCfg, pub edition: Edition, - /// Places where contract attributes were expanded into unstable AST forms. - /// This is used to allowlist those spans (so that we only check them against the feature - /// gate for the externally visible interface, and not internal implmentation machinery). - pub contract_attribute_spans: AppendOnlyVec<Span>, /// Places where raw identifiers were used. This is used to avoid complaining about idents /// clashing with keywords in new editions. pub raw_identifier_spans: AppendOnlyVec<Span>, @@ -260,7 +256,6 @@ impl ParseSess { config: Cfg::default(), check_config: CheckCfg::default(), edition: ExpnId::root().expn_data().edition, - contract_attribute_spans: Default::default(), raw_identifier_spans: Default::default(), bad_unicode_identifiers: Lock::new(Default::default()), source_map, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 0a4ffb15219..9f791603c72 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -39,12 +39,12 @@ macro_rules! def_reg_class { } } - pub fn parse(name: rustc_span::Symbol) -> Result<Self, &'static str> { + pub fn parse(name: rustc_span::Symbol) -> Result<Self, &'static [rustc_span::Symbol]> { match name { $( rustc_span::sym::$class => Ok(Self::$class), )* - _ => Err("unknown register class"), + _ => Err(&[$(rustc_span::sym::$class),*]), } } } @@ -635,7 +635,7 @@ impl InlineAsmRegClass { } } - pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> { + pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static [rustc_span::Symbol]> { Ok(match arch { InlineAsmArch::X86 | InlineAsmArch::X86_64 => { Self::X86(X86InlineAsmRegClass::parse(name)?) diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 50ac6c8fcde..b49dd258869 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -6,7 +6,6 @@ use rustc_abi::{ Size, TyAbiInterface, TyAndLayout, }; use rustc_macros::HashStable_Generic; -use rustc_span::Symbol; use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi}; @@ -623,19 +622,8 @@ impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> { } } -/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI. -#[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum AdjustForForeignAbiError { - /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs. - Unsupported { arch: Symbol, abi: ExternAbi }, -} - impl<'a, Ty> FnAbi<'a, Ty> { - pub fn adjust_for_foreign_abi<C>( - &mut self, - cx: &C, - abi: ExternAbi, - ) -> Result<(), AdjustForForeignAbiError> + pub fn adjust_for_foreign_abi<C>(&mut self, cx: &C, abi: ExternAbi) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasX86AbiOpt, @@ -644,7 +632,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { if let Some(arg) = self.args.first_mut() { arg.pass_by_stack_offset(None); } - return Ok(()); + return; } let spec = cx.target_spec(); @@ -719,15 +707,8 @@ impl<'a, Ty> FnAbi<'a, Ty> { } "wasm64" => wasm::compute_c_abi_info(cx, self), "bpf" => bpf::compute_abi_info(self), - arch => { - return Err(AdjustForForeignAbiError::Unsupported { - arch: Symbol::intern(arch), - abi, - }); - } + arch => panic!("no lowering implemented for {arch}"), } - - Ok(()) } pub fn adjust_for_rust_abi<C>(&mut self, cx: &C, abi: ExternAbi) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index ea7c15a3595..1ba8defedae 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -145,6 +145,7 @@ static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("dotprod", Unstable(sym::arm_target_feature), &["neon"]), ("dsp", Unstable(sym::arm_target_feature), &[]), ("fp-armv8", Unstable(sym::arm_target_feature), &["vfp4"]), + ("fp16", Unstable(sym::arm_target_feature), &["neon"]), ("fpregs", Unstable(sym::arm_target_feature), &[]), ("i8mm", Unstable(sym::arm_target_feature), &["neon"]), ("mclass", Unstable(sym::arm_target_feature), &[]), diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 99b70c87ccd..9e7e96dddd7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -18,6 +18,8 @@ use rustc_middle::ty::{ TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, }; use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym}; +use rustc_type_ir::inherent::*; +use rustc_type_ir::visit::TypeVisitableExt; use tracing::{debug, instrument, warn}; use super::nice_region_error::placeholder_error::Highlighted; @@ -155,27 +157,92 @@ impl UnderspecifiedArgKind { } } -struct ClosureEraser<'tcx> { - tcx: TyCtxt<'tcx>, +struct ClosureEraser<'a, 'tcx> { + infcx: &'a InferCtxt<'tcx>, } -impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'tcx> { +impl<'a, 'tcx> ClosureEraser<'a, 'tcx> { + fn new_infer(&mut self) -> Ty<'tcx> { + self.infcx.next_ty_var(DUMMY_SP) + } +} + +impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> { fn cx(&self) -> TyCtxt<'tcx> { - self.tcx + self.infcx.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.kind() { ty::Closure(_, args) => { + // For a closure type, we turn it into a function pointer so that it gets rendered + // as `fn(args) -> Ret`. let closure_sig = args.as_closure().sig(); Ty::new_fn_ptr( - self.tcx, - self.tcx.signature_unclosure(closure_sig, hir::Safety::Safe), + self.cx(), + self.cx().signature_unclosure(closure_sig, hir::Safety::Safe), ) } - _ => ty.super_fold_with(self), + ty::Adt(_, args) if !args.iter().any(|a| a.has_infer()) => { + // We have a type that doesn't have any inference variables, so we replace + // the whole thing with `_`. The type system already knows about this type in + // its entirety and it is redundant to specify it for the user. The user only + // needs to specify the type parameters that we *couldn't* figure out. + self.new_infer() + } + ty::Adt(def, args) => { + let generics = self.cx().generics_of(def.did()); + let generics: Vec<bool> = generics + .own_params + .iter() + .map(|param| param.default_value(self.cx()).is_some()) + .collect(); + let ty = Ty::new_adt( + self.cx(), + *def, + self.cx().mk_args_from_iter(generics.into_iter().zip(args.iter()).map( + |(has_default, arg)| { + if arg.has_infer() { + // This param has an unsubstituted type variable, meaning that this + // type has a (potentially deeply nested) type parameter from the + // corresponding type's definition. We have explicitly asked this + // type to not be hidden. In either case, we keep the type and don't + // substitute with `_` just yet. + arg.fold_with(self) + } else if has_default { + // We have a type param that has a default type, like the allocator + // in Vec. We decided to show `Vec` itself, because it hasn't yet + // been replaced by an `_` `Infer`, but we want to ensure that the + // type parameter with default types does *not* get replaced with + // `_` because then we'd end up with `Vec<_, _>`, instead of + // `Vec<_>`. + arg + } else if let GenericArgKind::Type(_) = arg.kind() { + // We don't replace lifetime or const params, only type params. + self.new_infer().into() + } else { + arg.fold_with(self) + } + }, + )), + ); + ty + } + _ if ty.has_infer() => { + // This type has a (potentially nested) type parameter that we couldn't figure out. + // We will print this depth of type, so at least the type name and at least one of + // its type parameters. + ty.super_fold_with(self) + } + // We don't have an unknown type parameter anywhere, replace with `_`. + _ => self.new_infer(), } } + + fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { + // Avoid accidentally erasing the type of the const. + c + } } fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> { @@ -219,9 +286,9 @@ fn ty_to_string<'tcx>( ) -> String { let mut printer = fmt_printer(infcx, Namespace::TypeNS); let ty = infcx.resolve_vars_if_possible(ty); - // We use `fn` ptr syntax for closures, but this only works when the closure - // does not capture anything. - let ty = ty.fold_with(&mut ClosureEraser { tcx: infcx.tcx }); + // We use `fn` ptr syntax for closures, but this only works when the closure does not capture + // anything. We also remove all type parameters that are fully known to the type system. + let ty = ty.fold_with(&mut ClosureEraser { infcx }); match (ty.kind(), called_method_def_id) { // We don't want the regular output for `fn`s because it includes its path in diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 169f3a78c26..332b00e8423 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -650,7 +650,7 @@ fn fn_abi_new_uncached<'tcx>( conv, can_unwind: fn_can_unwind(cx.tcx(), fn_def_id, sig.abi), }; - fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id)?; + fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id); debug!("fn_abi_new_uncached = {:?}", fn_abi); fn_abi_sanity_check(cx, &fn_abi, sig.abi); Ok(tcx.arena.alloc(fn_abi)) @@ -662,7 +662,7 @@ fn fn_abi_adjust_for_abi<'tcx>( fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, abi: ExternAbi, fn_def_id: Option<DefId>, -) -> Result<(), &'tcx FnAbiError<'tcx>> { +) { if abi == ExternAbi::Unadjusted { // The "unadjusted" ABI passes aggregates in "direct" mode. That's fragile but needed for // some LLVM intrinsics. @@ -682,7 +682,7 @@ fn fn_abi_adjust_for_abi<'tcx>( for arg in fn_abi.args.iter_mut() { unadjust(arg); } - return Ok(()); + return; } let tcx = cx.tcx(); @@ -723,12 +723,8 @@ fn fn_abi_adjust_for_abi<'tcx>( } } } else { - fn_abi - .adjust_for_foreign_abi(cx, abi) - .map_err(|err| &*tcx.arena.alloc(FnAbiError::AdjustForForeignAbi(err)))?; + fn_abi.adjust_for_foreign_abi(cx, abi); } - - Ok(()) } #[tracing::instrument(level = "debug", skip(cx))] diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index dc2312b2da3..e42639c6807 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -1,10 +1,10 @@ -pub use rustc_type_ir::relate::*; -use rustc_type_ir::solve::Goal; -use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; use tracing::{debug, instrument}; use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys}; use crate::data_structures::DelayedSet; +pub use crate::relate::*; +use crate::solve::Goal; +use crate::{self as ty, InferCtxtLike, Interner}; pub trait RelateExt: InferCtxtLike { fn relate<T: Relate<Self::Interner>>( diff --git a/config.example.toml b/config.example.toml index 7f6bbf27992..1a8f42428ab 100644 --- a/config.example.toml +++ b/config.example.toml @@ -323,7 +323,7 @@ #full-bootstrap = false # Set the bootstrap/download cache path. It is useful when building rust -# repeatedly in a CI invironment. +# repeatedly in a CI environment. #bootstrap-cache-path = /path/to/shared/cache # Enable a build of the extended Rust tool set which is not only the compiler diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index dcab6136ae8..9805cee1c33 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -94,7 +94,7 @@ impl fmt::Display for AllocError { /// - the memory block is deallocated, or /// - the allocator is dropped. /// -/// Copying, cloning, or moving the allocator must not invalidate memory blocks returned from it +/// Copying, cloning, or moving the allocator must not invalidate memory blocks returned from it. /// A copied or cloned allocator must behave like the original allocator. /// /// A memory block which is [*currently allocated*] may be passed to diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 17d94555927..f90de1f5ced 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -610,6 +610,101 @@ impl dyn Any + Send + Sync { /// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth /// noting that the hashes and ordering will vary between Rust releases. Beware /// of relying on them inside of your code! +/// +/// # Danger of Improper Variance +/// +/// You might think that subtyping is impossible between two static types, +/// but this is false; there exists a static type with a static subtype. +/// To wit, `fn(&str)`, which is short for `for<'any> fn(&'any str)`, and +/// `fn(&'static str)`, are two distinct, static types, and yet, +/// `fn(&str)` is a subtype of `fn(&'static str)`, since any value of type +/// `fn(&str)` can be used where a value of type `fn(&'static str)` is needed. +/// +/// This means that abstractions around `TypeId`, despite its +/// `'static` bound on arguments, still need to worry about unnecessary +/// and improper variance: it is advisable to strive for invariance +/// first. The usability impact will be negligible, while the reduction +/// in the risk of unsoundness will be most welcome. +/// +/// ## Examples +/// +/// Suppose `SubType` is a subtype of `SuperType`, that is, +/// a value of type `SubType` can be used wherever +/// a value of type `SuperType` is expected. +/// Suppose also that `CoVar<T>` is a generic type, which is covariant over `T` +/// (like many other types, including `PhantomData<T>` and `Vec<T>`). +/// +/// Then, by covariance, `CoVar<SubType>` is a subtype of `CoVar<SuperType>`, +/// that is, a value of type `CoVar<SubType>` can be used wherever +/// a value of type `CoVar<SuperType>` is expected. +/// +/// Then if `CoVar<SuperType>` relies on `TypeId::of::<SuperType>()` to uphold any invariants, +/// those invariants may be broken because a value of type `CoVar<SuperType>` can be created +/// without going through any of its methods, like so: +/// ``` +/// type SubType = fn(&()); +/// type SuperType = fn(&'static ()); +/// type CoVar<T> = Vec<T>; // imagine something more complicated +/// +/// let sub: CoVar<SubType> = CoVar::new(); +/// // we have a `CoVar<SuperType>` instance without +/// // *ever* having called `CoVar::<SuperType>::new()`! +/// let fake_super: CoVar<SuperType> = sub; +/// ``` +/// +/// The following is an example program that tries to use `TypeId::of` to +/// implement a generic type `Unique<T>` that guarantees unique instances for each `Unique<T>`, +/// that is, and for each type `T` there can be at most one value of type `Unique<T>` at any time. +/// +/// ``` +/// mod unique { +/// use std::any::TypeId; +/// use std::collections::BTreeSet; +/// use std::marker::PhantomData; +/// use std::sync::Mutex; +/// +/// static ID_SET: Mutex<BTreeSet<TypeId>> = Mutex::new(BTreeSet::new()); +/// +/// // TypeId has only covariant uses, which makes Unique covariant over TypeAsId 🚨 +/// #[derive(Debug, PartialEq)] +/// pub struct Unique<TypeAsId: 'static>( +/// // private field prevents creation without `new` outside this module +/// PhantomData<TypeAsId>, +/// ); +/// +/// impl<TypeAsId: 'static> Unique<TypeAsId> { +/// pub fn new() -> Option<Self> { +/// let mut set = ID_SET.lock().unwrap(); +/// (set.insert(TypeId::of::<TypeAsId>())).then(|| Self(PhantomData)) +/// } +/// } +/// +/// impl<TypeAsId: 'static> Drop for Unique<TypeAsId> { +/// fn drop(&mut self) { +/// let mut set = ID_SET.lock().unwrap(); +/// (!set.remove(&TypeId::of::<TypeAsId>())).then(|| panic!("duplicity detected")); +/// } +/// } +/// } +/// +/// use unique::Unique; +/// +/// // `OtherRing` is a subtype of `TheOneRing`. Both are 'static, and thus have a TypeId. +/// type TheOneRing = fn(&'static ()); +/// type OtherRing = fn(&()); +/// +/// fn main() { +/// let the_one_ring: Unique<TheOneRing> = Unique::new().unwrap(); +/// assert_eq!(Unique::<TheOneRing>::new(), None); +/// +/// let other_ring: Unique<OtherRing> = Unique::new().unwrap(); +/// // Use that `Unique<OtherRing>` is a subtype of `Unique<TheOneRing>` 🚨 +/// let fake_one_ring: Unique<TheOneRing> = other_ring; +/// assert_eq!(fake_one_ring, the_one_ring); +/// +/// std::mem::forget(fake_one_ring); +/// } +/// ``` #[derive(Clone, Copy, Eq, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct TypeId { @@ -627,8 +722,7 @@ impl PartialEq for TypeId { } impl TypeId { - /// Returns the `TypeId` of the type this generic function has been - /// instantiated with. + /// Returns the `TypeId` of the generic type parameter. /// /// # Examples /// diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index a115acf42b1..21bad6705ab 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -612,8 +612,6 @@ macro_rules! nonzero_integer { /// Basic usage: /// /// ``` - /// #![feature(non_zero_count_ones)] - /// /// # use std::num::NonZero; /// # /// # fn main() { test().unwrap(); } @@ -627,7 +625,8 @@ macro_rules! nonzero_integer { /// # } /// ``` /// - #[unstable(feature = "non_zero_count_ones", issue = "120287")] + #[stable(feature = "non_zero_count_ones", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "non_zero_count_ones", since = "CURRENT_RUSTC_VERSION")] #[doc(alias = "popcount")] #[doc(alias = "popcnt")] #[must_use = "this returns the result of the operation, \ diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 0871a9e22d3..83b009c86dc 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -664,7 +664,7 @@ impl File { /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { - /// let f = File::open("foo.txt")?; + /// let f = File::create("foo.txt")?; /// f.lock()?; /// Ok(()) /// } @@ -767,7 +767,7 @@ impl File { /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { - /// let f = File::open("foo.txt")?; + /// let f = File::create("foo.txt")?; /// f.try_lock()?; /// Ok(()) /// } diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 1d26bf37f4d..825a89fc7f2 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -651,16 +651,24 @@ mod if_keyword {} #[doc(keyword = "impl")] // -/// Implement some functionality for a type. +/// Implementations of functionality for a type, or a type implementing some functionality. +/// +/// There are two uses of the keyword `impl`: +/// * An `impl` block is an item that is used to implement some functionality for a type. +/// * An `impl Trait` in a type-position can be used to designate a type that implements a trait called `Trait`. +/// +/// # Implementing Functionality for a Type /// /// The `impl` keyword is primarily used to define implementations on types. Inherent /// implementations are standalone, while trait implementations are used to implement traits for /// types, or other traits. /// -/// Functions and consts can both be defined in an implementation. A function defined in an -/// `impl` block can be standalone, meaning it would be called like `Foo::bar()`. If the function +/// An implementation consists of definitions of functions and consts. A function defined in an +/// `impl` block can be standalone, meaning it would be called like `Vec::new()`. If the function /// takes `self`, `&self`, or `&mut self` as its first argument, it can also be called using -/// method-call syntax, a familiar feature to any object oriented programmer, like `foo.bar()`. +/// method-call syntax, a familiar feature to any object-oriented programmer, like `vec.len()`. +/// +/// ## Inherent Implementations /// /// ```rust /// struct Example { @@ -680,6 +688,17 @@ mod if_keyword {} /// self.number /// } /// } +/// ``` +/// +/// It matters little where an inherent implementation is defined; +/// its functionality is in scope wherever its implementing type is. +/// +/// ## Trait Implementations +/// +/// ```rust +/// struct Example { +/// number: i32, +/// } /// /// trait Thingy { /// fn do_thingy(&self); @@ -692,11 +711,19 @@ mod if_keyword {} /// } /// ``` /// +/// It matters little where a trait implementation is defined; +/// its functionality can be brought into scope by importing the trait it implements. +/// /// For more information on implementations, see the [Rust book][book1] or the [Reference]. /// -/// The other use of the `impl` keyword is in `impl Trait` syntax, which can be seen as a shorthand -/// for "a concrete type that implements this trait". Its primary use is working with closures, -/// which have type definitions generated at compile time that can't be simply typed out. +/// # Designating a Type that Implements Some Functionality +/// +/// The other use of the `impl` keyword is in `impl Trait` syntax, which can be understood to mean +/// "any (or some) concrete type that implements Trait". +/// It can be used as the type of a variable declaration, +/// in [argument position](https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html) +/// or in [return position](https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html). +/// One pertinent use case is in working with closures, which have unnameable types. /// /// ```rust /// fn thing_returning_closure() -> impl Fn(i32) -> bool { diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs index 6d23c72ef22..e305b8610c9 100644 --- a/library/std/src/sys/pal/uefi/os.rs +++ b/library/std/src/sys/pal/uefi/os.rs @@ -17,111 +17,50 @@ pub fn errno() -> RawOsError { pub fn error_string(errno: RawOsError) -> String { // Keep the List in Alphabetical Order // The Messages are taken from UEFI Specification Appendix D - Status Codes - match r_efi::efi::Status::from_usize(errno) { - Status::ABORTED => "The operation was aborted.".to_owned(), - Status::ACCESS_DENIED => "Access was denied.".to_owned(), - Status::ALREADY_STARTED => "The protocol has already been started.".to_owned(), - Status::BAD_BUFFER_SIZE => "The buffer was not the proper size for the request.".to_owned(), - Status::BUFFER_TOO_SMALL => { - "The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs.".to_owned() - } - Status::COMPROMISED_DATA => { - "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status.".to_owned() - } - Status::CONNECTION_FIN => { - "The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance.".to_owned() - } - Status::CONNECTION_REFUSED => { - "The receiving or transmission operation fails because this connection is refused.".to_owned() - } - Status::CONNECTION_RESET => { - "The connect fails because the connection is reset either by instance itself or the communication peer.".to_owned() - } - Status::CRC_ERROR => "A CRC error was detected.".to_owned(), - Status::DEVICE_ERROR => "The physical device reported an error while attempting the operation.".to_owned() - , - Status::END_OF_FILE => { - "The end of the file was reached.".to_owned() - } - Status::END_OF_MEDIA => { - "Beginning or end of media was reached".to_owned() - } - Status::HOST_UNREACHABLE => { - "The remote host is not reachable.".to_owned() - } - Status::HTTP_ERROR => { - "A HTTP error occurred during the network operation.".to_owned() - } - Status::ICMP_ERROR => { - "An ICMP error occurred during the network operation.".to_owned() - } - Status::INCOMPATIBLE_VERSION => { - "The function encountered an internal version that was incompatible with a version requested by the caller.".to_owned() - } - Status::INVALID_LANGUAGE => { - "The language specified was invalid.".to_owned() - } - Status::INVALID_PARAMETER => { - "A parameter was incorrect.".to_owned() - } - Status::IP_ADDRESS_CONFLICT => { - "There is an address conflict address allocation".to_owned() - } - Status::LOAD_ERROR => { - "The image failed to load.".to_owned() - } - Status::MEDIA_CHANGED => { - "The medium in the device has changed since the last access.".to_owned() - } - Status::NETWORK_UNREACHABLE => { - "The network containing the remote host is not reachable.".to_owned() - } - Status::NO_MAPPING => { - "A mapping to a device does not exist.".to_owned() - } - Status::NO_MEDIA => { - "The device does not contain any medium to perform the operation.".to_owned() - } - Status::NO_RESPONSE => { - "The server was not found or did not respond to the request.".to_owned() - } - Status::NOT_FOUND => "The item was not found.".to_owned(), - Status::NOT_READY => { - "There is no data pending upon return.".to_owned() - } - Status::NOT_STARTED => { - "The protocol has not been started.".to_owned() - } - Status::OUT_OF_RESOURCES => { - "A resource has run out.".to_owned() - } - Status::PROTOCOL_ERROR => { - "A protocol error occurred during the network operation.".to_owned() - } - Status::PROTOCOL_UNREACHABLE => { - "An ICMP protocol unreachable error is received.".to_owned() - } - Status::SECURITY_VIOLATION => { - "The function was not performed due to a security violation.".to_owned() - } - Status::TFTP_ERROR => { - "A TFTP error occurred during the network operation.".to_owned() - } - Status::TIMEOUT => "The timeout time expired.".to_owned(), - Status::UNSUPPORTED => { - "The operation is not supported.".to_owned() - } - Status::VOLUME_FULL => { - "There is no more space on the file system.".to_owned() - } - Status::VOLUME_CORRUPTED => { - "An inconstancy was detected on the file system causing the operating to fail.".to_owned() - } - Status::WRITE_PROTECTED => { - "The device cannot be written to.".to_owned() - } - _ => format!("Status: {}", errno), - } + #[rustfmt::skip] + let msg = match r_efi::efi::Status::from_usize(errno) { + Status::ABORTED => "The operation was aborted.", + Status::ACCESS_DENIED => "Access was denied.", + Status::ALREADY_STARTED => "The protocol has already been started.", + Status::BAD_BUFFER_SIZE => "The buffer was not the proper size for the request.", + Status::BUFFER_TOO_SMALL => "The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs.", + Status::COMPROMISED_DATA => "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status.", + Status::CONNECTION_FIN => "The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance.", + Status::CONNECTION_REFUSED => "The receiving or transmission operation fails because this connection is refused.", + Status::CONNECTION_RESET => "The connect fails because the connection is reset either by instance itself or the communication peer.", + Status::CRC_ERROR => "A CRC error was detected.", + Status::DEVICE_ERROR => "The physical device reported an error while attempting the operation.", + Status::END_OF_FILE => "The end of the file was reached.", + Status::END_OF_MEDIA => "Beginning or end of media was reached", + Status::HOST_UNREACHABLE => "The remote host is not reachable.", + Status::HTTP_ERROR => "A HTTP error occurred during the network operation.", + Status::ICMP_ERROR => "An ICMP error occurred during the network operation.", + Status::INCOMPATIBLE_VERSION => "The function encountered an internal version that was incompatible with a version requested by the caller.", + Status::INVALID_LANGUAGE => "The language specified was invalid.", + Status::INVALID_PARAMETER => "A parameter was incorrect.", + Status::IP_ADDRESS_CONFLICT => "There is an address conflict address allocation", + Status::LOAD_ERROR => "The image failed to load.", + Status::MEDIA_CHANGED => "The medium in the device has changed since the last access.", + Status::NETWORK_UNREACHABLE => "The network containing the remote host is not reachable.", + Status::NO_MAPPING => "A mapping to a device does not exist.", + Status::NO_MEDIA => "The device does not contain any medium to perform the operation.", + Status::NO_RESPONSE => "The server was not found or did not respond to the request.", + Status::NOT_FOUND => "The item was not found.", + Status::NOT_READY => "There is no data pending upon return.", + Status::NOT_STARTED => "The protocol has not been started.", + Status::OUT_OF_RESOURCES => "A resource has run out.", + Status::PROTOCOL_ERROR => "A protocol error occurred during the network operation.", + Status::PROTOCOL_UNREACHABLE => "An ICMP protocol unreachable error is received.", + Status::SECURITY_VIOLATION => "The function was not performed due to a security violation.", + Status::TFTP_ERROR => "A TFTP error occurred during the network operation.", + Status::TIMEOUT => "The timeout time expired.", + Status::UNSUPPORTED => "The operation is not supported.", + Status::VOLUME_FULL => "There is no more space on the file system.", + Status::VOLUME_CORRUPTED => "An inconstancy was detected on the file system causing the operating to fail.", + Status::WRITE_PROTECTED => "The device cannot be written to.", + _ => return format!("Status: {errno}"), + }; + msg.to_owned() } pub fn getcwd() -> io::Result<PathBuf> { @@ -314,7 +253,7 @@ mod uefi_env { let mut start = 0; - // UEFI Shell returns all keys seperated by NULL. + // UEFI Shell returns all keys separated by NULL. // End of string is denoted by two NULLs for i in 0.. { if unsafe { *val.add(i) } == 0 { diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index f6f9067b9c6..03491e01e30 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1105,9 +1105,7 @@ pub fn rustc_cargo( cargo.rustflag("-Zdefault-visibility=protected"); } - // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary - // and may just be a time sink. - if compiler.stage != 0 { + if is_lto_stage(compiler) { match builder.config.rust_lto { RustcLto::Thin | RustcLto::Fat => { // Since using LTO for optimizing dylibs is currently experimental, @@ -2335,3 +2333,8 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path) // everything else (standard library, future stages...) to be rebuilt. t!(file.set_modified(previous_mtime)); } + +/// We only use LTO for stage 2+, to speed up build time of intermediate stages. +pub fn is_lto_stage(build_compiler: &Compiler) -> bool { + build_compiler.stage != 0 +} diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 793fa24991b..1291a634a6f 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use std::{env, fs}; +use crate::core::build_steps::compile::is_lto_stage; use crate::core::build_steps::toolstate::ToolState; use crate::core::build_steps::{compile, llvm}; use crate::core::builder; @@ -659,14 +660,16 @@ impl Step for Rustdoc { ); // rustdoc is performance sensitive, so apply LTO to it. - let lto = match builder.config.rust_lto { - RustcLto::Off => Some("off"), - RustcLto::Thin => Some("thin"), - RustcLto::Fat => Some("fat"), - RustcLto::ThinLocal => None, - }; - if let Some(lto) = lto { - cargo.env(cargo_profile_var("LTO", &builder.config), lto); + if is_lto_stage(&build_compiler) { + let lto = match builder.config.rust_lto { + RustcLto::Off => Some("off"), + RustcLto::Thin => Some("thin"), + RustcLto::Fat => Some("fat"), + RustcLto::ThinLocal => None, + }; + if let Some(lto) = lto { + cargo.env(cargo_profile_var("LTO", &builder.config), lto); + } } let _guard = builder.msg_tool( diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 738c8aaaed8..c08104e796b 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -12,15 +12,15 @@ runners: # Large runner used mainly for its bigger disk capacity - &job-linux-4c-largedisk - os: ubuntu-22.04-4core-16gb + os: ubuntu-24.04-4core-16gb <<: *base-job - &job-linux-8c - os: ubuntu-22.04-8core-32gb + os: ubuntu-24.04-8core-32gb <<: *base-job - &job-linux-16c - os: ubuntu-22.04-16core-64gb + os: ubuntu-24.04-16core-64gb <<: *base-job - &job-macos-xl diff --git a/src/doc/rustc/src/check-cfg.md b/src/doc/rustc/src/check-cfg.md index c62ca9fd9ad..00add2651ae 100644 --- a/src/doc/rustc/src/check-cfg.md +++ b/src/doc/rustc/src/check-cfg.md @@ -135,7 +135,7 @@ As of `2025-01-02T`, the list of known names is as follows: - `windows` > Starting with 1.85.0, the `test` cfg is consider to be a "userspace" config -> despite being also set by `rustc` and should be managed by the build-system it-self. +> despite being also set by `rustc` and should be managed by the build system itself. Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())` as argument to `--check-cfg`. diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index bb89d97a798..05555f537c9 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -169,7 +169,7 @@ target | std | notes [`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 32-bit x86 MinGW (Windows 10+, Pentium 4), LLVM ABI [^x86_32-floats-return-ABI] [`i686-unknown-freebsd`](platform-support/freebsd.md) | ✓ | 32-bit x86 FreeBSD (Pentium 4) [^x86_32-floats-return-ABI] `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 (Pentium 4) [^x86_32-floats-return-ABI] -[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | ? (Pentium 4, softfloat) | 32-bit UEFI +[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | ? | 32-bit UEFI (Pentium 4, softfloat) [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64D ABI) [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64S ABI) [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] @@ -313,7 +313,7 @@ target | std | host | notes [`i586-unknown-netbsd`](platform-support/netbsd.md) | ✓ | | 32-bit x86 (original Pentium) [^x86_32-floats-x87] [`i686-apple-darwin`](platform-support/apple-darwin.md) | ✓ | ✓ | 32-bit macOS (10.12+, Sierra+, Penryn) [^x86_32-floats-return-ABI] `i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku (Pentium 4) [^x86_32-floats-return-ABI] -[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd (Pentium 4) [^x86_32-floats-x87] +[`i686-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 32-bit GNU/Hurd (Pentium 4) [^x86_32-floats-return-ABI] [`i686-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/i386 (Pentium 4) [^x86_32-floats-return-ABI] [`i686-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 32-bit OpenBSD (Pentium 4) [^x86_32-floats-return-ABI] [`i686-unknown-redox`](platform-support/redox.md) | ✓ | | i686 Redox OS (PentiumPro) [^x86_32-floats-x87] diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs index fa7737bc143..7f5c7da3634 100644 --- a/src/librustdoc/passes/strip_aliased_non_local.rs +++ b/src/librustdoc/passes/strip_aliased_non_local.rs @@ -26,7 +26,7 @@ impl DocFolder for AliasedNonLocalStripper<'_> { Some(match i.kind { clean::TypeAliasItem(..) => { let mut stripper = NonLocalStripper { tcx: self.tcx }; - // don't call `fold_item` as that could strip the type-alias it-self + // don't call `fold_item` as that could strip the type alias itself // which we don't want to strip out stripper.fold_item_recur(i) } diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff deleted file mode 100644 index 60742ef0e9a..00000000000 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-abort.diff +++ /dev/null @@ -1,100 +0,0 @@ -- // MIR for `is_line_doc_comment_2` before DeduplicateBlocks -+ // MIR for `is_line_doc_comment_2` after DeduplicateBlocks - - fn is_line_doc_comment_2(_1: &str) -> bool { - debug s => _1; - let mut _0: bool; - let mut _2: &[u8]; - let mut _3: &str; - let mut _4: usize; - let mut _5: usize; - let mut _6: bool; - let mut _7: usize; - let mut _8: usize; - let mut _9: bool; - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = &(*_1); - _2 = core::str::<impl str>::as_bytes(move _3) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_3); - _4 = Len((*_2)); - _5 = const 4_usize; - _6 = Ge(move _4, move _5); - switchInt(move _6) -> [0: bb2, otherwise: bb3]; - } - - bb2: { - _7 = Len((*_2)); - _8 = const 3_usize; - _9 = Ge(move _7, move _8); -- switchInt(move _9) -> [0: bb7, otherwise: bb8]; -+ switchInt(move _9) -> [0: bb11, otherwise: bb7]; - } - - bb3: { - switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; - } - - bb4: { - switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; - } - - bb5: { - switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; - } - - bb6: { -- switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2]; -+ switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; - } - - bb7: { -- _0 = const false; -- goto -> bb14; -+ switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11]; - } - - bb8: { -- switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; -+ switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11]; - } - - bb9: { -- switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; -+ switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11]; - } - - bb10: { -- switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7]; -- } -- -- bb11: { - _0 = const true; -- goto -> bb14; -+ goto -> bb12; - } - -- bb12: { -- _0 = const true; -- goto -> bb14; -- } -- -- bb13: { -+ bb11: { - _0 = const false; -- goto -> bb14; -+ goto -> bb12; - } - -- bb14: { -+ bb12: { - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff deleted file mode 100644 index 7337a32f525..00000000000 --- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.panic-unwind.diff +++ /dev/null @@ -1,100 +0,0 @@ -- // MIR for `is_line_doc_comment_2` before DeduplicateBlocks -+ // MIR for `is_line_doc_comment_2` after DeduplicateBlocks - - fn is_line_doc_comment_2(_1: &str) -> bool { - debug s => _1; - let mut _0: bool; - let mut _2: &[u8]; - let mut _3: &str; - let mut _4: usize; - let mut _5: usize; - let mut _6: bool; - let mut _7: usize; - let mut _8: usize; - let mut _9: bool; - - bb0: { - StorageLive(_2); - StorageLive(_3); - _3 = &(*_1); - _2 = core::str::<impl str>::as_bytes(move _3) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_3); - _4 = Len((*_2)); - _5 = const 4_usize; - _6 = Ge(move _4, move _5); - switchInt(move _6) -> [0: bb2, otherwise: bb3]; - } - - bb2: { - _7 = Len((*_2)); - _8 = const 3_usize; - _9 = Ge(move _7, move _8); -- switchInt(move _9) -> [0: bb7, otherwise: bb8]; -+ switchInt(move _9) -> [0: bb11, otherwise: bb7]; - } - - bb3: { - switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2]; - } - - bb4: { - switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2]; - } - - bb5: { - switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2]; - } - - bb6: { -- switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2]; -+ switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2]; - } - - bb7: { -- _0 = const false; -- goto -> bb14; -+ switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11]; - } - - bb8: { -- switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7]; -+ switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11]; - } - - bb9: { -- switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7]; -+ switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11]; - } - - bb10: { -- switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7]; -- } -- -- bb11: { - _0 = const true; -- goto -> bb14; -+ goto -> bb12; - } - -- bb12: { -- _0 = const true; -- goto -> bb14; -- } -- -- bb13: { -+ bb11: { - _0 = const false; -- goto -> bb14; -+ goto -> bb12; - } - -- bb14: { -+ bb12: { - StorageDead(_2); - return; - } - } - diff --git a/tests/mir-opt/deduplicate_blocks.rs b/tests/mir-opt/deduplicate_blocks.rs deleted file mode 100644 index 3a164cb09a0..00000000000 --- a/tests/mir-opt/deduplicate_blocks.rs +++ /dev/null @@ -1,17 +0,0 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -//@ test-mir-pass: DeduplicateBlocks - -// EMIT_MIR deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff -pub const fn is_line_doc_comment_2(s: &str) -> bool { - match s.as_bytes() { - [b'/', b'/', b'/', b'/', ..] => false, - [b'/', b'/', b'/', ..] => true, - [b'/', b'/', b'!', ..] => true, - _ => false, - } -} - -fn main() { - is_line_doc_comment_2("asd"); -} diff --git a/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff b/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff new file mode 100644 index 00000000000..2f83f54d2af --- /dev/null +++ b/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff @@ -0,0 +1,12 @@ +- // MIR for `cursed_is_i32` before GVN ++ // MIR for `cursed_is_i32` after GVN + + fn cursed_is_i32() -> bool { + let mut _0: bool; + + bb0: { + _0 = Eq(const cursed_is_i32::<T>::{constant#0}, const cursed_is_i32::<T>::{constant#1}); + return; + } + } + diff --git a/tests/mir-opt/gvn_type_id_polymorphic.rs b/tests/mir-opt/gvn_type_id_polymorphic.rs new file mode 100644 index 00000000000..39bc5c24ecc --- /dev/null +++ b/tests/mir-opt/gvn_type_id_polymorphic.rs @@ -0,0 +1,22 @@ +//@ test-mir-pass: GVN +//@ compile-flags: -C opt-level=2 + +#![feature(core_intrinsics)] + +fn generic<T>() {} + +const fn type_id_of_val<T: 'static>(_: &T) -> u128 { + std::intrinsics::type_id::<T>() +} + +// EMIT_MIR gvn_type_id_polymorphic.cursed_is_i32.GVN.diff +fn cursed_is_i32<T: 'static>() -> bool { + // CHECK-LABEL: fn cursed_is_i32( + // CHECK: _0 = Eq(const cursed_is_i32::<T>::{constant#0}, const cursed_is_i32::<T>::{constant#1}); + // CHECK-NEXT: return; + (const { type_id_of_val(&generic::<T>) } == const { type_id_of_val(&generic::<i32>) }) +} + +fn main() { + dbg!(cursed_is_i32::<i32>()); +} diff --git a/tests/ui/asm/aarch64/bad-reg.stderr b/tests/ui/asm/aarch64/bad-reg.stderr index 370752ad0f1..c76722f32a7 100644 --- a/tests/ui/asm/aarch64/bad-reg.stderr +++ b/tests/ui/asm/aarch64/bad-reg.stderr @@ -3,6 +3,8 @@ error: invalid register class `foo`: unknown register class | LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ + | + = note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, `preg` error: invalid register `foo`: unknown register --> $DIR/bad-reg.rs:14:18 diff --git a/tests/ui/asm/x86_64/bad-reg.stderr b/tests/ui/asm/x86_64/bad-reg.stderr index 3df1f7b2208..6a02957210b 100644 --- a/tests/ui/asm/x86_64/bad-reg.stderr +++ b/tests/ui/asm/x86_64/bad-reg.stderr @@ -3,6 +3,8 @@ error: invalid register class `foo`: unknown register class | LL | asm!("{}", in(foo) foo); | ^^^^^^^^^^^ + | + = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg` error: invalid register `foo`: unknown register --> $DIR/bad-reg.rs:14:18 diff --git a/tests/ui/asm/x86_64/issue-82869.stderr b/tests/ui/asm/x86_64/issue-82869.stderr index 3cf9d6d1c1c..56e49099569 100644 --- a/tests/ui/asm/x86_64/issue-82869.stderr +++ b/tests/ui/asm/x86_64/issue-82869.stderr @@ -3,12 +3,16 @@ error: invalid register class `vreg`: unknown register class | LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") { | ^^^^^^^^^^^ + | + = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg` error: invalid register class `vreg`: unknown register class --> $DIR/issue-82869.rs:11:45 | LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") { | ^^^^^^^^^^ + | + = note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg` error: invalid register `d0`: unknown register --> $DIR/issue-82869.rs:11:57 diff --git a/tests/ui/contracts/associated-item.rs b/tests/ui/contracts/associated-item.rs new file mode 100644 index 00000000000..4a2d05abbc5 --- /dev/null +++ b/tests/ui/contracts/associated-item.rs @@ -0,0 +1,18 @@ +// Ensure we don't ICE when lowering contracts on an associated item. + +//@ compile-flags: --crate-type=lib +//@ check-pass + +#![feature(contracts)] +//~^ WARN the feature `contracts` is incomplete and may not be safe to use + +extern crate core; + +use core::contracts::requires; + +struct Foo; + +impl Foo { + #[requires(align > 0 && (align & (align - 1)) == 0)] + pub fn foo(align: i32) {} +} diff --git a/tests/ui/contracts/associated-item.stderr b/tests/ui/contracts/associated-item.stderr new file mode 100644 index 00000000000..20651026b87 --- /dev/null +++ b/tests/ui/contracts/associated-item.stderr @@ -0,0 +1,11 @@ +warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/associated-item.rs:6:12 + | +LL | #![feature(contracts)] + | ^^^^^^^^^ + | + = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr index c0e1522f54c..7302694a787 100644 --- a/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr +++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr @@ -1,18 +1,18 @@ error[E0658]: contract internal machinery is for internal use only - --> $DIR/internal-feature-gating.rs:16:45 + --> $DIR/internal-feature-gating.rs:16:28 | LL | fn identity_1() -> i32 contract_requires(|| true) { 10 } - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ | = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information = help: add `#![feature(contracts_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: contract internal machinery is for internal use only - --> $DIR/internal-feature-gating.rs:18:44 + --> $DIR/internal-feature-gating.rs:18:28 | LL | fn identity_2() -> i32 contract_ensures(|_| true) { 10 } - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information = help: add `#![feature(contracts_internals)]` to the crate attributes to enable diff --git a/tests/ui/feature-gates/feature-gate-contracts.rs b/tests/ui/feature-gates/feature-gate-contracts.rs index 5544f1d82ee..1759d23077b 100644 --- a/tests/ui/feature-gates/feature-gate-contracts.rs +++ b/tests/ui/feature-gates/feature-gate-contracts.rs @@ -3,9 +3,7 @@ #[core::contracts::requires(x > 0)] pub fn requires_needs_it(x: i32) { } //~^^ ERROR use of unstable library feature `contracts` -//~^^^ ERROR contracts are incomplete #[core::contracts::ensures(|ret| *ret > 0)] pub fn ensures_needs_it() -> i32 { 10 } //~^^ ERROR use of unstable library feature `contracts` -//~^^^ ERROR contracts are incomplete diff --git a/tests/ui/feature-gates/feature-gate-contracts.stderr b/tests/ui/feature-gates/feature-gate-contracts.stderr index 4403e7df50b..4b0f7150973 100644 --- a/tests/ui/feature-gates/feature-gate-contracts.stderr +++ b/tests/ui/feature-gates/feature-gate-contracts.stderr @@ -9,7 +9,7 @@ LL | #[core::contracts::requires(x > 0)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `contracts` - --> $DIR/feature-gate-contracts.rs:8:3 + --> $DIR/feature-gate-contracts.rs:7:3 | LL | #[core::contracts::ensures(|ret| *ret > 0)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,26 +18,6 @@ LL | #[core::contracts::ensures(|ret| *ret > 0)] = help: add `#![feature(contracts)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: contracts are incomplete - --> $DIR/feature-gate-contracts.rs:3:1 - | -LL | #[core::contracts::requires(x > 0)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information - = help: add `#![feature(contracts)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: contracts are incomplete - --> $DIR/feature-gate-contracts.rs:8:1 - | -LL | #[core::contracts::ensures(|ret| *ret > 0)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information - = help: add `#![feature(contracts)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr index a16e832f8ef..ee17f7737cf 100644 --- a/tests/ui/inference/cannot-infer-closure-circular.stderr +++ b/tests/ui/inference/cannot-infer-closure-circular.stderr @@ -9,8 +9,8 @@ LL | Ok(v) | help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified | -LL | let x = |r: Result<(), E>| { - | +++++++++++++++ +LL | let x = |r: Result<_, E>| { + | ++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr index 4e9a74c1e40..1ec8a33eb82 100644 --- a/tests/ui/inference/erase-type-params-in-label.stderr +++ b/tests/ui/inference/erase-type-params-in-label.stderr @@ -12,8 +12,8 @@ LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> { | ^^^^^^^ required by this bound in `foo` help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified | -LL | let foo: Foo<i32, &str, W, Z> = foo(1, ""); - | ++++++++++++++++++++++ +LL | let foo: Foo<_, &_, W, Z> = foo(1, ""); + | ++++++++++++++++++ error[E0283]: type annotations needed for `Bar<i32, &str, _>` --> $DIR/erase-type-params-in-label.rs:5:9 @@ -29,8 +29,8 @@ LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> { | ^^^^^^^ required by this bound in `bar` help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified | -LL | let bar: Bar<i32, &str, Z> = bar(1, ""); - | +++++++++++++++++++ +LL | let bar: Bar<_, &_, Z> = bar(1, ""); + | +++++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr index 391ed16f349..27382e30134 100644 --- a/tests/ui/inference/issue-104649.stderr +++ b/tests/ui/inference/issue-104649.stderr @@ -6,8 +6,8 @@ LL | let a = A(Result::Ok(Result::Ok(()))); | help: consider giving `a` an explicit type, where the type for type parameter `E` is specified | -LL | let a: A<std::result::Result<std::result::Result<(), E>, Error>> = A(Result::Ok(Result::Ok(()))); - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | let a: A<std::result::Result<std::result::Result<_, E>, _>> = A(Result::Ok(Result::Ok(()))); + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr index 69d1d71ef3c..97ccad9e785 100644 --- a/tests/ui/inference/issue-83606.stderr +++ b/tests/ui/inference/issue-83606.stderr @@ -11,8 +11,8 @@ LL | fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] { | ^^^^^^^^^^^^^^ required by this const generic parameter in `foo` help: consider giving this pattern a type, where the value of const parameter `N` is specified | -LL | let _: [usize; N] = foo("foo"); - | ++++++++++++ +LL | let _: [_; N] = foo("foo"); + | ++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs new file mode 100644 index 00000000000..4fd15eea9e0 --- /dev/null +++ b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs @@ -0,0 +1,10 @@ +type A = (i32, i32, i32, i32); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +fn foo(x: D) { + let y = Err(x); //~ ERROR type annotations needed for `Result<_ +} + +fn main() {} diff --git a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr new file mode 100644 index 00000000000..65fe2ffcb7f --- /dev/null +++ b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr @@ -0,0 +1,14 @@ +error[E0282]: type annotations needed for `Result<_, ((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))>` + --> $DIR/really-long-type-in-let-binding-without-sufficient-type-info.rs:7:9 + | +LL | let y = Err(x); + | ^ ------ type must be known at this point + | +help: consider giving `y` an explicit type, where the type for type parameter `T` is specified + | +LL | let y: Result<T, _> = Err(x); + | ++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/type-inference/or_else-multiple-type-params.stderr b/tests/ui/type-inference/or_else-multiple-type-params.stderr index 3176a2d490e..9bcd07f8bf1 100644 --- a/tests/ui/type-inference/or_else-multiple-type-params.stderr +++ b/tests/ui/type-inference/or_else-multiple-type-params.stderr @@ -6,8 +6,8 @@ LL | .or_else(|err| { | help: try giving this closure an explicit return type | -LL | .or_else(|err| -> Result<Child, F> { - | +++++++++++++++++++ +LL | .or_else(|err| -> Result<_, F> { + | +++++++++++++++ error: aborting due to 1 previous error |
