diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index deee3a597aed9..29c1d34a125a4 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`, /// just as part of the type system. - Pat(P, P), + Pat(P, P), /// 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, +} + +/// 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>, Option>, Spanned), + + /// 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 a9961cca5833c..de9f049704a4f 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) { + 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(vis: &mut T, ty: &mut P) { 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(vis: &mut T, ty: &mut P) { vis.visit_span(span); } +pub fn walk_ty_pat(vis: &mut T, ty: &mut P) { + 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(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 714b074f930c2..3242d4145959d 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>) -> V::Result { if let Some(qself) = qself { let QSelf { ty, path_span: _, position: _ } = &**qself; diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index bb9b2a13185ba..e1f3afbcf5908 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 eeec24e5ea4e0..0bf5de3ef8985 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 a600a9f316a7a..a55c7e962d098 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, P)> { +fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P, P)> { 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_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 149ded28356b8..66723cbf88206 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 33a956e552fbe..93553f3f3648a 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 ae4c4d5876e2b..58933a77e53d1 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, 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::>(); + 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::>(); - 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 8c94a46ebf305..78b3a7f85417b 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 c6855dd42e531..4a5491ec7a18c 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 ba4fd75fb9418..7fe527a4c07d0 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 2c9f1cda13a8a..54c5d445f66bd 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 bdc83267cca94..cebceef1b93f8 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 3200c94d97703..8b97688590456 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 4d6a76b23ea1a..441d144ce50d6 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 707aeba22ccf7..7becba4ccd4c0 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_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index ffddf6f73aaf0..e58cb2ff59209 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2154,11 +2154,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported") } // FIXME(const_generics): create real const to allow fn items as const paths - Res::Def(DefKind::Fn | DefKind::AssocFn, _) => ty::Const::new_error_with_message( - tcx, - span, - "fn items cannot be used as const args", - ), + Res::Def(DefKind::Fn | DefKind::AssocFn, did) => { + self.dcx().span_delayed_bug(span, "function items cannot be used as const args"); + let args = self.lower_generic_args_of_path_segment( + span, + did, + path.segments.last().unwrap(), + ); + ty::Const::new_value(tcx, ty::ValTree::zst(), Ty::new_fn_def(tcx, did, args)) + } // Exhaustive match to be clear about what exactly we're considering to be // an invalid Res for a const path. diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 55c6a122d35d5..480d97e377a40 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 45b188205d228..636779fe9b4cf 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 d89e615e14ad3..c8de5e877531e 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 601d2fbfb67f2..68b1f435a4cf7 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` 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> { 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/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index feae8ea312eaa..5a88e315b399f 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1800,7 +1800,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } let u8_type = self.tcx().types.u8; - match (cv.valtree, cv.ty.kind()) { + match (cv.valtree, *cv.ty.kind()) { (ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() { ty::Slice(t) if *t == u8_type => { let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| { @@ -1820,13 +1820,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { return Ok(()); } _ => { - let cv = ty::Value { valtree: cv.valtree, ty: *inner_ty }; + let cv = ty::Value { valtree: cv.valtree, ty: inner_ty }; p!("&"); p!(pretty_print_const_valtree(cv, print_ty)); return Ok(()); } }, - (ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => { + (ty::ValTree::Branch(_), ty::Array(t, _)) if t == u8_type => { let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| { bug!("expected to convert valtree to raw bytes for type {:?}", t) }); @@ -1893,11 +1893,16 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } (ty::ValTree::Leaf(leaf), ty::Ref(_, inner_ty, _)) => { p!(write("&")); - return self.pretty_print_const_scalar_int(leaf, *inner_ty, print_ty); + return self.pretty_print_const_scalar_int(leaf, inner_ty, print_ty); } (ty::ValTree::Leaf(leaf), _) => { return self.pretty_print_const_scalar_int(leaf, cv.ty, print_ty); } + (_, ty::FnDef(def_id, args)) => { + // Never allowed today, but we still encounter them in invalid const args. + p!(print_value_path(def_id, args)); + return Ok(()); + } // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading // their fields instead of just dumping the memory. _ => {} diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 508bd831ccbea..03aeb8720ca62 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_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs index dcf9b6b4460f3..1b8f4c1be2dfa 100644 --- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs +++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { base.max_atomic_width = Some(64); // https://developer.android.com/ndk/guides/abis.html#x86 - base.cpu = "pentiumpro".into(); + base.cpu = "pentium4".into(); base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into(); base.stack_probes = StackProbeType::Inline; 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 99b70c87ccd1c..9e7e96dddd7c1 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> 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> 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 = 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/library/core/src/hint.rs b/library/core/src/hint.rs index e5c1a64c12ee5..520b9941ae45d 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -646,7 +646,7 @@ pub const fn must_use(value: T) -> T { /// ``` /// /// -#[unstable(feature = "likely_unlikely", issue = "26179")] +#[unstable(feature = "likely_unlikely", issue = "136873")] #[inline(always)] pub const fn likely(b: bool) -> bool { crate::intrinsics::likely(b) @@ -696,7 +696,7 @@ pub const fn likely(b: bool) -> bool { /// } /// } /// ``` -#[unstable(feature = "likely_unlikely", issue = "26179")] +#[unstable(feature = "likely_unlikely", issue = "136873")] #[inline(always)] pub const fn unlikely(b: bool) -> bool { crate::intrinsics::unlikely(b) @@ -729,7 +729,7 @@ pub const fn unlikely(b: bool) -> bool { /// } /// } /// ``` -#[unstable(feature = "cold_path", issue = "26179")] +#[unstable(feature = "cold_path", issue = "136873")] #[inline(always)] pub const fn cold_path() { crate::intrinsics::cold_path() diff --git a/library/std/src/net/ip_addr.rs b/library/std/src/net/ip_addr.rs index 4d673a1d66db6..7262899b3bbbe 100644 --- a/library/std/src/net/ip_addr.rs +++ b/library/std/src/net/ip_addr.rs @@ -8,32 +8,3 @@ pub use core::net::IpAddr; pub use core::net::Ipv6MulticastScope; #[stable(feature = "rust1", since = "1.0.0")] pub use core::net::{Ipv4Addr, Ipv6Addr}; - -use crate::sys::net::netc as c; -use crate::sys_common::{FromInner, IntoInner}; - -impl IntoInner for Ipv4Addr { - #[inline] - fn into_inner(self) -> c::in_addr { - // `s_addr` is stored as BE on all machines and the array is in BE order. - // So the native endian conversion method is used so that it's never swapped. - c::in_addr { s_addr: u32::from_ne_bytes(self.octets()) } - } -} -impl FromInner for Ipv4Addr { - fn from_inner(addr: c::in_addr) -> Ipv4Addr { - Ipv4Addr::from(addr.s_addr.to_ne_bytes()) - } -} - -impl IntoInner for Ipv6Addr { - fn into_inner(self) -> c::in6_addr { - c::in6_addr { s6_addr: self.octets() } - } -} -impl FromInner for Ipv6Addr { - #[inline] - fn from_inner(addr: c::in6_addr) -> Ipv6Addr { - Ipv6Addr::from(addr.s6_addr) - } -} diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs index e8355cc31d7a5..4c8905c0d4609 100644 --- a/library/std/src/net/socket_addr.rs +++ b/library/std/src/net/socket_addr.rs @@ -6,50 +6,8 @@ mod tests; pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use crate::sys::net::{LookupHost, netc as c}; -use crate::sys_common::{FromInner, IntoInner}; -use crate::{io, iter, mem, option, slice, vec}; - -impl FromInner for SocketAddrV4 { - fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 { - SocketAddrV4::new(Ipv4Addr::from_inner(addr.sin_addr), u16::from_be(addr.sin_port)) - } -} - -impl FromInner for SocketAddrV6 { - fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 { - SocketAddrV6::new( - Ipv6Addr::from_inner(addr.sin6_addr), - u16::from_be(addr.sin6_port), - addr.sin6_flowinfo, - addr.sin6_scope_id, - ) - } -} - -impl IntoInner for SocketAddrV4 { - fn into_inner(self) -> c::sockaddr_in { - c::sockaddr_in { - sin_family: c::AF_INET as c::sa_family_t, - sin_port: self.port().to_be(), - sin_addr: self.ip().into_inner(), - ..unsafe { mem::zeroed() } - } - } -} - -impl IntoInner for SocketAddrV6 { - fn into_inner(self) -> c::sockaddr_in6 { - c::sockaddr_in6 { - sin6_family: c::AF_INET6 as c::sa_family_t, - sin6_port: self.port().to_be(), - sin6_addr: self.ip().into_inner(), - sin6_flowinfo: self.flowinfo(), - sin6_scope_id: self.scope_id(), - ..unsafe { mem::zeroed() } - } - } -} +use crate::sys::net::LookupHost; +use crate::{io, iter, option, slice, vec}; /// A trait for objects which can be converted or resolved to one or more /// [`SocketAddr`] values. diff --git a/library/std/src/os/solid/io.rs b/library/std/src/os/solid/io.rs index b8c3440542d00..ca58a900c4451 100644 --- a/library/std/src/os/solid/io.rs +++ b/library/std/src/os/solid/io.rs @@ -122,7 +122,7 @@ impl BorrowedFd<'_> { /// Creates a new `OwnedFd` instance that shares the same underlying file /// description as the existing `BorrowedFd` instance. pub fn try_clone_to_owned(&self) -> crate::io::Result { - let fd = sys::net::cvt(unsafe { sys::net::netc::dup(self.as_raw_fd()) })?; + let fd = sys::net::cvt(unsafe { crate::sys::abi::sockets::dup(self.as_raw_fd()) })?; Ok(unsafe { OwnedFd::from_raw_fd(fd) }) } } @@ -168,7 +168,7 @@ impl FromRawFd for OwnedFd { impl Drop for OwnedFd { #[inline] fn drop(&mut self) { - unsafe { sys::net::netc::close(self.fd.as_inner()) }; + unsafe { crate::sys::abi::sockets::close(self.fd.as_inner()) }; } } diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs index b390a5eac5f74..242df10bc3270 100644 --- a/library/std/src/sys/net/connection/sgx.rs +++ b/library/std/src/sys/net/connection/sgx.rs @@ -499,38 +499,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost { LookupHost::new(format!("{host}:{port}")) } } - -#[allow(bad_style)] -pub mod netc { - pub const AF_INET: u8 = 0; - pub const AF_INET6: u8 = 1; - pub type sa_family_t = u8; - - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: u32, - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in { - #[allow(dead_code)] - pub sin_family: sa_family_t, - pub sin_port: u16, - pub sin_addr: in_addr, - } - - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u8; 16], - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - #[allow(dead_code)] - pub sin6_family: sa_family_t, - pub sin6_port: u16, - pub sin6_addr: in6_addr, - pub sin6_flowinfo: u32, - pub sin6_scope_id: u32, - } -} diff --git a/library/std/src/sys/net/connection/socket.rs b/library/std/src/sys/net/connection/socket.rs index 6fe3430b53f79..b4f0a7836803e 100644 --- a/library/std/src/sys/net/connection/socket.rs +++ b/library/std/src/sys/net/connection/socket.rs @@ -3,9 +3,9 @@ mod tests; use crate::ffi::{c_int, c_void}; use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; -use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; use crate::sys::common::small_c_string::run_with_cstr; -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner}; use crate::time::Duration; use crate::{cmp, fmt, mem, ptr}; @@ -79,6 +79,111 @@ cfg_if::cfg_if! { } } +//////////////////////////////////////////////////////////////////////////////// +// address conversions +//////////////////////////////////////////////////////////////////////////////// + +fn ip_v4_addr_to_c(addr: &Ipv4Addr) -> c::in_addr { + // `s_addr` is stored as BE on all machines and the array is in BE order. + // So the native endian conversion method is used so that it's never swapped. + c::in_addr { s_addr: u32::from_ne_bytes(addr.octets()) } +} + +fn ip_v6_addr_to_c(addr: &Ipv6Addr) -> c::in6_addr { + c::in6_addr { s6_addr: addr.octets() } +} + +fn ip_v4_addr_from_c(addr: c::in_addr) -> Ipv4Addr { + Ipv4Addr::from(addr.s_addr.to_ne_bytes()) +} + +fn ip_v6_addr_from_c(addr: c::in6_addr) -> Ipv6Addr { + Ipv6Addr::from(addr.s6_addr) +} + +fn socket_addr_v4_to_c(addr: &SocketAddrV4) -> c::sockaddr_in { + c::sockaddr_in { + sin_family: c::AF_INET as c::sa_family_t, + sin_port: addr.port().to_be(), + sin_addr: ip_v4_addr_to_c(addr.ip()), + ..unsafe { mem::zeroed() } + } +} + +fn socket_addr_v6_to_c(addr: &SocketAddrV6) -> c::sockaddr_in6 { + c::sockaddr_in6 { + sin6_family: c::AF_INET6 as c::sa_family_t, + sin6_port: addr.port().to_be(), + sin6_addr: ip_v6_addr_to_c(addr.ip()), + sin6_flowinfo: addr.flowinfo(), + sin6_scope_id: addr.scope_id(), + ..unsafe { mem::zeroed() } + } +} + +fn socket_addr_v4_from_c(addr: c::sockaddr_in) -> SocketAddrV4 { + SocketAddrV4::new(ip_v4_addr_from_c(addr.sin_addr), u16::from_be(addr.sin_port)) +} + +fn socket_addr_v6_from_c(addr: c::sockaddr_in6) -> SocketAddrV6 { + SocketAddrV6::new( + ip_v6_addr_from_c(addr.sin6_addr), + u16::from_be(addr.sin6_port), + addr.sin6_flowinfo, + addr.sin6_scope_id, + ) +} + +/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level +/// SocketAddr* types into their system representation. The benefit of this specific +/// type over using `c::sockaddr_storage` is that this type is exactly as large as it +/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust. +#[repr(C)] +union SocketAddrCRepr { + v4: c::sockaddr_in, + v6: c::sockaddr_in6, +} + +impl SocketAddrCRepr { + fn as_ptr(&self) -> *const c::sockaddr { + self as *const _ as *const c::sockaddr + } +} + +fn socket_addr_to_c(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) { + match addr { + SocketAddr::V4(a) => { + let sockaddr = SocketAddrCRepr { v4: socket_addr_v4_to_c(a) }; + (sockaddr, mem::size_of::() as c::socklen_t) + } + SocketAddr::V6(a) => { + let sockaddr = SocketAddrCRepr { v6: socket_addr_v6_to_c(a) }; + (sockaddr, mem::size_of::() as c::socklen_t) + } + } +} + +unsafe fn socket_addr_from_c( + storage: *const c::sockaddr_storage, + len: usize, +) -> io::Result { + match (*storage).ss_family as c_int { + c::AF_INET => { + assert!(len >= mem::size_of::()); + Ok(SocketAddr::V4(socket_addr_v4_from_c(unsafe { + *(storage as *const _ as *const c::sockaddr_in) + }))) + } + c::AF_INET6 => { + assert!(len >= mem::size_of::()); + Ok(SocketAddr::V6(socket_addr_v6_from_c(unsafe { + *(storage as *const _ as *const c::sockaddr_in6) + }))) + } + _ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")), + } +} + //////////////////////////////////////////////////////////////////////////////// // sockaddr and misc bindings //////////////////////////////////////////////////////////////////////////////// @@ -124,25 +229,7 @@ where let mut storage: c::sockaddr_storage = mem::zeroed(); let mut len = mem::size_of_val(&storage) as c::socklen_t; cvt(f((&raw mut storage) as *mut _, &mut len))?; - sockaddr_to_addr(&storage, len as usize) - } -} - -pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result { - match storage.ss_family as c_int { - c::AF_INET => { - assert!(len >= mem::size_of::()); - Ok(SocketAddr::V4(FromInner::from_inner(unsafe { - *(storage as *const _ as *const c::sockaddr_in) - }))) - } - c::AF_INET6 => { - assert!(len >= mem::size_of::()); - Ok(SocketAddr::V6(FromInner::from_inner(unsafe { - *(storage as *const _ as *const c::sockaddr_in6) - }))) - } - _ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")), + socket_addr_from_c(&storage, len as usize) } } @@ -179,7 +266,7 @@ impl Iterator for LookupHost { unsafe { let cur = self.cur.as_ref()?; self.cur = cur.ai_next; - match sockaddr_to_addr(mem::transmute(cur.ai_addr), cur.ai_addrlen as usize) { + match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) { Ok(addr) => return Some(addr), Err(_) => continue, } @@ -432,7 +519,7 @@ impl TcpListener { setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?; // Bind our new socket - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; cfg_if::cfg_if! { @@ -473,7 +560,7 @@ impl TcpListener { let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() }; let mut len = mem::size_of_val(&storage) as c::socklen_t; let sock = self.inner.accept((&raw mut storage) as *mut _, &mut len)?; - let addr = sockaddr_to_addr(&storage, len as usize)?; + let addr = unsafe { socket_addr_from_c(&storage, len as usize)? }; Ok((TcpStream { inner: sock }, addr)) } @@ -542,7 +629,7 @@ impl UdpSocket { init(); let sock = Socket::new(addr, c::SOCK_DGRAM)?; - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?; Ok(UdpSocket { inner: sock }) } @@ -574,7 +661,7 @@ impl UdpSocket { pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result { let len = cmp::min(buf.len(), ::MAX as usize) as wrlen_t; - let (dst, dstlen) = dst.into_inner(); + let (dst, dstlen) = socket_addr_to_c(dst); let ret = cvt(unsafe { c::sendto( self.inner.as_raw(), @@ -656,15 +743,15 @@ impl UdpSocket { pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { let mreq = c::ip_mreq { - imr_multiaddr: multiaddr.into_inner(), - imr_interface: interface.into_inner(), + imr_multiaddr: ip_v4_addr_to_c(multiaddr), + imr_interface: ip_v4_addr_to_c(interface), }; setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) } pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { let mreq = c::ipv6_mreq { - ipv6mr_multiaddr: multiaddr.into_inner(), + ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr), ipv6mr_interface: to_ipv6mr_interface(interface), }; setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) @@ -672,15 +759,15 @@ impl UdpSocket { pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { let mreq = c::ip_mreq { - imr_multiaddr: multiaddr.into_inner(), - imr_interface: interface.into_inner(), + imr_multiaddr: ip_v4_addr_to_c(multiaddr), + imr_interface: ip_v4_addr_to_c(interface), }; setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) } pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { let mreq = c::ipv6_mreq { - ipv6mr_multiaddr: multiaddr.into_inner(), + ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr), ipv6mr_interface: to_ipv6mr_interface(interface), }; setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) @@ -720,7 +807,7 @@ impl UdpSocket { } pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> { - let (addr, len) = addr?.into_inner(); + let (addr, len) = socket_addr_to_c(addr?); cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop) } } @@ -743,38 +830,3 @@ impl fmt::Debug for UdpSocket { res.field(name, &self.inner.as_raw()).finish() } } - -//////////////////////////////////////////////////////////////////////////////// -// Converting SocketAddr to libc representation -//////////////////////////////////////////////////////////////////////////////// - -/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level -/// SocketAddr* types into their system representation. The benefit of this specific -/// type over using `c::sockaddr_storage` is that this type is exactly as large as it -/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust. -#[repr(C)] -pub(crate) union SocketAddrCRepr { - v4: c::sockaddr_in, - v6: c::sockaddr_in6, -} - -impl SocketAddrCRepr { - pub fn as_ptr(&self) -> *const c::sockaddr { - self as *const _ as *const c::sockaddr - } -} - -impl<'a> IntoInner<(SocketAddrCRepr, c::socklen_t)> for &'a SocketAddr { - fn into_inner(self) -> (SocketAddrCRepr, c::socklen_t) { - match *self { - SocketAddr::V4(ref a) => { - let sockaddr = SocketAddrCRepr { v4: a.into_inner() }; - (sockaddr, mem::size_of::() as c::socklen_t) - } - SocketAddr::V6(ref a) => { - let sockaddr = SocketAddrCRepr { v6: a.into_inner() }; - (sockaddr, mem::size_of::() as c::socklen_t) - } - } - } -} diff --git a/library/std/src/sys/net/connection/socket/hermit.rs b/library/std/src/sys/net/connection/socket/hermit.rs index 42179dcc9156d..e393342ced9da 100644 --- a/library/std/src/sys/net/connection/socket/hermit.rs +++ b/library/std/src/sys/net/connection/socket/hermit.rs @@ -2,13 +2,13 @@ use core::ffi::c_int; -pub(crate) use hermit_abi as netc; +pub(super) use hermit_abi as netc; +use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c}; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd}; use crate::sys::fd::FileDesc; -use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys::time::Instant; pub use crate::sys::{cvt, cvt_r}; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -55,7 +55,7 @@ impl Socket { } pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; Ok(()) } @@ -63,7 +63,7 @@ impl Socket { pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let r = unsafe { - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); cvt(netc::connect(self.as_raw_fd(), addr.as_ptr(), len)) }; self.set_nonblocking(false)?; @@ -195,7 +195,7 @@ impl Socket { &mut addrlen, ) })?; - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? })) } pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { diff --git a/library/std/src/sys/net/connection/socket/solid.rs b/library/std/src/sys/net/connection/socket/solid.rs index f85ecbb883ee7..906bef267b6f0 100644 --- a/library/std/src/sys/net/connection/socket/solid.rs +++ b/library/std/src/sys/net/connection/socket/solid.rs @@ -1,17 +1,17 @@ use libc::{c_int, c_void, size_t}; use self::netc::{MSG_PEEK, sockaddr, socklen_t}; +use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c}; use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::solid::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd}; use crate::sys::abi; -use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys_common::{FromInner, IntoInner}; use crate::time::Duration; use crate::{cmp, mem, ptr, str}; -pub mod netc { +pub(super) mod netc { pub use crate::sys::abi::sockets::*; } @@ -131,7 +131,7 @@ impl Socket { } pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); cvt(unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; Ok(()) } @@ -256,7 +256,7 @@ impl Socket { &mut addrlen, ) })?; - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? })) } pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index da6316055273f..34ab26bc117af 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -5,7 +5,7 @@ use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::sys::fd::FileDesc; -use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; +use crate::sys::net::{getsockopt, setsockopt}; use crate::sys::pal::IsMinusOne; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; @@ -19,8 +19,9 @@ cfg_if::cfg_if! { } } -pub(crate) use libc as netc; +pub(super) use libc as netc; +use super::{socket_addr_from_c, socket_addr_to_c}; pub use crate::sys::{cvt, cvt_r}; #[expect(non_camel_case_types)] @@ -150,7 +151,7 @@ impl Socket { } pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); loop { let result = unsafe { libc::connect(self.as_raw_fd(), addr.as_ptr(), len) }; if result.is_minus_one() { @@ -168,7 +169,7 @@ impl Socket { pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { self.set_nonblocking(true)?; let r = unsafe { - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); cvt(libc::connect(self.as_raw_fd(), addr.as_ptr(), len)) }; self.set_nonblocking(false)?; @@ -334,7 +335,7 @@ impl Socket { &mut addrlen, ) })?; - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? })) } pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { diff --git a/library/std/src/sys/net/connection/socket/wasip2.rs b/library/std/src/sys/net/connection/socket/wasip2.rs index 9d1c05a473e4d..c5034e73dd704 100644 --- a/library/std/src/sys/net/connection/socket/wasip2.rs +++ b/library/std/src/sys/net/connection/socket/wasip2.rs @@ -1,19 +1,18 @@ #![deny(unsafe_op_in_unsafe_fn)] +pub(super) use libc as netc; use libc::{c_int, c_void, size_t}; +use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c}; use crate::ffi::CStr; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; -use crate::sys::net::{getsockopt, setsockopt, sockaddr_to_addr}; use crate::sys::unsupported; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::time::{Duration, Instant}; use crate::{cmp, mem, str}; -pub extern crate libc as netc; - #[allow(non_camel_case_types)] pub type wrlen_t = size_t; @@ -89,7 +88,7 @@ impl Socket { } pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); cvt_r(|| unsafe { netc::connect(self.as_raw_fd(), addr.as_ptr(), len) })?; Ok(()) } @@ -224,7 +223,7 @@ impl Socket { &mut addrlen, ) })?; - Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) + Ok((n as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? })) } pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { diff --git a/library/std/src/sys/net/connection/socket/windows.rs b/library/std/src/sys/net/connection/socket/windows.rs index 80cf37eaf0580..428f142dabe20 100644 --- a/library/std/src/sys/net/connection/socket/windows.rs +++ b/library/std/src/sys/net/connection/socket/windows.rs @@ -2,6 +2,7 @@ use core::ffi::{c_int, c_long, c_ulong, c_ushort}; +use super::{getsockopt, setsockopt, socket_addr_from_c, socket_addr_to_c}; use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut, Read}; use crate::net::{Shutdown, SocketAddr}; use crate::os::windows::io::{ @@ -16,7 +17,7 @@ use crate::{cmp, mem, ptr, sys}; #[allow(non_camel_case_types)] pub type wrlen_t = i32; -pub mod netc { +pub(super) mod netc { //! BSD socket compatibility shim //! //! Some Windows API types are not quite what's expected by our cross-platform @@ -225,7 +226,7 @@ impl Socket { } pub fn connect(&self, addr: &SocketAddr) -> io::Result<()> { - let (addr, len) = addr.into_inner(); + let (addr, len) = socket_addr_to_c(addr); let result = unsafe { c::connect(self.as_raw(), addr.as_ptr(), len) }; cvt(result).map(drop) } @@ -401,12 +402,12 @@ impl Socket { let error = unsafe { c::WSAGetLastError() }; if error == c::WSAESHUTDOWN { - Ok((0, super::sockaddr_to_addr(&storage, addrlen as usize)?)) + Ok((0, unsafe { socket_addr_from_c(&storage, addrlen as usize)? })) } else { Err(io::Error::from_raw_os_error(error)) } } - _ => Ok((result as usize, super::sockaddr_to_addr(&storage, addrlen as usize)?)), + _ => Ok((result as usize, unsafe { socket_addr_from_c(&storage, addrlen as usize)? })), } } @@ -451,11 +452,11 @@ impl Socket { } None => 0, }; - super::setsockopt(self, c::SOL_SOCKET, kind, timeout) + setsockopt(self, c::SOL_SOCKET, kind, timeout) } pub fn timeout(&self, kind: c_int) -> io::Result> { - let raw: u32 = super::getsockopt(self, c::SOL_SOCKET, kind)?; + let raw: u32 = getsockopt(self, c::SOL_SOCKET, kind)?; if raw == 0 { Ok(None) } else { @@ -488,26 +489,26 @@ impl Socket { l_linger: linger.unwrap_or_default().as_secs() as c_ushort, }; - super::setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger) + setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger) } pub fn linger(&self) -> io::Result> { - let val: c::LINGER = super::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?; + let val: c::LINGER = getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?; Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64))) } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { - super::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL) + setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BOOL) } pub fn nodelay(&self) -> io::Result { - let raw: c::BOOL = super::getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?; + let raw: c::BOOL = getsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY)?; Ok(raw != 0) } pub fn take_error(&self) -> io::Result> { - let raw: c_int = super::getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?; + let raw: c_int = getsockopt(self, c::SOL_SOCKET, c::SO_ERROR)?; if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) } } diff --git a/library/std/src/sys/net/connection/unsupported.rs b/library/std/src/sys/net/connection/unsupported.rs index 87e6106468fdb..da2174396266f 100644 --- a/library/std/src/sys/net/connection/unsupported.rs +++ b/library/std/src/sys/net/connection/unsupported.rs @@ -332,38 +332,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost { unsupported() } } - -#[allow(nonstandard_style)] -pub mod netc { - pub const AF_INET: u8 = 0; - pub const AF_INET6: u8 = 1; - pub type sa_family_t = u8; - - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: u32, - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in { - #[allow(dead_code)] - pub sin_family: sa_family_t, - pub sin_port: u16, - pub sin_addr: in_addr, - } - - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u8; 16], - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - #[allow(dead_code)] - pub sin6_family: sa_family_t, - pub sin6_port: u16, - pub sin6_addr: in6_addr, - pub sin6_flowinfo: u32, - pub sin6_scope_id: u32, - } -} diff --git a/library/std/src/sys/net/connection/wasip1.rs b/library/std/src/sys/net/connection/wasip1.rs index 27e3a528af497..951dc65e5b47d 100644 --- a/library/std/src/sys/net/connection/wasip1.rs +++ b/library/std/src/sys/net/connection/wasip1.rs @@ -505,38 +505,3 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost { unsupported() } } - -#[allow(nonstandard_style)] -pub mod netc { - pub const AF_INET: u8 = 0; - pub const AF_INET6: u8 = 1; - pub type sa_family_t = u8; - - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: u32, - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in { - #[allow(dead_code)] - pub sin_family: sa_family_t, - pub sin_port: u16, - pub sin_addr: in_addr, - } - - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u8; 16], - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - #[allow(dead_code)] - pub sin6_family: sa_family_t, - pub sin6_port: u16, - pub sin6_addr: in6_addr, - pub sin6_flowinfo: u32, - pub sin6_scope_id: u32, - } -} diff --git a/library/std/src/sys/net/connection/xous/mod.rs b/library/std/src/sys/net/connection/xous/mod.rs index 3e18ed24208d3..e44a375b9e3c5 100644 --- a/library/std/src/sys/net/connection/xous/mod.rs +++ b/library/std/src/sys/net/connection/xous/mod.rs @@ -46,38 +46,3 @@ pub struct GetAddress { } pub use dns::LookupHost; - -#[allow(nonstandard_style)] -pub mod netc { - pub const AF_INET: u8 = 0; - pub const AF_INET6: u8 = 1; - pub type sa_family_t = u8; - - #[derive(Copy, Clone)] - pub struct in_addr { - pub s_addr: u32, - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in { - #[allow(dead_code)] - pub sin_family: sa_family_t, - pub sin_port: u16, - pub sin_addr: in_addr, - } - - #[derive(Copy, Clone)] - pub struct in6_addr { - pub s6_addr: [u8; 16], - } - - #[derive(Copy, Clone)] - pub struct sockaddr_in6 { - #[allow(dead_code)] - pub sin6_family: sa_family_t, - pub sin6_port: u16, - pub sin6_addr: in6_addr, - pub sin6_flowinfo: u32, - pub sin6_scope_id: u32, - } -} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 05555f537c962..a086498fcbdce 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -165,7 +165,7 @@ target | std | notes `i586-pc-windows-msvc` | * | 32-bit Windows (original Pentium) [^x86_32-floats-x87] `i586-unknown-linux-gnu` | ✓ | 32-bit Linux (kernel 3.2, glibc 2.17, original Pentium) [^x86_32-floats-x87] `i586-unknown-linux-musl` | ✓ | 32-bit Linux (musl 1.2.3, original Pentium) [^x86_32-floats-x87] -[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android ([PentiumPro with SSE](https://developer.android.com/ndk/guides/abis.html#x86)) [^x86_32-floats-return-ABI] +[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android ([Pentium 4 plus various extensions](https://developer.android.com/ndk/guides/abis.html#x86)) [^x86_32-floats-return-ABI] [`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 32-bit x86 MinGW (Windows 10+, Pentium 4), LLVM ABI [^x86_32-floats-return-ABI] [`i686-unknown-freebsd`](platform-support/freebsd.md) | ✓ | 32-bit x86 FreeBSD (Pentium 4) [^x86_32-floats-return-ABI] `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 (Pentium 4) [^x86_32-floats-return-ABI] diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index 1d88726d94586..bafed41e39f42 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>, - pub(crate) span: Span, +pub(crate) struct RangeOperand<'a, T> { + pub operand: &'a Option>, + 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 { 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( + context: &RewriteContext<'_>, + shape: Shape, + lhs: &Option>, + rhs: &Option>, + end_kind: &rustc_span::source_map::Spanned, + 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>, path: &ast::Path, diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 6b3e40b91150d..e93eb53cd87f1 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 f8b713117f4c9..0009490e86fee 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 { + 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/ui/const-generics/mgca/unexpected-fn-item-in-array.rs b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs new file mode 100644 index 0000000000000..1c3274f6a3764 --- /dev/null +++ b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs @@ -0,0 +1,13 @@ +// Make sure we don't ICE when encountering an fn item during lowering in mGCA. + +#![feature(min_generic_const_args)] +//~^ WARN the feature `min_generic_const_args` is incomplete + +trait A {} + +impl A<[usize; fn_item]> for () {} +//~^ ERROR the constant `fn_item` is not of type `usize` + +fn fn_item() {} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr new file mode 100644 index 0000000000000..89fc8270e3e74 --- /dev/null +++ b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.stderr @@ -0,0 +1,19 @@ +warning: the feature `min_generic_const_args` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/unexpected-fn-item-in-array.rs:3:12 + | +LL | #![feature(min_generic_const_args)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #132980 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: the constant `fn_item` is not of type `usize` + --> $DIR/unexpected-fn-item-in-array.rs:8:6 + | +LL | impl A<[usize; fn_item]> for () {} + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found fn item + | + = note: the length of array `[usize; fn_item]` must be type `usize` + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr index a16e832f8ef91..ee17f7737cf30 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 4e9a74c1e403d..1ec8a33eb8205 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: T, k: K) -> Foo { | ^^^^^^^ 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 = foo(1, ""); - | ++++++++++++++++++++++ +LL | let foo: Foo<_, &_, W, Z> = foo(1, ""); + | ++++++++++++++++++ error[E0283]: type annotations needed for `Bar` --> $DIR/erase-type-params-in-label.rs:5:9 @@ -29,8 +29,8 @@ LL | fn bar(t: T, k: K) -> Bar { | ^^^^^^^ 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 = 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 391ed16f349d7..27382e301341f 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, Error>> = A(Result::Ok(Result::Ok(()))); - | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +LL | let a: A, _>> = 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 69d1d71ef3cc0..97ccad9e785e3 100644 --- a/tests/ui/inference/issue-83606.stderr +++ b/tests/ui/inference/issue-83606.stderr @@ -11,8 +11,8 @@ LL | fn foo(_: 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 0000000000000..4fd15eea9e0f1 --- /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 0000000000000..65fe2ffcb7f16 --- /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 = 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 9bbb20246df9d..e4477c9620221 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; + fn pt_non_zero_usize_opt_full_range() -> Option; + //~^ 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; + } + } + 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 48dd1adbc1fa2..118b18b224c05 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`, which is not FFI-safe + --> $DIR/clashing-extern-fn.rs:502:54 + | +LL | fn pt_non_zero_usize_opt_full_range() -> Option; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 usize` found `unsafe extern "C" fn() -> Option>>` -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 19af1de95760b..0d19d5b534713 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>>); //~^ ERROR `extern` block uses type fn option_repr_rust(x: Option>>); //~ ERROR `extern` block uses type + fn option_u8(x: Option); //~ ERROR `extern` block uses type fn result_ref_t(x: Result<&'static u8, ()>); fn result_fn_t(x: Result); diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr index 8e92e7e694627..a491bd1960563 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>>); = 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`, which is not FFI-safe + --> $DIR/lint-ctypes-enum.rs:97:21 + | +LL | fn option_u8(x: Option); + | ^^^^^^^^^^ 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, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -88,7 +97,7 @@ LL | fn result_nonzero_u128_t(x: Result, ()>); = 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, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -96,7 +105,7 @@ LL | fn result_nonzero_i128_t(x: Result, ()>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result>, ()>`, 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>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -105,7 +114,7 @@ LL | fn result_transparent_union_t(x: Result>, ()>`, 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>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -114,7 +123,7 @@ LL | fn result_repr_rust_t(x: Result>, ()>); = note: enum has no representation hint error: `extern` block uses type `Result, 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, U>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -123,7 +132,7 @@ LL | fn result_1zst_exhaustive_single_variant_t(x: Result, = note: enum has no representation hint error: `extern` block uses type `Result, 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, B>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -132,7 +141,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result = note: enum has no representation hint error: `extern` block uses type `Result, 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, NonExhaustive>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -141,7 +150,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result, = note: enum has no representation hint error: `extern` block uses type `Result, 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, Field>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -150,7 +159,7 @@ LL | fn result_1zst_exhaustive_single_field_t(x: Result, Fi = note: enum has no representation hint error: `extern` block uses type `Result>, ()>`, 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>, ()>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -159,7 +168,7 @@ LL | fn result_cascading_t(x: Result>, ()>); = 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>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -167,7 +176,7 @@ LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero>); = 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>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -175,7 +184,7 @@ LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero>); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `Result<(), TransparentUnion>>`, 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>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -184,7 +193,7 @@ LL | fn result_transparent_union_e(x: Result<(), TransparentUnion>>`, 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>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -193,7 +202,7 @@ LL | fn result_repr_rust_e(x: Result<(), Rust>>); = note: enum has no representation hint error: `extern` block uses type `Result>`, 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>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -202,7 +211,7 @@ LL | fn result_1zst_exhaustive_single_variant_e(x: Result>`, 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>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -211,7 +220,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result>`, 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>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -220,7 +229,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result>`, 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>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -229,7 +238,7 @@ LL | fn result_1zst_exhaustive_single_field_e(x: Result>>`, 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>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -238,7 +247,7 @@ LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero>>); = 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 3176a2d490ebc..9bcd07f8bf164 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 { - | +++++++++++++++++++ +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 c5d9691a02918..8cff0cee7b972 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(_: pattern_type!(u32 is ::START..=::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ cannot perform const operation using `T` | - = note: see issue #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(_: pattern_type!(u32 is ::START..=::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ cannot perform const operation using `T` | - = note: see issue #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(_: pattern_type!(u32 is ::START..=::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(_: pattern_type!(u32 is ::START..=::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(_: pattern_type!(u32 is T::START..=T::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #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(_: pattern_type!(u32 is T::START..=T::END)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #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(_: 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(_: 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 87886587d5153..90508801990e8 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(_: pattern_type!(u32 is ::START..=::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(_: 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 0f10bf8ce627c..c28fda6f91aea 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 = 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 fbe80a19863db..ffc6068eb17e1 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 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 49c87f4fa0d65..ed19b10671af0 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 82b616105afa7..0000000000000 --- 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 b90ba4784023a..b4f4bd656f5ff 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 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 69239d68bdc75..12508bcb54a34 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 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 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 50c355c8de61a..c6b4b325fa35a 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 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 0000000000000..81bf9dea0e2fd --- /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 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 11066c90edb77..19ae66f7a07aa 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