diff options
98 files changed, 895 insertions, 1099 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/src/ast.rs b/compiler/rustc_ast/src/ast.rs index deee3a597ae..29c1d34a125 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2249,7 +2249,7 @@ pub enum TyKind { CVarArgs, /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`, /// just as part of the type system. - Pat(P<Ty>, P<Pat>), + Pat(P<Ty>, P<TyPat>), /// Sometimes we need a dummy value when no error has occurred. Dummy, /// Placeholder for a kind that has failed to be defined. @@ -2277,6 +2277,27 @@ impl TyKind { } } +/// A pattern type pattern. +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct TyPat { + pub id: NodeId, + pub kind: TyPatKind, + pub span: Span, + pub tokens: Option<LazyAttrTokenStream>, +} + +/// All the different flavors of pattern that Rust recognizes. +// +// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`. +#[derive(Clone, Encodable, Decodable, Debug)] +pub enum TyPatKind { + /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`). + Range(Option<P<AnonConst>>, Option<P<AnonConst>>, Spanned<RangeEnd>), + + /// Placeholder for a pattern that wasn't syntactically well formed in some way. + Err(ErrorGuaranteed), +} + /// Syntax used to declare a trait object. #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] #[repr(u8)] diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index a9961cca583..de9f049704a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -210,6 +210,10 @@ pub trait MutVisitor: Sized { walk_ty(self, t); } + fn visit_ty_pat(&mut self, t: &mut P<TyPat>) { + walk_ty_pat(self, t); + } + fn visit_lifetime(&mut self, l: &mut Lifetime) { walk_lifetime(self, l); } @@ -570,7 +574,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) { TyKind::Paren(ty) => vis.visit_ty(ty), TyKind::Pat(ty, pat) => { vis.visit_ty(ty); - vis.visit_pat(pat); + vis.visit_ty_pat(pat); } TyKind::Path(qself, path) => { vis.visit_qself(qself); @@ -594,6 +598,20 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) { vis.visit_span(span); } +pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) { + let TyPat { id, kind, span, tokens } = ty.deref_mut(); + vis.visit_id(id); + match kind { + TyPatKind::Range(start, end, _include_end) => { + visit_opt(start, |c| vis.visit_anon_const(c)); + visit_opt(end, |c| vis.visit_anon_const(c)); + } + TyPatKind::Err(_) => {} + } + visit_lazy_tts(vis, tokens); + vis.visit_span(span); +} + fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) { let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod; visit_safety(vis, safety); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 714b074f930..3242d414595 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -179,6 +179,9 @@ pub trait Visitor<'ast>: Sized { fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result { walk_ty(self, t) } + fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result { + walk_ty_pat(self, t) + } fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result { walk_generic_param(self, param) } @@ -534,7 +537,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { } TyKind::Pat(ty, pat) => { try_visit!(visitor.visit_ty(ty)); - try_visit!(visitor.visit_pat(pat)); + try_visit!(visitor.visit_ty_pat(pat)); } TyKind::Array(ty, length) => { try_visit!(visitor.visit_ty(ty)); @@ -555,6 +558,18 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result { V::Result::output() } +pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Result { + let TyPat { id: _, kind, span: _, tokens: _ } = tp; + match kind { + TyPatKind::Range(start, end, _include_end) => { + visit_opt!(visitor, visit_anon_const, start); + visit_opt!(visitor, visit_anon_const, end); + } + TyPatKind::Err(_) => {} + } + V::Result::output() +} + fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result { if let Some(qself) = qself { let QSelf { ty, path_span: _, position: _ } = &**qself; 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/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index bb9b2a13185..e1f3afbcf59 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -4,10 +4,10 @@ use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::Res; use rustc_middle::span_bug; use rustc_span::source_map::{Spanned, respan}; -use rustc_span::{Ident, Span, kw}; +use rustc_span::{Ident, Span}; use super::errors::{ ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, @@ -430,78 +430,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind }) } - pub(crate) fn lower_ty_pat(&mut self, pattern: &Pat) -> &'hir hir::TyPat<'hir> { + pub(crate) fn lower_ty_pat(&mut self, pattern: &TyPat) -> &'hir hir::TyPat<'hir> { self.arena.alloc(self.lower_ty_pat_mut(pattern)) } - fn lower_ty_pat_mut(&mut self, mut pattern: &Pat) -> hir::TyPat<'hir> { + fn lower_ty_pat_mut(&mut self, pattern: &TyPat) -> hir::TyPat<'hir> { // loop here to avoid recursion let pat_hir_id = self.lower_node_id(pattern.id); - let node = loop { - match &pattern.kind { - PatKind::Range(e1, e2, Spanned { node: end, .. }) => { - // FIXME(pattern_types): remove this closure and call `lower_const_arg` instead. - // That requires first modifying the AST to have const args here. - let mut lower_expr = |e: &Expr| -> &_ { - if let ExprKind::Path(None, path) = &e.kind - && let Some(res) = self - .resolver - .get_partial_res(e.id) - .and_then(|partial_res| partial_res.full_res()) - { - self.lower_const_path_to_const_arg(path, res, e.id, e.span) - } else { - let node_id = self.next_node_id(); - let def_id = self.create_def( - self.current_hir_id_owner.def_id, - node_id, - kw::Empty, - DefKind::AnonConst, - e.span, - ); - let hir_id = self.lower_node_id(node_id); - let ac = self.arena.alloc(hir::AnonConst { - def_id, - hir_id, - body: self.lower_const_body(pattern.span, Some(e)), - span: self.lower_span(pattern.span), - }); - self.arena.alloc(hir::ConstArg { - hir_id: self.next_id(), - kind: hir::ConstArgKind::Anon(ac), - }) - } - }; - break hir::TyPatKind::Range( - e1.as_deref().map(|e| lower_expr(e)), - e2.as_deref().map(|e| lower_expr(e)), - self.lower_range_end(end, e2.is_some()), - ); - } - // return inner to be processed in next loop - PatKind::Paren(inner) => pattern = inner, - PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), - PatKind::Err(guar) => break hir::TyPatKind::Err(*guar), - PatKind::Deref(..) - | PatKind::Box(..) - | PatKind::Or(..) - | PatKind::Struct(..) - | PatKind::TupleStruct(..) - | PatKind::Tuple(..) - | PatKind::Ref(..) - | PatKind::Expr(..) - | PatKind::Guard(..) - | PatKind::Slice(_) - | PatKind::Ident(..) - | PatKind::Path(..) - | PatKind::Wild - | PatKind::Never - | PatKind::Rest => { - break hir::TyPatKind::Err( - self.dcx().span_err(pattern.span, "pattern not supported in pattern types"), - ); - } - } + let node = match &pattern.kind { + TyPatKind::Range(e1, e2, Spanned { node: end, .. }) => hir::TyPatKind::Range( + e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)), + e2.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)), + self.lower_range_end(end, e2.is_some()), + ), + TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar), }; hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index eeec24e5ea4..0bf5de3ef89 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1148,6 +1148,28 @@ impl<'a> State<'a> { } } + pub fn print_ty_pat(&mut self, pat: &ast::TyPat) { + match &pat.kind { + rustc_ast::TyPatKind::Range(start, end, include_end) => { + if let Some(start) = start { + self.print_expr_anon_const(start, &[]); + } + self.word(".."); + if let Some(end) = end { + if let RangeEnd::Included(_) = include_end.node { + self.word("="); + } + self.print_expr_anon_const(end, &[]); + } + } + rustc_ast::TyPatKind::Err(_) => { + self.popen(); + self.word("/*ERROR*/"); + self.pclose(); + } + } + } + pub fn print_type(&mut self, ty: &ast::Ty) { self.maybe_print_comment(ty.span.lo()); self.ibox(0); @@ -1252,7 +1274,7 @@ impl<'a> State<'a> { ast::TyKind::Pat(ty, pat) => { self.print_type(ty); self.word(" is "); - self.print_pat(pat); + self.print_ty_pat(pat); } } self.end(); diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index a600a9f316a..a55c7e962d0 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -1,6 +1,6 @@ use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{Pat, Ty, ast}; +use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast}; use rustc_errors::PResult; use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_parse::exp; @@ -21,12 +21,24 @@ pub(crate) fn expand<'cx>( ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat)))) } -fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<Pat>)> { +fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> { let mut parser = cx.new_parser_from_tts(stream); let ty = parser.parse_ty()?; parser.expect_keyword(exp!(Is))?; - let pat = parser.parse_pat_no_top_alt(None, None)?; + let pat = parser.parse_pat_no_top_alt(None, None)?.into_inner(); + + let kind = match pat.kind { + ast::PatKind::Range(start, end, include_end) => TyPatKind::Range( + start.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })), + end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })), + include_end, + ), + ast::PatKind::Err(guar) => TyPatKind::Err(guar), + _ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")), + }; + + let pat = P(TyPat { id: pat.id, kind, span: pat.span, tokens: pat.tokens }); Ok((ty, pat)) } 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/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/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/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_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_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_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 55c6a122d35..480d97e377a 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -390,9 +390,6 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData` lint_improper_ctypes_opaque = opaque types have no C equivalent -lint_improper_ctypes_pat_help = consider using the base type instead - -lint_improper_ctypes_pat_reason = pattern types have no C equivalent lint_improper_ctypes_slice_help = consider using a raw pointer instead lint_improper_ctypes_slice_reason = slices have no C equivalent diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 45b188205d2..636779fe9b4 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -241,10 +241,7 @@ fn structurally_same_type_impl<'tcx>( if let ty::Adt(def, args) = *ty.kind() { let is_transparent = def.repr().transparent(); let is_non_null = types::nonnull_optimization_guaranteed(tcx, def); - debug!( - "non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}", - ty, is_transparent, is_non_null - ); + debug!(?ty, is_transparent, is_non_null); if is_transparent && !is_non_null { debug_assert_eq!(def.variants().len(), 1); let v = &def.variant(FIRST_VARIANT); @@ -378,14 +375,14 @@ fn structurally_same_type_impl<'tcx>( // An Adt and a primitive or pointer type. This can be FFI-safe if non-null // enum layout optimisation is being applied. - (Adt(..), _) if is_primitive_or_pointer(b) => { + (Adt(..) | Pat(..), _) if is_primitive_or_pointer(b) => { if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) { a_inner == b } else { false } } - (_, Adt(..)) if is_primitive_or_pointer(a) => { + (_, Adt(..) | Pat(..)) if is_primitive_or_pointer(a) => { if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) { b_inner == a } else { diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index d89e615e14a..c8de5e87753 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -33,6 +33,7 @@ #![feature(let_chains)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 601d2fbfb67..68b1f435a4c 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -877,6 +877,37 @@ fn ty_is_known_nonnull<'tcx>( .filter_map(|variant| transparent_newtype_field(tcx, variant)) .any(|field| ty_is_known_nonnull(tcx, typing_env, field.ty(tcx, args), mode)) } + ty::Pat(base, pat) => { + ty_is_known_nonnull(tcx, typing_env, *base, mode) + || Option::unwrap_or_default( + try { + match **pat { + ty::PatternKind::Range { start, end, include_end } => { + match (start, end) { + (Some(start), None) => { + start.try_to_value()?.try_to_bits(tcx, typing_env)? > 0 + } + (Some(start), Some(end)) => { + let start = + start.try_to_value()?.try_to_bits(tcx, typing_env)?; + let end = + end.try_to_value()?.try_to_bits(tcx, typing_env)?; + + if include_end { + // This also works for negative numbers, as we just need + // to ensure we aren't wrapping over zero. + start > 0 && end >= start + } else { + start > 0 && end > start + } + } + _ => false, + } + } + } + }, + ) + } _ => false, } } @@ -907,9 +938,8 @@ fn get_nullable_type<'tcx>( }; return get_nullable_type(tcx, typing_env, inner_field_ty); } - ty::Int(ty) => Ty::new_int(tcx, ty), - ty::Uint(ty) => Ty::new_uint(tcx, ty), - ty::RawPtr(ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl), + ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base), + ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty, // As these types are always non-null, the nullable equivalent of // `Option<T>` of these types are their raw pointer counterparts. ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl), @@ -965,63 +995,69 @@ pub(crate) fn repr_nullable_ptr<'tcx>( ckind: CItemKind, ) -> Option<Ty<'tcx>> { debug!("is_repr_nullable_ptr(tcx, ty = {:?})", ty); - if let ty::Adt(ty_def, args) = ty.kind() { - let field_ty = match &ty_def.variants().raw[..] { - [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) { - ([], [field]) | ([field], []) => field.ty(tcx, args), - ([field1], [field2]) => { - let ty1 = field1.ty(tcx, args); - let ty2 = field2.ty(tcx, args); - - if is_niche_optimization_candidate(tcx, typing_env, ty1) { - ty2 - } else if is_niche_optimization_candidate(tcx, typing_env, ty2) { - ty1 - } else { - return None; + match ty.kind() { + ty::Adt(ty_def, args) => { + let field_ty = match &ty_def.variants().raw[..] { + [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) { + ([], [field]) | ([field], []) => field.ty(tcx, args), + ([field1], [field2]) => { + let ty1 = field1.ty(tcx, args); + let ty2 = field2.ty(tcx, args); + + if is_niche_optimization_candidate(tcx, typing_env, ty1) { + ty2 + } else if is_niche_optimization_candidate(tcx, typing_env, ty2) { + ty1 + } else { + return None; + } } - } + _ => return None, + }, _ => return None, - }, - _ => return None, - }; + }; - if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) { - return None; - } + if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) { + return None; + } - // At this point, the field's type is known to be nonnull and the parent enum is Option-like. - // If the computed size for the field and the enum are different, the nonnull optimization isn't - // being applied (and we've got a problem somewhere). - let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok(); - if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) { - bug!("improper_ctypes: Option nonnull optimization not applied?"); - } + // At this point, the field's type is known to be nonnull and the parent enum is Option-like. + // If the computed size for the field and the enum are different, the nonnull optimization isn't + // being applied (and we've got a problem somewhere). + let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok(); + if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) { + bug!("improper_ctypes: Option nonnull optimization not applied?"); + } - // Return the nullable type this Option-like enum can be safely represented with. - let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty)); - if field_ty_layout.is_err() && !field_ty.has_non_region_param() { - bug!("should be able to compute the layout of non-polymorphic type"); - } + // Return the nullable type this Option-like enum can be safely represented with. + let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty)); + if field_ty_layout.is_err() && !field_ty.has_non_region_param() { + bug!("should be able to compute the layout of non-polymorphic type"); + } - let field_ty_abi = &field_ty_layout.ok()?.backend_repr; - if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi { - match field_ty_scalar.valid_range(&tcx) { - WrappingRange { start: 0, end } - if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 => - { - return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); - } - WrappingRange { start: 1, .. } => { - return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); - } - WrappingRange { start, end } => { - unreachable!("Unhandled start and end range: ({}, {})", start, end) - } - }; + let field_ty_abi = &field_ty_layout.ok()?.backend_repr; + if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi { + match field_ty_scalar.valid_range(&tcx) { + WrappingRange { start: 0, end } + if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 => + { + return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); + } + WrappingRange { start: 1, .. } => { + return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap()); + } + WrappingRange { start, end } => { + unreachable!("Unhandled start and end range: ({}, {})", start, end) + } + }; + } + None } + ty::Pat(base, pat) => match **pat { + ty::PatternKind::Range { .. } => get_nullable_type(tcx, typing_env, *base), + }, + _ => None, } - None } impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { @@ -1256,11 +1292,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { help: Some(fluent::lint_improper_ctypes_char_help), }, - ty::Pat(..) => FfiUnsafe { - ty, - reason: fluent::lint_improper_ctypes_pat_reason, - help: Some(fluent::lint_improper_ctypes_pat_help), - }, + // It's just extra invariants on the type that you need to uphold, + // but only the base type is relevant for being representable in FFI. + ty::Pat(base, ..) => self.check_type_for_ffi(acc, base), ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => { FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None } 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_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_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 508bd831ccb..03aeb8720ca 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -923,6 +923,21 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r self.diag_metadata.current_trait_object = prev; self.diag_metadata.current_type_path = prev_ty; } + + fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result { + match &t.kind { + TyPatKind::Range(start, end, _) => { + if let Some(start) = start { + self.resolve_anon_const(start, AnonConstKind::ConstArg(IsRepeatExpr::No)); + } + if let Some(end) = end { + self.resolve_anon_const(end, AnonConstKind::ConstArg(IsRepeatExpr::No)); + } + } + TyPatKind::Err(_) => {} + } + } + fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) { let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo()); self.with_generic_param_rib( 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_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_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/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/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/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/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/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 1d88726d945..bafed41e39f 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -75,12 +75,12 @@ fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool } } -pub(crate) struct RangeOperand<'a> { - operand: &'a Option<ptr::P<ast::Expr>>, - pub(crate) span: Span, +pub(crate) struct RangeOperand<'a, T> { + pub operand: &'a Option<ptr::P<T>>, + pub span: Span, } -impl<'a> Rewrite for RangeOperand<'a> { +impl<'a, T: Rewrite> Rewrite for RangeOperand<'a, T> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { self.rewrite_result(context, shape).ok() } @@ -259,40 +259,7 @@ impl Rewrite for Pat { } PatKind::Never => Err(RewriteError::Unknown), PatKind::Range(ref lhs, ref rhs, ref end_kind) => { - let infix = match end_kind.node { - RangeEnd::Included(RangeSyntax::DotDotDot) => "...", - RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", - RangeEnd::Excluded => "..", - }; - let infix = if context.config.spaces_around_ranges() { - let lhs_spacing = match lhs { - None => "", - Some(_) => " ", - }; - let rhs_spacing = match rhs { - None => "", - Some(_) => " ", - }; - format!("{lhs_spacing}{infix}{rhs_spacing}") - } else { - infix.to_owned() - }; - let lspan = self.span.with_hi(end_kind.span.lo()); - let rspan = self.span.with_lo(end_kind.span.hi()); - rewrite_pair( - &RangeOperand { - operand: lhs, - span: lspan, - }, - &RangeOperand { - operand: rhs, - span: rspan, - }, - PairParts::infix(&infix), - context, - shape, - SeparatorPlace::Front, - ) + rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span) } PatKind::Ref(ref pat, mutability) => { let prefix = format!("&{}", format_mutability(mutability)); @@ -359,6 +326,50 @@ impl Rewrite for Pat { } } +pub fn rewrite_range_pat<T: Rewrite>( + context: &RewriteContext<'_>, + shape: Shape, + lhs: &Option<ptr::P<T>>, + rhs: &Option<ptr::P<T>>, + end_kind: &rustc_span::source_map::Spanned<RangeEnd>, + span: Span, +) -> RewriteResult { + let infix = match end_kind.node { + RangeEnd::Included(RangeSyntax::DotDotDot) => "...", + RangeEnd::Included(RangeSyntax::DotDotEq) => "..=", + RangeEnd::Excluded => "..", + }; + let infix = if context.config.spaces_around_ranges() { + let lhs_spacing = match lhs { + None => "", + Some(_) => " ", + }; + let rhs_spacing = match rhs { + None => "", + Some(_) => " ", + }; + format!("{lhs_spacing}{infix}{rhs_spacing}") + } else { + infix.to_owned() + }; + let lspan = span.with_hi(end_kind.span.lo()); + let rspan = span.with_lo(end_kind.span.hi()); + rewrite_pair( + &RangeOperand { + operand: lhs, + span: lspan, + }, + &RangeOperand { + operand: rhs, + span: rspan, + }, + PairParts::infix(&infix), + context, + shape, + SeparatorPlace::Front, + ) +} + fn rewrite_struct_pat( qself: &Option<ptr::P<ast::QSelf>>, path: &ast::Path, diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 6b3e40b9115..e93eb53cd87 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -211,7 +211,7 @@ impl Spanned for ast::PreciseCapturingArg { } } -impl<'a> Spanned for RangeOperand<'a> { +impl<'a, T> Spanned for RangeOperand<'a, T> { fn span(&self) -> Span { self.span } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index f8b713117f4..0009490e86f 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -18,6 +18,7 @@ use crate::lists::{ use crate::macros::{MacroPosition, rewrite_macro}; use crate::overflow; use crate::pairs::{PairParts, rewrite_pair}; +use crate::patterns::rewrite_range_pat; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::shape::Shape; use crate::source_map::SpanUtils; @@ -1045,6 +1046,21 @@ impl Rewrite for ast::Ty { } } +impl Rewrite for ast::TyPat { + fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult { + match self.kind { + ast::TyPatKind::Range(ref lhs, ref rhs, ref end_kind) => { + rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span) + } + ast::TyPatKind::Err(_) => Err(RewriteError::Unknown), + } + } +} + fn rewrite_bare_fn( bare_fn: &ast::BareFnTy, span: Span, 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/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/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/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs index 9bbb20246df..e4477c96202 100644 --- a/tests/ui/lint/clashing-extern-fn.rs +++ b/tests/ui/lint/clashing-extern-fn.rs @@ -1,7 +1,7 @@ //@ check-pass //@ aux-build:external_extern_fn.rs #![crate_type = "lib"] - +#![feature(pattern_type_macro, pattern_types)] mod redeclared_different_signature { mod a { extern "C" { @@ -490,3 +490,33 @@ mod hidden_niche { } } } + +mod pattern_types { + mod a { + use std::pat::pattern_type; + #[repr(transparent)] + struct NonZeroUsize(pattern_type!(usize is 1..)); + extern "C" { + fn pt_non_zero_usize() -> pattern_type!(usize is 1..); + fn pt_non_zero_usize_opt() -> Option<pattern_type!(usize is 1..)>; + fn pt_non_zero_usize_opt_full_range() -> Option<pattern_type!(usize is 0..)>; + //~^ WARN not FFI-safe + fn pt_non_null_ptr() -> pattern_type!(usize is 1..); + fn pt_non_zero_usize_wrapper() -> NonZeroUsize; + fn pt_non_zero_usize_wrapper_opt() -> Option<NonZeroUsize>; + } + } + mod b { + extern "C" { + // If there's a clash in either of these cases you're either gaining an incorrect + // invariant that the value is non-zero, or you're missing out on that invariant. Both + // cases are warning for, from both a caller-convenience and optimisation perspective. + fn pt_non_zero_usize() -> usize; + fn pt_non_zero_usize_opt() -> usize; + fn pt_non_null_ptr() -> *const (); + //~^ WARN `pt_non_null_ptr` redeclared with a different signature + fn pt_non_zero_usize_wrapper() -> usize; + fn pt_non_zero_usize_wrapper_opt() -> usize; + } + } +} diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr index 48dd1adbc1f..118b18b224c 100644 --- a/tests/ui/lint/clashing-extern-fn.stderr +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -17,6 +17,15 @@ LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint +warning: `extern` block uses type `Option<(usize) is 0..=>`, which is not FFI-safe + --> $DIR/clashing-extern-fn.rs:502:54 + | +LL | fn pt_non_zero_usize_opt_full_range() -> Option<pattern_type!(usize is 0..)>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + warning: `clash` redeclared with a different signature --> $DIR/clashing-extern-fn.rs:13:13 | @@ -258,5 +267,17 @@ LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz = note: expected `unsafe extern "C" fn() -> usize` found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZero<usize>>>` -warning: 22 warnings emitted +warning: `pt_non_null_ptr` redeclared with a different signature + --> $DIR/clashing-extern-fn.rs:516:13 + | +LL | fn pt_non_null_ptr() -> pattern_type!(usize is 1..); + | ---------------------------------------------------- `pt_non_null_ptr` previously declared here +... +LL | fn pt_non_null_ptr() -> *const (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | + = note: expected `unsafe extern "C" fn() -> (usize) is 1..=` + found `unsafe extern "C" fn() -> *const ()` + +warning: 24 warnings emitted diff --git a/tests/ui/lint/lint-ctypes-enum.rs b/tests/ui/lint/lint-ctypes-enum.rs index 19af1de9576..0d19d5b5347 100644 --- a/tests/ui/lint/lint-ctypes-enum.rs +++ b/tests/ui/lint/lint-ctypes-enum.rs @@ -94,6 +94,7 @@ extern "C" { fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>); //~^ ERROR `extern` block uses type fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>); //~ ERROR `extern` block uses type + fn option_u8(x: Option<u8>); //~ ERROR `extern` block uses type fn result_ref_t(x: Result<&'static u8, ()>); fn result_fn_t(x: Result<extern "C" fn(), ()>); diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr index 8e92e7e6946..a491bd19605 100644 --- a/tests/ui/lint/lint-ctypes-enum.stderr +++ b/tests/ui/lint/lint-ctypes-enum.stderr @@ -79,8 +79,17 @@ LL | fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint +error: `extern` block uses type `Option<u8>`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:97:21 + | +LL | fn option_u8(x: Option<u8>); + | ^^^^^^^^^^ not FFI-safe + | + = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum + = note: enum has no representation hint + error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:106:33 + --> $DIR/lint-ctypes-enum.rs:107:33 | LL | fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -88,7 +97,7 @@ LL | fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:113:33 + --> $DIR/lint-ctypes-enum.rs:114:33 | LL | fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -96,7 +105,7 @@ LL | fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:118:38 + --> $DIR/lint-ctypes-enum.rs:119:38 | LL | fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -105,7 +114,7 @@ LL | fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u = note: enum has no representation hint error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:120:30 + --> $DIR/lint-ctypes-enum.rs:121:30 | LL | fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -114,7 +123,7 @@ LL | fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>); = note: enum has no representation hint error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:124:51 + --> $DIR/lint-ctypes-enum.rs:125:51 | LL | fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -123,7 +132,7 @@ LL | fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, = note: enum has no representation hint error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:126:53 + --> $DIR/lint-ctypes-enum.rs:127:53 | LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -132,7 +141,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8> = note: enum has no representation hint error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:128:51 + --> $DIR/lint-ctypes-enum.rs:129:51 | LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -141,7 +150,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, = note: enum has no representation hint error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:131:49 + --> $DIR/lint-ctypes-enum.rs:132:49 | LL | fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -150,7 +159,7 @@ LL | fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Fi = note: enum has no representation hint error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:133:30 + --> $DIR/lint-ctypes-enum.rs:134:30 | LL | fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -159,7 +168,7 @@ LL | fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>); = note: enum has no representation hint error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:144:33 + --> $DIR/lint-ctypes-enum.rs:145:33 | LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -167,7 +176,7 @@ LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:151:33 + --> $DIR/lint-ctypes-enum.rs:152:33 | LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -175,7 +184,7 @@ LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:156:38 + --> $DIR/lint-ctypes-enum.rs:157:38 | LL | fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -184,7 +193,7 @@ LL | fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZe = note: enum has no representation hint error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:158:30 + --> $DIR/lint-ctypes-enum.rs:159:30 | LL | fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -193,7 +202,7 @@ LL | fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>); = note: enum has no representation hint error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:162:51 + --> $DIR/lint-ctypes-enum.rs:163:51 | LL | fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -202,7 +211,7 @@ LL | fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8 = note: enum has no representation hint error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:164:53 + --> $DIR/lint-ctypes-enum.rs:165:53 | LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -211,7 +220,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero< = note: enum has no representation hint error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:166:51 + --> $DIR/lint-ctypes-enum.rs:167:51 | LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -220,7 +229,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num = note: enum has no representation hint error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:169:49 + --> $DIR/lint-ctypes-enum.rs:170:49 | LL | fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -229,7 +238,7 @@ LL | fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero< = note: enum has no representation hint error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:171:30 + --> $DIR/lint-ctypes-enum.rs:172:30 | LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -238,7 +247,7 @@ LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>); = note: enum has no representation hint error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe - --> $DIR/lint-ctypes-enum.rs:173:27 + --> $DIR/lint-ctypes-enum.rs:174:27 | LL | fn result_unit_t_e(x: Result<(), ()>); | ^^^^^^^^^^^^^^ not FFI-safe @@ -246,5 +255,5 @@ LL | fn result_unit_t_e(x: Result<(), ()>); = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = note: enum has no representation hint -error: aborting due to 26 previous errors +error: aborting due to 27 previous errors 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 diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr index c5d9691a029..8cff0cee7b9 100644 --- a/tests/ui/type/pattern_types/assoc_const.default.stderr +++ b/tests/ui/type/pattern_types/assoc_const.default.stderr @@ -1,79 +1,38 @@ -error[E0658]: wraparound pattern type ranges cause monomorphization time errors - --> $DIR/assoc_const.rs:17:19 +error: generic parameters may not be used in const operations + --> $DIR/assoc_const.rs:17:41 | LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ cannot perform const operation using `T` | - = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information - = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: type parameters may not be used in const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error[E0658]: wraparound pattern type ranges cause monomorphization time errors - --> $DIR/assoc_const.rs:17:19 +error: generic parameters may not be used in const operations + --> $DIR/assoc_const.rs:17:61 | LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ cannot perform const operation using `T` | - = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information - = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: type parameters may not be used in const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: constant expression depends on a generic parameter - --> $DIR/assoc_const.rs:17:19 - | -LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this may fail depending on what value the parameter takes - -error: constant expression depends on a generic parameter - --> $DIR/assoc_const.rs:17:19 - | -LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this may fail depending on what value the parameter takes - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0658]: wraparound pattern type ranges cause monomorphization time errors - --> $DIR/assoc_const.rs:22:19 - | -LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information - = help: add `#![feature(generic_pattern_types)]` 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]: wraparound pattern type ranges cause monomorphization time errors - --> $DIR/assoc_const.rs:22:19 - | -LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information - = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: constant expression depends on a generic parameter - --> $DIR/assoc_const.rs:22:19 +error: generic parameters may not be used in const operations + --> $DIR/assoc_const.rs:20:40 | LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ cannot perform const operation using `T` | - = note: this may fail depending on what value the parameter takes + = note: type parameters may not be used in const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: constant expression depends on a generic parameter - --> $DIR/assoc_const.rs:22:19 +error: generic parameters may not be used in const operations + --> $DIR/assoc_const.rs:20:51 | LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ cannot perform const operation using `T` | - = note: this may fail depending on what value the parameter takes - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + = note: type parameters may not be used in const expressions + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/type/pattern_types/assoc_const.rs b/tests/ui/type/pattern_types/assoc_const.rs index 87886587d51..90508801990 100644 --- a/tests/ui/type/pattern_types/assoc_const.rs +++ b/tests/ui/type/pattern_types/assoc_const.rs @@ -15,14 +15,10 @@ trait Foo { } fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {} -//[default]~^ ERROR: constant expression depends on a generic parameter -//[default]~| ERROR: constant expression depends on a generic parameter -//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors -//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors +//[default]~^ ERROR: generic parameters may not be used in const operations +//[default]~| ERROR: generic parameters may not be used in const operations fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {} -//[default]~^ ERROR: constant expression depends on a generic parameter -//[default]~| ERROR: constant expression depends on a generic parameter -//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors -//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors +//[default]~^ ERROR: generic parameters may not be used in const operations +//[default]~| ERROR: generic parameters may not be used in const operations fn main() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index 0f10bf8ce62..c28fda6f91a 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -5,7 +5,7 @@ //@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " //@ rustc-env:RUST_BACKTRACE=0 -#![feature(pattern_types, pattern_type_macro)] +#![feature(pattern_types, pattern_type_macro, generic_const_exprs)] #![allow(internal_features)] type Pat<const START: u32, const END: u32> = diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr index fbe80a19863..ffc6068eb17 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -1,4 +1,11 @@ -error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible +warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/bad_const_generics_args_on_const_param.rs:8:47 + | +LL | #![feature(pattern_types, pattern_type_macro, generic_const_exprs)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information + = error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible --> $DIR/bad_const_generics_args_on_const_param.rs:12:36 | LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); @@ -10,5 +17,5 @@ query stack during panic: #0 [type_of] expanding type alias `Pat` #1 [check_well_formed] checking that `Pat` is well-formed ... and 2 other queries... use `env RUST_BACKTRACE=1` to see the full query stack -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs index 49c87f4fa0d..ed19b10671a 100644 --- a/tests/ui/type/pattern_types/const_block.rs +++ b/tests/ui/type/pattern_types/const_block.rs @@ -1,10 +1,10 @@ #![feature(pattern_types)] #![feature(pattern_type_macro)] #![feature(inline_const_pat)] +//@ check-pass use std::pat::pattern_type; fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} -//~^ ERROR: cycle fn main() {} diff --git a/tests/ui/type/pattern_types/const_block.stderr b/tests/ui/type/pattern_types/const_block.stderr deleted file mode 100644 index 82b616105af..00000000000 --- a/tests/ui/type/pattern_types/const_block.stderr +++ /dev/null @@ -1,72 +0,0 @@ -error[E0391]: cycle detected when evaluating type-level constant - --> $DIR/const_block.rs:7:36 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^^^^^^ - | -note: ...which requires const-evaluating + checking `bar::{constant#2}`... - --> $DIR/const_block.rs:7:36 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^^^^^^ -note: ...which requires caching mir of `bar::{constant#2}` for CTFE... - --> $DIR/const_block.rs:7:36 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^^^^^^ -note: ...which requires elaborating drops for `bar::{constant#2}`... - --> $DIR/const_block.rs:7:36 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^^^^^^ -note: ...which requires borrow-checking `bar::{constant#2}`... - --> $DIR/const_block.rs:7:36 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^^^^^^ -note: ...which requires borrow-checking `bar::{constant#0}`... - --> $DIR/const_block.rs:7:41 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^ -note: ...which requires promoting constants in MIR for `bar::{constant#0}`... - --> $DIR/const_block.rs:7:41 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^ -note: ...which requires const checking `bar::{constant#0}`... - --> $DIR/const_block.rs:7:41 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^ -note: ...which requires building MIR for `bar::{constant#0}`... - --> $DIR/const_block.rs:7:41 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^ -note: ...which requires match-checking `bar::{constant#0}`... - --> $DIR/const_block.rs:7:41 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^ -note: ...which requires type-checking `bar::{constant#0}`... - --> $DIR/const_block.rs:7:41 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^ -note: ...which requires type-checking `bar`... - --> $DIR/const_block.rs:7:1 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires evaluating type-level constant, completing the cycle -note: cycle used when checking that `bar` is well-formed - --> $DIR/const_block.rs:7:1 - | -LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs index b90ba478402..b4f4bd656f5 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs @@ -12,3 +12,4 @@ type Positive = pattern_type!(i32 is 0..); //~^ use of unstable library feature `pattern_type_macro` type Always = pattern_type!(Option<u32> is Some(_)); //~^ use of unstable library feature `pattern_type_macro` +//~| ERROR pattern not supported in pattern types diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr index 69239d68bdc..12508bcb54a 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr @@ -48,6 +48,12 @@ LL | type Always = pattern_type!(Option<u32> is Some(_)); = help: add `#![feature(pattern_type_macro)]` 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 5 previous errors +error: pattern not supported in pattern types + --> $DIR/feature-gate-pattern_types.rs:13:44 + | +LL | type Always = pattern_type!(Option<u32> is Some(_)); + | ^^^^^^^ + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs index 50c355c8de6..c6b4b325fa3 100644 --- a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Zno-analysis -//@ check-pass #![feature(pattern_type_macro)] @@ -10,3 +9,4 @@ type Percent = pattern_type!(u32 is 0..=100); type Negative = pattern_type!(i32 is ..=0); type Positive = pattern_type!(i32 is 0..); type Always = pattern_type!(Option<u32> is Some(_)); +//~^ ERROR: pattern not supported in pattern types diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr new file mode 100644 index 00000000000..81bf9dea0e2 --- /dev/null +++ b/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr @@ -0,0 +1,8 @@ +error: pattern not supported in pattern types + --> $DIR/feature-gate-pattern_types2.rs:11:44 + | +LL | type Always = pattern_type!(Option<u32> is Some(_)); + | ^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 11066c90edb..19ae66f7a07 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -678,7 +678,7 @@ mod types { /*! FIXME: todo */ } /// TyKind::Pat - fn ty_pat() { let _: u32 is 1..; } + fn ty_pat() { let _: u32 is const 1..; } } mod visibilities { /// VisibilityKind::Public |
