1
Fork 0

Auto merge of #136905 - matthiaskrgr:rollup-8zwcgta, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #135549 (Document some safety constraints and use more safe wrappers)
 - #135965 (In "specify type" suggestion, skip type params that are already known)
 - #136193 (Implement pattern type ffi checks)
 - #136646 (Add a TyPat in the AST to reuse the generic arg lowering logic)
 - #136874 (Change the issue number for `likely_unlikely` and `cold_path`)
 - #136884 (Lower fn items as ZST valtrees and delay a bug)
 - #136885 (i686-linux-android: increase CPU baseline to Pentium 4 (without an actual change)
 - #136891 (Check sig for errors before checking for unconstrained anonymous lifetime)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-02-12 06:54:18 +00:00
commit 33d92df3e6
57 changed files with 739 additions and 557 deletions

View file

@ -2249,7 +2249,7 @@ pub enum TyKind {
CVarArgs, CVarArgs,
/// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`, /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
/// just as part of the type system. /// just as part of the type system.
Pat(P<Ty>, P<Pat>), Pat(P<Ty>, P<TyPat>),
/// Sometimes we need a dummy value when no error has occurred. /// Sometimes we need a dummy value when no error has occurred.
Dummy, Dummy,
/// Placeholder for a kind that has failed to be defined. /// Placeholder for a kind that has failed to be defined.
@ -2277,6 +2277,27 @@ impl TyKind {
} }
} }
/// A pattern type pattern.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct TyPat {
pub id: NodeId,
pub kind: TyPatKind,
pub span: Span,
pub tokens: Option<LazyAttrTokenStream>,
}
/// All the different flavors of pattern that Rust recognizes.
//
// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum TyPatKind {
/// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
Range(Option<P<AnonConst>>, Option<P<AnonConst>>, Spanned<RangeEnd>),
/// Placeholder for a pattern that wasn't syntactically well formed in some way.
Err(ErrorGuaranteed),
}
/// Syntax used to declare a trait object. /// Syntax used to declare a trait object.
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
#[repr(u8)] #[repr(u8)]

View file

@ -210,6 +210,10 @@ pub trait MutVisitor: Sized {
walk_ty(self, t); walk_ty(self, t);
} }
fn visit_ty_pat(&mut self, t: &mut P<TyPat>) {
walk_ty_pat(self, t);
}
fn visit_lifetime(&mut self, l: &mut Lifetime) { fn visit_lifetime(&mut self, l: &mut Lifetime) {
walk_lifetime(self, l); walk_lifetime(self, l);
} }
@ -570,7 +574,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
TyKind::Paren(ty) => vis.visit_ty(ty), TyKind::Paren(ty) => vis.visit_ty(ty),
TyKind::Pat(ty, pat) => { TyKind::Pat(ty, pat) => {
vis.visit_ty(ty); vis.visit_ty(ty);
vis.visit_pat(pat); vis.visit_ty_pat(pat);
} }
TyKind::Path(qself, path) => { TyKind::Path(qself, path) => {
vis.visit_qself(qself); vis.visit_qself(qself);
@ -594,6 +598,20 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
vis.visit_span(span); vis.visit_span(span);
} }
pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
let TyPat { id, kind, span, tokens } = ty.deref_mut();
vis.visit_id(id);
match kind {
TyPatKind::Range(start, end, _include_end) => {
visit_opt(start, |c| vis.visit_anon_const(c));
visit_opt(end, |c| vis.visit_anon_const(c));
}
TyPatKind::Err(_) => {}
}
visit_lazy_tts(vis, tokens);
vis.visit_span(span);
}
fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) { fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) {
let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod; let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
visit_safety(vis, safety); visit_safety(vis, safety);

View file

@ -179,6 +179,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result { fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result {
walk_ty(self, t) 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 { fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result {
walk_generic_param(self, param) 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) => { TyKind::Pat(ty, pat) => {
try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_ty(ty));
try_visit!(visitor.visit_pat(pat)); try_visit!(visitor.visit_ty_pat(pat));
} }
TyKind::Array(ty, length) => { TyKind::Array(ty, length) => {
try_visit!(visitor.visit_ty(ty)); 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() V::Result::output()
} }
pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Result {
let TyPat { id: _, kind, span: _, tokens: _ } = tp;
match kind {
TyPatKind::Range(start, end, _include_end) => {
visit_opt!(visitor, visit_anon_const, start);
visit_opt!(visitor, visit_anon_const, end);
}
TyPatKind::Err(_) => {}
}
V::Result::output()
}
fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result { fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result {
if let Some(qself) = qself { if let Some(qself) = qself {
let QSelf { ty, path_span: _, position: _ } = &**qself; let QSelf { ty, path_span: _, position: _ } = &**qself;

View file

@ -4,10 +4,10 @@ use rustc_ast::ptr::P;
use rustc_ast::*; use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::Res;
use rustc_middle::span_bug; use rustc_middle::span_bug;
use rustc_span::source_map::{Spanned, respan}; use rustc_span::source_map::{Spanned, respan};
use rustc_span::{Ident, Span, kw}; use rustc_span::{Ident, Span};
use super::errors::{ use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, 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 }) 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)) 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 // loop here to avoid recursion
let pat_hir_id = self.lower_node_id(pattern.id); let pat_hir_id = self.lower_node_id(pattern.id);
let node = loop { let node = match &pattern.kind {
match &pattern.kind { TyPatKind::Range(e1, e2, Spanned { node: end, .. }) => hir::TyPatKind::Range(
PatKind::Range(e1, e2, Spanned { node: end, .. }) => { e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
// FIXME(pattern_types): remove this closure and call `lower_const_arg` instead. e2.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
// That requires first modifying the AST to have const args here. self.lower_range_end(end, e2.is_some()),
let mut lower_expr = |e: &Expr| -> &_ { ),
if let ExprKind::Path(None, path) = &e.kind TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar),
&& 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"),
);
}
}
}; };
hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) } hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }

View file

@ -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) { pub fn print_type(&mut self, ty: &ast::Ty) {
self.maybe_print_comment(ty.span.lo()); self.maybe_print_comment(ty.span.lo());
self.ibox(0); self.ibox(0);
@ -1252,7 +1274,7 @@ impl<'a> State<'a> {
ast::TyKind::Pat(ty, pat) => { ast::TyKind::Pat(ty, pat) => {
self.print_type(ty); self.print_type(ty);
self.word(" is "); self.word(" is ");
self.print_pat(pat); self.print_ty_pat(pat);
} }
} }
self.end(); self.end();

View file

@ -1,6 +1,6 @@
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream; 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_errors::PResult;
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_parse::exp; 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)))) ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
} }
fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<Pat>)> { fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> {
let mut parser = cx.new_parser_from_tts(stream); let mut parser = cx.new_parser_from_tts(stream);
let ty = parser.parse_ty()?; let ty = parser.parse_ty()?;
parser.expect_keyword(exp!(Is))?; 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)) Ok((ty, pat))
} }

View file

@ -81,13 +81,13 @@ pub(crate) unsafe fn codegen(
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
let val = tcx.sess.opts.unstable_opts.oom.should_panic(); let val = tcx.sess.opts.unstable_opts.oom.should_panic();
let llval = llvm::LLVMConstInt(i8, val as u64, False); 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 name = NO_ALLOC_SHIM_IS_UNSTABLE;
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_c_char_ptr(), name.len(), i8); 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())); llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
let llval = llvm::LLVMConstInt(i8, 0, False); 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 { if tcx.sess.opts.debuginfo != DebugInfo::None {

View file

@ -11,7 +11,7 @@ use rustc_codegen_ssa::back::archive::{
use rustc_session::Session; use rustc_session::Session;
use crate::llvm::archive_ro::{ArchiveRO, Child}; 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. /// Helper for adding many files to an archive.
#[must_use = "must call build() to finish building the 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 })); .unwrap_or_else(|kind| self.sess.dcx().emit_fatal(UnknownArchiveKind { kind }));
let mut additions = mem::take(&mut self.additions); 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 strings = Vec::new();
let mut members = Vec::new(); let mut members = Vec::new();
@ -229,12 +231,7 @@ impl<'a> LlvmArchiveBuilder<'a> {
self.sess.target.arch == "arm64ec", self.sess.target.arch == "arm64ec",
); );
let ret = if r.into_result().is_err() { let ret = if r.into_result().is_err() {
let err = llvm::LLVMRustGetLastError(); let msg = last_error().unwrap_or_else(|| "failed to write archive".into());
let msg = if err.is_null() {
"failed to write archive".into()
} else {
String::from_utf8_lossy(CStr::from_ptr(err).to_bytes())
};
Err(io::Error::new(io::ErrorKind::Other, msg)) Err(io::Error::new(io::ErrorKind::Other, msg))
} else { } else {
Ok(!members.is_empty()) Ok(!members.is_empty())

View file

@ -40,7 +40,7 @@ use crate::errors::{
WithLlvmError, WriteBytecode, WithLlvmError, WriteBytecode,
}; };
use crate::llvm::diagnostic::OptimizationDiagnosticKind::*; use crate::llvm::diagnostic::OptimizationDiagnosticKind::*;
use crate::llvm::{self, DiagnosticInfo, PassManager}; use crate::llvm::{self, DiagnosticInfo};
use crate::type_::Type; use crate::type_::Type;
use crate::{LlvmCodegenBackend, ModuleLlvm, base, common, llvm_util}; 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>( fn write_output_file<'ll>(
dcx: DiagCtxtHandle<'_>, dcx: DiagCtxtHandle<'_>,
target: &'ll llvm::TargetMachine, target: &'ll llvm::TargetMachine,
pm: &llvm::PassManager<'ll>, no_builtins: bool,
m: &'ll llvm::Module, m: &'ll llvm::Module,
output: &Path, output: &Path,
dwo_output: Option<&Path>, dwo_output: Option<&Path>,
@ -63,16 +63,19 @@ fn write_output_file<'ll>(
verify_llvm_ir: bool, verify_llvm_ir: bool,
) -> Result<(), FatalError> { ) -> Result<(), FatalError> {
debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output); debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output);
unsafe { let output_c = path_to_c_string(output);
let output_c = path_to_c_string(output); let dwo_output_c;
let dwo_output_c; let dwo_output_ptr = if let Some(dwo_output) = dwo_output {
let dwo_output_ptr = if let Some(dwo_output) = dwo_output { dwo_output_c = path_to_c_string(dwo_output);
dwo_output_c = path_to_c_string(dwo_output); dwo_output_c.as_ptr()
dwo_output_c.as_ptr() } else {
} else { std::ptr::null()
std::ptr::null() };
}; let result = unsafe {
let result = llvm::LLVMRustWriteOutputFile( let pm = llvm::LLVMCreatePassManager();
llvm::LLVMAddAnalysisPasses(target, pm);
llvm::LLVMRustAddLibraryInfo(pm, m, no_builtins);
llvm::LLVMRustWriteOutputFile(
target, target,
pm, pm,
m, m,
@ -80,22 +83,22 @@ fn write_output_file<'ll>(
dwo_output_ptr, dwo_output_ptr,
file_type, file_type,
verify_llvm_ir, verify_llvm_ir,
); )
};
// Record artifact sizes for self-profiling // Record artifact sizes for self-profiling
if result == llvm::LLVMRustResult::Success { if result == llvm::LLVMRustResult::Success {
let artifact_kind = match file_type { let artifact_kind = match file_type {
llvm::FileType::ObjectFile => "object_file", llvm::FileType::ObjectFile => "object_file",
llvm::FileType::AssemblyFile => "assembly_file", llvm::FileType::AssemblyFile => "assembly_file",
}; };
record_artifact_size(self_profiler_ref, artifact_kind, output); record_artifact_size(self_profiler_ref, artifact_kind, output);
if let Some(dwo_file) = dwo_output { if let Some(dwo_file) = dwo_output {
record_artifact_size(self_profiler_ref, "dwo_file", dwo_file); 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( pub(crate) fn create_informational_target_machine(
@ -325,13 +328,17 @@ pub(crate) fn save_temp_bitcode(
if !cgcx.save_temps { if !cgcx.save_temps {
return; return;
} }
let ext = format!("{name}.bc");
let cgu = Some(&module.name[..]);
let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
write_bitcode_to_file(module, &path)
}
fn write_bitcode_to_file(module: &ModuleCodegen<ModuleLlvm>, path: &Path) {
unsafe { unsafe {
let ext = format!("{name}.bc"); let path = path_to_c_string(&path);
let cgu = Some(&module.name[..]);
let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
let cstr = path_to_c_string(&path);
let llmod = module.module_llvm.llmod(); 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> { ) -> Result<(), FatalError> {
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name); 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 llcx = &*module.module_llvm.llcx;
let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt); 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 { if config.emit_no_opt_bc {
let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
let out = path_to_c_string(&out); write_bitcode_to_file(module, &out)
unsafe { llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()) };
} }
// FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts // FIXME(ZuseZ4): support SanitizeHWAddress and prevent illegal/unsupported opts
@ -755,31 +760,6 @@ pub(crate) unsafe fn codegen(
create_msvc_imps(cgcx, llcx, llmod); 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, // 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 // copy it to the .o file, and delete the bitcode if it wasn't
// otherwise requested. // otherwise requested.
@ -898,21 +878,17 @@ pub(crate) unsafe fn codegen(
} else { } else {
llmod llmod
}; };
unsafe { write_output_file(
with_codegen(tm, llmod, config.no_builtins, |cpm| { dcx,
write_output_file( tm,
dcx, config.no_builtins,
tm, llmod,
cpm, &path,
llmod, None,
&path, llvm::FileType::AssemblyFile,
None, &cgcx.prof,
llvm::FileType::AssemblyFile, config.verify_llvm_ir,
&cgcx.prof, )?;
config.verify_llvm_ir,
)
})?;
}
} }
match config.emit_obj { match config.emit_obj {
@ -936,21 +912,17 @@ pub(crate) unsafe fn codegen(
(_, SplitDwarfKind::Split) => Some(dwo_out.as_path()), (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
}; };
unsafe { write_output_file(
with_codegen(tm, llmod, config.no_builtins, |cpm| { dcx,
write_output_file( tm,
dcx, config.no_builtins,
tm, llmod,
cpm, &obj_out,
llmod, dwo_out,
&obj_out, llvm::FileType::ObjectFile,
dwo_out, &cgcx.prof,
llvm::FileType::ObjectFile, config.verify_llvm_ir,
&cgcx.prof, )?;
config.verify_llvm_ir,
)
})?;
}
} }
EmitObj::Bitcode => { EmitObj::Bitcode => {
@ -1077,24 +1049,18 @@ unsafe fn embed_bitcode(
{ {
// We don't need custom section flags, create LLVM globals. // We don't need custom section flags, create LLVM globals.
let llconst = common::bytes_in_context(llcx, bitcode); let llconst = common::bytes_in_context(llcx, bitcode);
let llglobal = llvm::LLVMAddGlobal( let llglobal =
llmod, llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.module");
common::val_ty(llconst), llvm::set_initializer(llglobal, llconst);
c"rustc.embedded.module".as_ptr(),
);
llvm::LLVMSetInitializer(llglobal, llconst);
llvm::set_section(llglobal, bitcode_section_name(cgcx)); llvm::set_section(llglobal, bitcode_section_name(cgcx));
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
llvm::LLVMSetGlobalConstant(llglobal, llvm::True); llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
let llglobal = llvm::LLVMAddGlobal( let llglobal =
llmod, llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
common::val_ty(llconst), llvm::set_initializer(llglobal, llconst);
c"rustc.embedded.cmdline".as_ptr(),
);
llvm::LLVMSetInitializer(llglobal, llconst);
let section = if cgcx.target_is_like_osx { let section = if cgcx.target_is_like_osx {
c"__LLVM,__cmdline" c"__LLVM,__cmdline"
} else if cgcx.target_is_like_aix { } else if cgcx.target_is_like_aix {
@ -1134,31 +1100,29 @@ fn create_msvc_imps(
// underscores added in front). // underscores added in front).
let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" }; let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" };
unsafe { let ptr_ty = Type::ptr_llcx(llcx);
let ptr_ty = Type::ptr_llcx(llcx); let globals = base::iter_globals(llmod)
let globals = base::iter_globals(llmod) .filter(|&val| {
.filter(|&val| { llvm::get_linkage(val) == llvm::Linkage::ExternalLinkage && !llvm::is_declaration(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.
.filter_map(|val| { let name = llvm::get_value_name(val);
// Exclude some symbols that we know are not Rust symbols. if ignored(name) { None } else { Some((val, name)) }
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();
.map(move |(val, name)| { imp_name.extend(name);
let mut imp_name = prefix.as_bytes().to_vec(); let imp_name = CString::new(imp_name).unwrap();
imp_name.extend(name); (imp_name, val)
let imp_name = CString::new(imp_name).unwrap(); })
(imp_name, val) .collect::<Vec<_>>();
})
.collect::<Vec<_>>();
for (imp_name, val) in globals { for (imp_name, val) in globals {
let imp = llvm::LLVMAddGlobal(llmod, ptr_ty, imp_name.as_ptr()); let imp = llvm::add_global(llmod, ptr_ty, &imp_name);
llvm::LLVMSetInitializer(imp, val);
llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage); llvm::set_initializer(imp, val);
} llvm::set_linkage(imp, llvm::Linkage::ExternalLinkage);
} }
// Use this function to exclude certain symbols from `__imp` generation. // Use this function to exclude certain symbols from `__imp` generation.

View file

@ -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(|| { let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| {
bug!("symbol `{}` is already defined", sym); bug!("symbol `{}` is already defined", sym);
}); });
llvm::set_initializer(g, sc);
unsafe { unsafe {
llvm::LLVMSetInitializer(g, sc);
llvm::LLVMSetGlobalConstant(g, True); llvm::LLVMSetGlobalConstant(g, True);
llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global); llvm::LLVMSetUnnamedAddress(g, llvm::UnnamedAddr::Global);
} }

View file

@ -191,7 +191,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
}) })
}); });
llvm::set_linkage(g2, llvm::Linkage::InternalLinkage); llvm::set_linkage(g2, llvm::Linkage::InternalLinkage);
unsafe { llvm::LLVMSetInitializer(g2, g1) }; llvm::set_initializer(g2, g1);
g2 g2
} else if cx.tcx.sess.target.arch == "x86" } else if cx.tcx.sess.target.arch == "x86"
&& common::is_mingw_gnu_toolchain(&cx.tcx.sess.target) && 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)), _ => self.define_private_global(self.val_ty(cv)),
}; };
unsafe { llvm::LLVMSetInitializer(gv, cv) }; llvm::set_initializer(gv, cv);
set_global_alignment(self, gv, align); set_global_alignment(self, gv, align);
llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global); llvm::SetUnnamedAddress(gv, llvm::UnnamedAddr::Global);
gv gv
@ -458,7 +458,7 @@ impl<'ll> CodegenCx<'ll, '_> {
new_g new_g
}; };
set_global_alignment(self, g, alloc.align); set_global_alignment(self, g, alloc.align);
llvm::LLVMSetInitializer(g, v); llvm::set_initializer(g, v);
if self.should_assume_dso_local(g, true) { if self.should_assume_dso_local(g, true) {
llvm::LLVMRustSetDSOLocal(g, true); llvm::LLVMRustSetDSOLocal(g, true);

View file

@ -616,12 +616,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) { pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
let array = self.const_array(self.type_ptr(), values); let array = self.const_array(self.type_ptr(), values);
unsafe { let g = llvm::add_global(self.llmod, self.val_ty(array), name);
let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); llvm::set_initializer(g, array);
llvm::LLVMSetInitializer(g, array); llvm::set_linkage(g, llvm::Linkage::AppendingLinkage);
llvm::set_linkage(g, llvm::Linkage::AppendingLinkage); llvm::set_section(g, c"llvm.metadata");
llvm::set_section(g, c"llvm.metadata");
}
} }
} }
impl<'ll> SimpleCx<'ll> { impl<'ll> SimpleCx<'ll> {

View file

@ -73,7 +73,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
.define_global(section_var_name, llvm_type) .define_global(section_var_name, llvm_type)
.unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name)); .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
llvm::set_section(section_var, c".debug_gdb_scripts"); 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::LLVMSetGlobalConstant(section_var, llvm::True);
llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage); llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage);

View file

@ -235,7 +235,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
/// name. /// name.
pub(crate) fn get_defined_value(&self, name: &str) -> Option<&'ll Value> { pub(crate) fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
self.get_declared_value(name).and_then(|val| { 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 } if !declaration { Some(val) } else { None }
}) })
} }

View file

@ -824,7 +824,7 @@ fn codegen_msvc_try<'ll>(
if bx.cx.tcx.sess.target.supports_comdat() { if bx.cx.tcx.sess.target.supports_comdat() {
llvm::SetUniqueComdat(bx.llmod, tydesc); 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 // 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 // reference instead of by value. We can't use catch by value because

View file

@ -2359,7 +2359,7 @@ unsafe extern "C" {
); );
pub fn LLVMRustWriteOutputFile<'a>( pub fn LLVMRustWriteOutputFile<'a>(
T: &'a TargetMachine, T: &'a TargetMachine,
PM: &PassManager<'a>, PM: *mut PassManager<'a>,
M: &'a Module, M: &'a Module,
Output: *const c_char, Output: *const c_char,
DwoOutput: *const c_char, DwoOutput: *const c_char,

View file

@ -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 { pub fn get_visibility(llglobal: &Value) -> Visibility {
unsafe { LLVMGetVisibility(llglobal) }.to_rust() unsafe { LLVMGetVisibility(llglobal) }.to_rust()
} }

View file

@ -2154,11 +2154,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported") 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 // 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( Res::Def(DefKind::Fn | DefKind::AssocFn, did) => {
tcx, self.dcx().span_delayed_bug(span, "function items cannot be used as const args");
span, let args = self.lower_generic_args_of_path_segment(
"fn items cannot be used as const args", 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 // Exhaustive match to be clear about what exactly we're considering to be
// an invalid Res for a const path. // an invalid Res for a const path.
@ -2557,27 +2561,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// reject function types that violate cmse ABI requirements // reject function types that violate cmse ABI requirements
cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty); cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty);
// Find any late-bound regions declared in return type that do if !bare_fn_ty.references_error() {
// not appear in the arguments. These are not well-formed. // Find any late-bound regions declared in return type that do
// // not appear in the arguments. These are not well-formed.
// Example: //
// for<'a> fn() -> &'a str <-- 'a is bad // Example:
// for<'a> fn(&'a String) -> &'a str <-- 'a is ok // for<'a> fn() -> &'a str <-- 'a is bad
let inputs = bare_fn_ty.inputs(); // for<'a> fn(&'a String) -> &'a str <-- 'a is ok
let late_bound_in_args = let inputs = bare_fn_ty.inputs();
tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned())); let late_bound_in_args =
let output = bare_fn_ty.output(); tcx.collect_constrained_late_bound_regions(inputs.map_bound(|i| i.to_owned()));
let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output); let output = bare_fn_ty.output();
let late_bound_in_ret = tcx.collect_referenced_late_bound_regions(output);
self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| { self.validate_late_bound_regions(late_bound_in_args, late_bound_in_ret, |br_name| {
struct_span_code_err!( struct_span_code_err!(
self.dcx(), self.dcx(),
decl.output.span(), decl.output.span(),
E0581, E0581,
"return type references {}, which is not constrained by the fn input types", "return type references {}, which is not constrained by the fn input types",
br_name br_name
) )
}); });
}
bare_fn_ty bare_fn_ty
} }

View file

@ -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_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_help = consider using a raw pointer instead
lint_improper_ctypes_slice_reason = slices have no C equivalent lint_improper_ctypes_slice_reason = slices have no C equivalent

View file

@ -241,10 +241,7 @@ fn structurally_same_type_impl<'tcx>(
if let ty::Adt(def, args) = *ty.kind() { if let ty::Adt(def, args) = *ty.kind() {
let is_transparent = def.repr().transparent(); let is_transparent = def.repr().transparent();
let is_non_null = types::nonnull_optimization_guaranteed(tcx, def); let is_non_null = types::nonnull_optimization_guaranteed(tcx, def);
debug!( debug!(?ty, is_transparent, is_non_null);
"non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
ty, is_transparent, is_non_null
);
if is_transparent && !is_non_null { if is_transparent && !is_non_null {
debug_assert_eq!(def.variants().len(), 1); debug_assert_eq!(def.variants().len(), 1);
let v = &def.variant(FIRST_VARIANT); 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 // An Adt and a primitive or pointer type. This can be FFI-safe if non-null
// enum layout optimisation is being applied. // 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) { if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) {
a_inner == b a_inner == b
} else { } else {
false 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) { if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) {
b_inner == a b_inner == a
} else { } else {

View file

@ -33,6 +33,7 @@
#![feature(let_chains)] #![feature(let_chains)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![feature(rustdoc_internals)] #![feature(rustdoc_internals)]
#![feature(try_blocks)]
#![warn(unreachable_pub)] #![warn(unreachable_pub)]
// tidy-alphabetical-end // tidy-alphabetical-end

View file

@ -877,6 +877,37 @@ fn ty_is_known_nonnull<'tcx>(
.filter_map(|variant| transparent_newtype_field(tcx, variant)) .filter_map(|variant| transparent_newtype_field(tcx, variant))
.any(|field| ty_is_known_nonnull(tcx, typing_env, field.ty(tcx, args), mode)) .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, _ => false,
} }
} }
@ -907,9 +938,8 @@ fn get_nullable_type<'tcx>(
}; };
return get_nullable_type(tcx, typing_env, inner_field_ty); return get_nullable_type(tcx, typing_env, inner_field_ty);
} }
ty::Int(ty) => Ty::new_int(tcx, ty), ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base),
ty::Uint(ty) => Ty::new_uint(tcx, ty), ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty,
ty::RawPtr(ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
// As these types are always non-null, the nullable equivalent of // As these types are always non-null, the nullable equivalent of
// `Option<T>` of these types are their raw pointer counterparts. // `Option<T>` of these types are their raw pointer counterparts.
ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl), ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
@ -965,63 +995,69 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
ckind: CItemKind, ckind: CItemKind,
) -> Option<Ty<'tcx>> { ) -> Option<Ty<'tcx>> {
debug!("is_repr_nullable_ptr(tcx, ty = {:?})", ty); debug!("is_repr_nullable_ptr(tcx, ty = {:?})", ty);
if let ty::Adt(ty_def, args) = ty.kind() { match ty.kind() {
let field_ty = match &ty_def.variants().raw[..] { ty::Adt(ty_def, args) => {
[var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) { let field_ty = match &ty_def.variants().raw[..] {
([], [field]) | ([field], []) => field.ty(tcx, args), [var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
([field1], [field2]) => { ([], [field]) | ([field], []) => field.ty(tcx, args),
let ty1 = field1.ty(tcx, args); ([field1], [field2]) => {
let ty2 = field2.ty(tcx, args); let ty1 = field1.ty(tcx, args);
let ty2 = field2.ty(tcx, args);
if is_niche_optimization_candidate(tcx, typing_env, ty1) { if is_niche_optimization_candidate(tcx, typing_env, ty1) {
ty2 ty2
} else if is_niche_optimization_candidate(tcx, typing_env, ty2) { } else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
ty1 ty1
} else { } else {
return None; return None;
}
} }
} _ => return None,
},
_ => return None, _ => return None,
},
_ => 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?");
}
// 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)
}
}; };
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?");
}
// 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)
}
};
}
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> { impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
@ -1256,11 +1292,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
help: Some(fluent::lint_improper_ctypes_char_help), help: Some(fluent::lint_improper_ctypes_char_help),
}, },
ty::Pat(..) => FfiUnsafe { // It's just extra invariants on the type that you need to uphold,
ty, // but only the base type is relevant for being representable in FFI.
reason: fluent::lint_improper_ctypes_pat_reason, ty::Pat(base, ..) => self.check_type_for_ffi(acc, base),
help: Some(fluent::lint_improper_ctypes_pat_help),
},
ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => { ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None } FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }

View file

@ -1800,7 +1800,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
} }
let u8_type = self.tcx().types.u8; 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::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
ty::Slice(t) if *t == u8_type => { ty::Slice(t) if *t == u8_type => {
let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| { 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(()); return Ok(());
} }
_ => { _ => {
let cv = ty::Value { valtree: cv.valtree, ty: *inner_ty }; let cv = ty::Value { valtree: cv.valtree, ty: inner_ty };
p!("&"); p!("&");
p!(pretty_print_const_valtree(cv, print_ty)); p!(pretty_print_const_valtree(cv, print_ty));
return Ok(()); 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(|| { let bytes = cv.try_to_raw_bytes(self.tcx()).unwrap_or_else(|| {
bug!("expected to convert valtree to raw bytes for type {:?}", t) 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, _)) => { (ty::ValTree::Leaf(leaf), ty::Ref(_, inner_ty, _)) => {
p!(write("&")); 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), _) => { (ty::ValTree::Leaf(leaf), _) => {
return self.pretty_print_const_scalar_int(leaf, cv.ty, print_ty); 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 // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
// their fields instead of just dumping the memory. // their fields instead of just dumping the memory.
_ => {} _ => {}

View file

@ -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_trait_object = prev;
self.diag_metadata.current_type_path = prev_ty; 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) { 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()); let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo());
self.with_generic_param_rib( self.with_generic_param_rib(

View file

@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
// https://developer.android.com/ndk/guides/abis.html#x86 // 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.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into();
base.stack_probes = StackProbeType::Inline; base.stack_probes = StackProbeType::Inline;

View file

@ -18,6 +18,8 @@ use rustc_middle::ty::{
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults,
}; };
use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym}; 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 tracing::{debug, instrument, warn};
use super::nice_region_error::placeholder_error::Highlighted; use super::nice_region_error::placeholder_error::Highlighted;
@ -155,27 +157,92 @@ impl UnderspecifiedArgKind {
} }
} }
struct ClosureEraser<'tcx> { struct ClosureEraser<'a, 'tcx> {
tcx: TyCtxt<'tcx>, infcx: &'a InferCtxt<'tcx>,
} }
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'tcx> { impl<'a, 'tcx> ClosureEraser<'a, 'tcx> {
fn new_infer(&mut self) -> Ty<'tcx> {
self.infcx.next_ty_var(DUMMY_SP)
}
}
impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
fn cx(&self) -> TyCtxt<'tcx> { fn cx(&self) -> TyCtxt<'tcx> {
self.tcx self.infcx.tcx
} }
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.kind() { match ty.kind() {
ty::Closure(_, args) => { 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(); let closure_sig = args.as_closure().sig();
Ty::new_fn_ptr( Ty::new_fn_ptr(
self.tcx, self.cx(),
self.tcx.signature_unclosure(closure_sig, hir::Safety::Safe), self.cx().signature_unclosure(closure_sig, hir::Safety::Safe),
) )
} }
_ => ty.super_fold_with(self), ty::Adt(_, args) if !args.iter().any(|a| a.has_infer()) => {
// We have a type that doesn't have any inference variables, so we replace
// the whole thing with `_`. The type system already knows about this type in
// its entirety and it is redundant to specify it for the user. The user only
// needs to specify the type parameters that we *couldn't* figure out.
self.new_infer()
}
ty::Adt(def, args) => {
let generics = self.cx().generics_of(def.did());
let generics: Vec<bool> = generics
.own_params
.iter()
.map(|param| param.default_value(self.cx()).is_some())
.collect();
let ty = Ty::new_adt(
self.cx(),
*def,
self.cx().mk_args_from_iter(generics.into_iter().zip(args.iter()).map(
|(has_default, arg)| {
if arg.has_infer() {
// This param has an unsubstituted type variable, meaning that this
// type has a (potentially deeply nested) type parameter from the
// corresponding type's definition. We have explicitly asked this
// type to not be hidden. In either case, we keep the type and don't
// substitute with `_` just yet.
arg.fold_with(self)
} else if has_default {
// We have a type param that has a default type, like the allocator
// in Vec. We decided to show `Vec` itself, because it hasn't yet
// been replaced by an `_` `Infer`, but we want to ensure that the
// type parameter with default types does *not* get replaced with
// `_` because then we'd end up with `Vec<_, _>`, instead of
// `Vec<_>`.
arg
} else if let GenericArgKind::Type(_) = arg.kind() {
// We don't replace lifetime or const params, only type params.
self.new_infer().into()
} else {
arg.fold_with(self)
}
},
)),
);
ty
}
_ if ty.has_infer() => {
// This type has a (potentially nested) type parameter that we couldn't figure out.
// We will print this depth of type, so at least the type name and at least one of
// its type parameters.
ty.super_fold_with(self)
}
// We don't have an unknown type parameter anywhere, replace with `_`.
_ => self.new_infer(),
} }
} }
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
// Avoid accidentally erasing the type of the const.
c
}
} }
fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> { fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
@ -219,9 +286,9 @@ fn ty_to_string<'tcx>(
) -> String { ) -> String {
let mut printer = fmt_printer(infcx, Namespace::TypeNS); let mut printer = fmt_printer(infcx, Namespace::TypeNS);
let ty = infcx.resolve_vars_if_possible(ty); let ty = infcx.resolve_vars_if_possible(ty);
// We use `fn` ptr syntax for closures, but this only works when the closure // We use `fn` ptr syntax for closures, but this only works when the closure does not capture
// does not capture anything. // anything. We also remove all type parameters that are fully known to the type system.
let ty = ty.fold_with(&mut ClosureEraser { tcx: infcx.tcx }); let ty = ty.fold_with(&mut ClosureEraser { infcx });
match (ty.kind(), called_method_def_id) { match (ty.kind(), called_method_def_id) {
// We don't want the regular output for `fn`s because it includes its path in // We don't want the regular output for `fn`s because it includes its path in

View file

@ -646,7 +646,7 @@ pub const fn must_use<T>(value: T) -> T {
/// ``` /// ```
/// ///
/// ///
#[unstable(feature = "likely_unlikely", issue = "26179")] #[unstable(feature = "likely_unlikely", issue = "136873")]
#[inline(always)] #[inline(always)]
pub const fn likely(b: bool) -> bool { pub const fn likely(b: bool) -> bool {
crate::intrinsics::likely(b) 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)] #[inline(always)]
pub const fn unlikely(b: bool) -> bool { pub const fn unlikely(b: bool) -> bool {
crate::intrinsics::unlikely(b) 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)] #[inline(always)]
pub const fn cold_path() { pub const fn cold_path() {
crate::intrinsics::cold_path() crate::intrinsics::cold_path()

View file

@ -165,7 +165,7 @@ target | std | notes
`i586-pc-windows-msvc` | * | 32-bit Windows (original Pentium) [^x86_32-floats-x87] `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-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] `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-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-freebsd`](platform-support/freebsd.md) | ✓ | 32-bit x86 FreeBSD (Pentium 4) [^x86_32-floats-return-ABI]
`i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 (Pentium 4) [^x86_32-floats-return-ABI] `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 (Pentium 4) [^x86_32-floats-return-ABI]

View file

@ -75,12 +75,12 @@ fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool
} }
} }
pub(crate) struct RangeOperand<'a> { pub(crate) struct RangeOperand<'a, T> {
operand: &'a Option<ptr::P<ast::Expr>>, pub operand: &'a Option<ptr::P<T>>,
pub(crate) span: Span, pub span: Span,
} }
impl<'a> Rewrite for RangeOperand<'a> { impl<'a, T: Rewrite> Rewrite for RangeOperand<'a, T> {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
self.rewrite_result(context, shape).ok() self.rewrite_result(context, shape).ok()
} }
@ -259,40 +259,7 @@ impl Rewrite for Pat {
} }
PatKind::Never => Err(RewriteError::Unknown), PatKind::Never => Err(RewriteError::Unknown),
PatKind::Range(ref lhs, ref rhs, ref end_kind) => { PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
let infix = match end_kind.node { rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span)
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,
)
} }
PatKind::Ref(ref pat, mutability) => { PatKind::Ref(ref pat, mutability) => {
let prefix = format!("&{}", format_mutability(mutability)); let prefix = format!("&{}", format_mutability(mutability));
@ -359,6 +326,50 @@ impl Rewrite for Pat {
} }
} }
pub fn rewrite_range_pat<T: Rewrite>(
context: &RewriteContext<'_>,
shape: Shape,
lhs: &Option<ptr::P<T>>,
rhs: &Option<ptr::P<T>>,
end_kind: &rustc_span::source_map::Spanned<RangeEnd>,
span: Span,
) -> RewriteResult {
let infix = match end_kind.node {
RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
RangeEnd::Included(RangeSyntax::DotDotEq) => "..=",
RangeEnd::Excluded => "..",
};
let infix = if context.config.spaces_around_ranges() {
let lhs_spacing = match lhs {
None => "",
Some(_) => " ",
};
let rhs_spacing = match rhs {
None => "",
Some(_) => " ",
};
format!("{lhs_spacing}{infix}{rhs_spacing}")
} else {
infix.to_owned()
};
let lspan = span.with_hi(end_kind.span.lo());
let rspan = span.with_lo(end_kind.span.hi());
rewrite_pair(
&RangeOperand {
operand: lhs,
span: lspan,
},
&RangeOperand {
operand: rhs,
span: rspan,
},
PairParts::infix(&infix),
context,
shape,
SeparatorPlace::Front,
)
}
fn rewrite_struct_pat( fn rewrite_struct_pat(
qself: &Option<ptr::P<ast::QSelf>>, qself: &Option<ptr::P<ast::QSelf>>,
path: &ast::Path, path: &ast::Path,

View file

@ -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 { fn span(&self) -> Span {
self.span self.span
} }

View file

@ -18,6 +18,7 @@ use crate::lists::{
use crate::macros::{MacroPosition, rewrite_macro}; use crate::macros::{MacroPosition, rewrite_macro};
use crate::overflow; use crate::overflow;
use crate::pairs::{PairParts, rewrite_pair}; use crate::pairs::{PairParts, rewrite_pair};
use crate::patterns::rewrite_range_pat;
use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult}; use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
use crate::shape::Shape; use crate::shape::Shape;
use crate::source_map::SpanUtils; use crate::source_map::SpanUtils;
@ -1045,6 +1046,21 @@ impl Rewrite for ast::Ty {
} }
} }
impl Rewrite for ast::TyPat {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
self.rewrite_result(context, shape).ok()
}
fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
match self.kind {
ast::TyPatKind::Range(ref lhs, ref rhs, ref end_kind) => {
rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span)
}
ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
}
}
}
fn rewrite_bare_fn( fn rewrite_bare_fn(
bare_fn: &ast::BareFnTy, bare_fn: &ast::BareFnTy,
span: Span, span: Span,

View file

@ -0,0 +1,9 @@
//@ edition: 2021
// Make sure we don't complain about the implicit `-> impl Future` capturing an
// unconstrained anonymous lifetime.
async fn foo(_: Missing<'_>) {}
//~^ ERROR cannot find type `Missing` in this scope
fn main() {}

View file

@ -0,0 +1,9 @@
error[E0412]: cannot find type `Missing` in this scope
--> $DIR/unconstrained-lifetimes.rs:6:17
|
LL | async fn foo(_: Missing<'_>) {}
| ^^^^^^^ not found in this scope
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0412`.

View file

@ -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<T> {}
impl A<[usize; fn_item]> for () {}
//~^ ERROR the constant `fn_item` is not of type `usize`
fn fn_item() {}
fn main() {}

View file

@ -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 <https://github.com/rust-lang/rust/issues/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

View file

@ -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 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 error: aborting due to 1 previous error

View file

@ -12,8 +12,8 @@ LL | fn foo<T, K, W: Default, Z: Default>(t: T, k: K) -> Foo<T, K, W, Z> {
| ^^^^^^^ required by this bound in `foo` | ^^^^^^^ required by this bound in `foo`
help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified help: consider giving `foo` an explicit type, where the type for type parameter `W` is specified
| |
LL | let foo: Foo<i32, &str, W, Z> = foo(1, ""); LL | let foo: Foo<_, &_, W, Z> = foo(1, "");
| ++++++++++++++++++++++ | ++++++++++++++++++
error[E0283]: type annotations needed for `Bar<i32, &str, _>` error[E0283]: type annotations needed for `Bar<i32, &str, _>`
--> $DIR/erase-type-params-in-label.rs:5:9 --> $DIR/erase-type-params-in-label.rs:5:9
@ -29,8 +29,8 @@ LL | fn bar<T, K, Z: Default>(t: T, k: K) -> Bar<T, K, Z> {
| ^^^^^^^ required by this bound in `bar` | ^^^^^^^ required by this bound in `bar`
help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified help: consider giving `bar` an explicit type, where the type for type parameter `Z` is specified
| |
LL | let bar: Bar<i32, &str, Z> = bar(1, ""); LL | let bar: Bar<_, &_, Z> = bar(1, "");
| +++++++++++++++++++ | +++++++++++++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -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 help: consider giving `a` an explicit type, where the type for type parameter `E` is specified
| |
LL | let a: A<std::result::Result<std::result::Result<(), E>, Error>> = A(Result::Ok(Result::Ok(()))); LL | let a: A<std::result::Result<std::result::Result<_, E>, _>> = A(Result::Ok(Result::Ok(())));
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | ++++++++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -11,8 +11,8 @@ LL | fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] {
| ^^^^^^^^^^^^^^ required by this const generic parameter in `foo` | ^^^^^^^^^^^^^^ required by this const generic parameter in `foo`
help: consider giving this pattern a type, where the value of const parameter `N` is specified 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 error: aborting due to 1 previous error

View file

@ -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() {}

View file

@ -0,0 +1,14 @@
error[E0282]: type annotations needed for `Result<_, ((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))>`
--> $DIR/really-long-type-in-let-binding-without-sufficient-type-info.rs:7:9
|
LL | let y = Err(x);
| ^ ------ type must be known at this point
|
help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
|
LL | let y: Result<T, _> = Err(x);
| ++++++++++++++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0282`.

View file

@ -1,7 +1,7 @@
//@ check-pass //@ check-pass
//@ aux-build:external_extern_fn.rs //@ aux-build:external_extern_fn.rs
#![crate_type = "lib"] #![crate_type = "lib"]
#![feature(pattern_type_macro, pattern_types)]
mod redeclared_different_signature { mod redeclared_different_signature {
mod a { mod a {
extern "C" { extern "C" {
@ -490,3 +490,33 @@ mod hidden_niche {
} }
} }
} }
mod pattern_types {
mod a {
use std::pat::pattern_type;
#[repr(transparent)]
struct NonZeroUsize(pattern_type!(usize is 1..));
extern "C" {
fn pt_non_zero_usize() -> pattern_type!(usize is 1..);
fn pt_non_zero_usize_opt() -> Option<pattern_type!(usize is 1..)>;
fn pt_non_zero_usize_opt_full_range() -> Option<pattern_type!(usize is 0..)>;
//~^ WARN not FFI-safe
fn pt_non_null_ptr() -> pattern_type!(usize is 1..);
fn pt_non_zero_usize_wrapper() -> NonZeroUsize;
fn pt_non_zero_usize_wrapper_opt() -> Option<NonZeroUsize>;
}
}
mod b {
extern "C" {
// If there's a clash in either of these cases you're either gaining an incorrect
// invariant that the value is non-zero, or you're missing out on that invariant. Both
// cases are warning for, from both a caller-convenience and optimisation perspective.
fn pt_non_zero_usize() -> usize;
fn pt_non_zero_usize_opt() -> usize;
fn pt_non_null_ptr() -> *const ();
//~^ WARN `pt_non_null_ptr` redeclared with a different signature
fn pt_non_zero_usize_wrapper() -> usize;
fn pt_non_zero_usize_wrapper_opt() -> usize;
}
}
}

View file

@ -17,6 +17,15 @@ LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint = note: enum has no representation hint
warning: `extern` block uses type `Option<(usize) is 0..=>`, which is not FFI-safe
--> $DIR/clashing-extern-fn.rs:502:54
|
LL | fn pt_non_zero_usize_opt_full_range() -> Option<pattern_type!(usize is 0..)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
warning: `clash` redeclared with a different signature warning: `clash` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:13:13 --> $DIR/clashing-extern-fn.rs:13:13
| |
@ -258,5 +267,17 @@ LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
= note: expected `unsafe extern "C" fn() -> usize` = note: expected `unsafe extern "C" fn() -> usize`
found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZero<usize>>>` found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZero<usize>>>`
warning: 22 warnings emitted warning: `pt_non_null_ptr` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:516:13
|
LL | fn pt_non_null_ptr() -> pattern_type!(usize is 1..);
| ---------------------------------------------------- `pt_non_null_ptr` previously declared here
...
LL | fn pt_non_null_ptr() -> *const ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
= note: expected `unsafe extern "C" fn() -> (usize) is 1..=`
found `unsafe extern "C" fn() -> *const ()`
warning: 24 warnings emitted

View file

@ -94,6 +94,7 @@ extern "C" {
fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>); fn option_transparent_union(x: Option<TransparentUnion<num::NonZero<u8>>>);
//~^ ERROR `extern` block uses type //~^ ERROR `extern` block uses type
fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>); //~ ERROR `extern` block uses type fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>); //~ ERROR `extern` block uses type
fn option_u8(x: Option<u8>); //~ ERROR `extern` block uses type
fn result_ref_t(x: Result<&'static u8, ()>); fn result_ref_t(x: Result<&'static u8, ()>);
fn result_fn_t(x: Result<extern "C" fn(), ()>); fn result_fn_t(x: Result<extern "C" fn(), ()>);

View file

@ -79,8 +79,17 @@ LL | fn option_repr_rust(x: Option<Rust<num::NonZero<u8>>>);
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Option<u8>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:97:21
|
LL | fn option_u8(x: Option<u8>);
| ^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
error: `extern` block uses type `u128`, which is not FFI-safe error: `extern` block uses type `u128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:106:33 --> $DIR/lint-ctypes-enum.rs:107:33
| |
LL | fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>); LL | fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -88,7 +97,7 @@ LL | fn result_nonzero_u128_t(x: Result<num::NonZero<u128>, ()>);
= note: 128-bit integers don't currently have a known stable ABI = note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `i128`, which is not FFI-safe error: `extern` block uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:113:33 --> $DIR/lint-ctypes-enum.rs:114:33
| |
LL | fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>); LL | fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -96,7 +105,7 @@ LL | fn result_nonzero_i128_t(x: Result<num::NonZero<i128>, ()>);
= note: 128-bit integers don't currently have a known stable ABI = note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe error: `extern` block uses type `Result<TransparentUnion<NonZero<u8>>, ()>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:118:38 --> $DIR/lint-ctypes-enum.rs:119:38
| |
LL | fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>); LL | fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u8>>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -105,7 +114,7 @@ LL | fn result_transparent_union_t(x: Result<TransparentUnion<num::NonZero<u
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe error: `extern` block uses type `Result<Rust<NonZero<u8>>, ()>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:120:30 --> $DIR/lint-ctypes-enum.rs:121:30
| |
LL | fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>); LL | fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -114,7 +123,7 @@ LL | fn result_repr_rust_t(x: Result<Rust<num::NonZero<u8>>, ()>);
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe error: `extern` block uses type `Result<NonZero<u8>, U>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:124:51 --> $DIR/lint-ctypes-enum.rs:125:51
| |
LL | fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>); LL | fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>, U>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -123,7 +132,7 @@ LL | fn result_1zst_exhaustive_single_variant_t(x: Result<num::NonZero<u8>,
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe error: `extern` block uses type `Result<NonZero<u8>, B>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:126:53 --> $DIR/lint-ctypes-enum.rs:127:53
| |
LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>); LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>, B>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -132,7 +141,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_t(x: Result<num::NonZero<u8>
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe error: `extern` block uses type `Result<NonZero<u8>, NonExhaustive>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:128:51 --> $DIR/lint-ctypes-enum.rs:129:51
| |
LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>); LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>, NonExhaustive>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -141,7 +150,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_t(x: Result<num::NonZero<u8>,
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe error: `extern` block uses type `Result<NonZero<u8>, Field>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:131:49 --> $DIR/lint-ctypes-enum.rs:132:49
| |
LL | fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>); LL | fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Field>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -150,7 +159,7 @@ LL | fn result_1zst_exhaustive_single_field_t(x: Result<num::NonZero<u8>, Fi
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe error: `extern` block uses type `Result<Result<(), NonZero<u8>>, ()>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:133:30 --> $DIR/lint-ctypes-enum.rs:134:30
| |
LL | fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>); LL | fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -159,7 +168,7 @@ LL | fn result_cascading_t(x: Result<Result<(), num::NonZero<u8>>, ()>);
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `u128`, which is not FFI-safe error: `extern` block uses type `u128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:144:33 --> $DIR/lint-ctypes-enum.rs:145:33
| |
LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>); LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -167,7 +176,7 @@ LL | fn result_nonzero_u128_e(x: Result<(), num::NonZero<u128>>);
= note: 128-bit integers don't currently have a known stable ABI = note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `i128`, which is not FFI-safe error: `extern` block uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:151:33 --> $DIR/lint-ctypes-enum.rs:152:33
| |
LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>); LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -175,7 +184,7 @@ LL | fn result_nonzero_i128_e(x: Result<(), num::NonZero<i128>>);
= note: 128-bit integers don't currently have a known stable ABI = note: 128-bit integers don't currently have a known stable ABI
error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe error: `extern` block uses type `Result<(), TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:156:38 --> $DIR/lint-ctypes-enum.rs:157:38
| |
LL | fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>); LL | fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZero<u8>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -184,7 +193,7 @@ LL | fn result_transparent_union_e(x: Result<(), TransparentUnion<num::NonZe
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe error: `extern` block uses type `Result<(), Rust<NonZero<u8>>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:158:30 --> $DIR/lint-ctypes-enum.rs:159:30
| |
LL | fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>); LL | fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -193,7 +202,7 @@ LL | fn result_repr_rust_e(x: Result<(), Rust<num::NonZero<u8>>>);
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe error: `extern` block uses type `Result<U, NonZero<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:162:51 --> $DIR/lint-ctypes-enum.rs:163:51
| |
LL | fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>); LL | fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -202,7 +211,7 @@ LL | fn result_1zst_exhaustive_single_variant_e(x: Result<U, num::NonZero<u8
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe error: `extern` block uses type `Result<B, NonZero<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:164:53 --> $DIR/lint-ctypes-enum.rs:165:53
| |
LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>); LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -211,7 +220,7 @@ LL | fn result_1zst_exhaustive_multiple_variant_e(x: Result<B, num::NonZero<
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe error: `extern` block uses type `Result<NonExhaustive, NonZero<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:166:51 --> $DIR/lint-ctypes-enum.rs:167:51
| |
LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>); LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num::NonZero<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -220,7 +229,7 @@ LL | fn result_1zst_non_exhaustive_no_variant_e(x: Result<NonExhaustive, num
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe error: `extern` block uses type `Result<Field, NonZero<u8>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:169:49 --> $DIR/lint-ctypes-enum.rs:170:49
| |
LL | fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>); LL | fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<u8>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -229,7 +238,7 @@ LL | fn result_1zst_exhaustive_single_field_e(x: Result<Field, num::NonZero<
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe error: `extern` block uses type `Result<(), Result<(), NonZero<u8>>>`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:171:30 --> $DIR/lint-ctypes-enum.rs:172:30
| |
LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>); LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@ -238,7 +247,7 @@ LL | fn result_cascading_e(x: Result<(), Result<(), num::NonZero<u8>>>);
= note: enum has no representation hint = note: enum has no representation hint
error: `extern` block uses type `Result<(), ()>`, which is not FFI-safe 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<(), ()>); LL | fn result_unit_t_e(x: Result<(), ()>);
| ^^^^^^^^^^^^^^ not FFI-safe | ^^^^^^^^^^^^^^ 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 = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint = note: enum has no representation hint
error: aborting due to 26 previous errors error: aborting due to 27 previous errors

View file

@ -6,8 +6,8 @@ LL | .or_else(|err| {
| |
help: try giving this closure an explicit return type help: try giving this closure an explicit return type
| |
LL | .or_else(|err| -> Result<Child, F> { LL | .or_else(|err| -> Result<_, F> {
| +++++++++++++++++++ | +++++++++++++++
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,79 +1,38 @@
error[E0658]: wraparound pattern type ranges cause monomorphization time errors error: generic parameters may not be used in const operations
--> $DIR/assoc_const.rs:17:19 --> $DIR/assoc_const.rs:17:41
| |
LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {} LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^ cannot perform const operation using `T`
| |
= note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information = note: type parameters may not be used in const expressions
= help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
= 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 error: generic parameters may not be used in const operations
--> $DIR/assoc_const.rs:17:19 --> $DIR/assoc_const.rs:17:61
| |
LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {} LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^ cannot perform const operation using `T`
| |
= note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information = note: type parameters may not be used in const expressions
= help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
= 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 error: generic parameters may not be used in const operations
--> $DIR/assoc_const.rs:17:19 --> $DIR/assoc_const.rs:20:40
|
LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: constant expression depends on a generic parameter
--> $DIR/assoc_const.rs:17:19
|
LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0658]: wraparound pattern type ranges cause monomorphization time errors
--> $DIR/assoc_const.rs:22:19
| |
LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {} LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^ cannot perform const operation using `T`
| |
= note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information = note: type parameters may not be used in const expressions
= help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
= 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 error: generic parameters may not be used in const operations
--> $DIR/assoc_const.rs:22:19 --> $DIR/assoc_const.rs:20:51
| |
LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {} LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^ cannot perform const operation using `T`
| |
= note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information = note: type parameters may not be used in const expressions
= help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
= 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 error: aborting due to 4 previous errors
--> $DIR/assoc_const.rs:22:19
|
LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
error: constant expression depends on a generic parameter
--> $DIR/assoc_const.rs:22:19
|
LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this may fail depending on what value the parameter takes
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -15,14 +15,10 @@ trait Foo {
} }
fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {} fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
//[default]~^ ERROR: constant expression depends on a generic parameter //[default]~^ ERROR: generic parameters may not be used in const operations
//[default]~| ERROR: constant expression depends on a generic parameter //[default]~| ERROR: generic parameters may not be used in const operations
//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {} fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
//[default]~^ ERROR: constant expression depends on a generic parameter //[default]~^ ERROR: generic parameters may not be used in const operations
//[default]~| ERROR: constant expression depends on a generic parameter //[default]~| ERROR: generic parameters may not be used in const operations
//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
fn main() {} fn main() {}

View file

@ -5,7 +5,7 @@
//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " //@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
//@ rustc-env:RUST_BACKTRACE=0 //@ rustc-env:RUST_BACKTRACE=0
#![feature(pattern_types, pattern_type_macro)] #![feature(pattern_types, pattern_type_macro, generic_const_exprs)]
#![allow(internal_features)] #![allow(internal_features)]
type Pat<const START: u32, const END: u32> = type Pat<const START: u32, const END: u32> =

View file

@ -1,4 +1,11 @@
error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/bad_const_generics_args_on_const_param.rs:8:47
|
LL | #![feature(pattern_types, pattern_type_macro, generic_const_exprs)]
| ^^^^^^^^^^^^^^^^^^^
|
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
= error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible
--> $DIR/bad_const_generics_args_on_const_param.rs:12:36 --> $DIR/bad_const_generics_args_on_const_param.rs:12:36
| |
LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); 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` #0 [type_of] expanding type alias `Pat`
#1 [check_well_formed] checking that `Pat` is well-formed #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 ... 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

View file

@ -1,10 +1,10 @@
#![feature(pattern_types)] #![feature(pattern_types)]
#![feature(pattern_type_macro)] #![feature(pattern_type_macro)]
#![feature(inline_const_pat)] #![feature(inline_const_pat)]
//@ check-pass
use std::pat::pattern_type; use std::pat::pattern_type;
fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
//~^ ERROR: cycle
fn main() {} fn main() {}

View file

@ -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`.

View file

@ -12,3 +12,4 @@ type Positive = pattern_type!(i32 is 0..);
//~^ use of unstable library feature `pattern_type_macro` //~^ use of unstable library feature `pattern_type_macro`
type Always = pattern_type!(Option<u32> is Some(_)); type Always = pattern_type!(Option<u32> is Some(_));
//~^ use of unstable library feature `pattern_type_macro` //~^ use of unstable library feature `pattern_type_macro`
//~| ERROR pattern not supported in pattern types

View file

@ -48,6 +48,12 @@ LL | type Always = pattern_type!(Option<u32> is Some(_));
= help: add `#![feature(pattern_type_macro)]` to the crate attributes to enable = 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 = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 5 previous errors error: pattern not supported in pattern types
--> $DIR/feature-gate-pattern_types.rs:13:44
|
LL | type Always = pattern_type!(Option<u32> is Some(_));
| ^^^^^^^
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0658`. For more information about this error, try `rustc --explain E0658`.

View file

@ -1,5 +1,4 @@
//@ compile-flags: -Zno-analysis //@ compile-flags: -Zno-analysis
//@ check-pass
#![feature(pattern_type_macro)] #![feature(pattern_type_macro)]
@ -10,3 +9,4 @@ type Percent = pattern_type!(u32 is 0..=100);
type Negative = pattern_type!(i32 is ..=0); type Negative = pattern_type!(i32 is ..=0);
type Positive = pattern_type!(i32 is 0..); type Positive = pattern_type!(i32 is 0..);
type Always = pattern_type!(Option<u32> is Some(_)); type Always = pattern_type!(Option<u32> is Some(_));
//~^ ERROR: pattern not supported in pattern types

View file

@ -0,0 +1,8 @@
error: pattern not supported in pattern types
--> $DIR/feature-gate-pattern_types2.rs:11:44
|
LL | type Always = pattern_type!(Option<u32> is Some(_));
| ^^^^^^^
error: aborting due to 1 previous error

View file

@ -678,7 +678,7 @@ mod types {
/*! FIXME: todo */ /*! FIXME: todo */
} }
/// TyKind::Pat /// TyKind::Pat
fn ty_pat() { let _: u32 is 1..; } fn ty_pat() { let _: u32 is const 1..; }
} }
mod visibilities { mod visibilities {
/// VisibilityKind::Public /// VisibilityKind::Public