diff options
| author | bors <bors@rust-lang.org> | 2024-09-22 06:31:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-09-22 06:31:10 +0000 |
| commit | ee20c8628224ceae61f5f3dac98a18ede8872571 (patch) | |
| tree | d6de38b7510e7603d988ab5b33a317d201f32070 | |
| parent | a3fea24971e748914354acaf90033bbe594a4fa5 (diff) | |
| parent | d877ec2a3e7235c32e0fd094fb1cf813586b2665 (diff) | |
| download | rust-ee20c8628224ceae61f5f3dac98a18ede8872571.tar.gz rust-ee20c8628224ceae61f5f3dac98a18ede8872571.zip | |
Auto merge of #3902 - RalfJung:rustup, r=RalfJung
Rustup
191 files changed, 2412 insertions, 746 deletions
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 7bd2507d1ad..904c5933a18 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -337,23 +337,21 @@ impl TargetDataLayout { Ok(dl) } - /// Returns exclusive upper bound on object size. + /// Returns **exclusive** upper bound on object size in bytes. /// /// The theoretical maximum object size is defined as the maximum positive `isize` value. /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly /// index every address within an object along with one byte past the end, along with allowing /// `isize` to store the difference between any two pointers into an object. /// - /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer - /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is - /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable - /// address space on 64-bit ARMv8 and x86_64. + /// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes, + /// so we adopt such a more-constrained size bound due to its technical limitations. #[inline] pub fn obj_size_bound(&self) -> u64 { match self.pointer_size.bits() { 16 => 1 << 15, 32 => 1 << 31, - 64 => 1 << 47, + 64 => 1 << 61, bits => panic!("obj_size_bound: unknown pointer bit size {bits}"), } } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index ac65b7b22bc..d49265de202 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1187,8 +1187,8 @@ impl Expr { /// `min_const_generics` as more complex expressions are not supported. /// /// Does not ensure that the path resolves to a const param, the caller should check this. - pub fn is_potential_trivial_const_arg(&self) -> bool { - let this = self.maybe_unwrap_block(); + pub fn is_potential_trivial_const_arg(&self, strip_identity_block: bool) -> bool { + let this = if strip_identity_block { self.maybe_unwrap_block().1 } else { self }; if let ExprKind::Path(None, path) = &this.kind && path.is_potential_trivial_const_arg() @@ -1199,14 +1199,15 @@ impl Expr { } } - pub fn maybe_unwrap_block(&self) -> &Expr { + /// Returns an expression with (when possible) *one* outter brace removed + pub fn maybe_unwrap_block(&self) -> (bool, &Expr) { if let ExprKind::Block(block, None) = &self.kind && let [stmt] = block.stmts.as_slice() && let StmtKind::Expr(expr) = &stmt.kind { - expr + (true, expr) } else { - self + (false, self) } } diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index a9d1ee5c9c1..11867c39e02 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -20,8 +20,8 @@ use super::errors::{ }; use super::LoweringContext; use crate::{ - fluent_generated as fluent, ImplTraitContext, ImplTraitPosition, ParamMode, - ResolverAstLoweringExt, + fluent_generated as fluent, AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, + ParamMode, ResolverAstLoweringExt, }; impl<'a, 'hir> LoweringContext<'a, 'hir> { @@ -201,6 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.qself, &sym.path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); @@ -220,7 +221,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let parent_def_id = self.current_def_id_parent; let node_id = self.next_node_id(); // HACK(min_generic_const_args): see lower_anon_const - if !expr.is_potential_trivial_const_arg() { + if !expr.is_potential_trivial_const_arg(true) { self.create_def( parent_def_id, node_id, diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index ac527df474a..97483e85f77 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -52,7 +52,7 @@ use rustc_target::spec::abi; use {rustc_ast as ast, rustc_hir as hir}; use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode}; -use crate::{ImplTraitPosition, ResolverAstLoweringExt}; +use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt}; pub(crate) struct DelegationResults<'hir> { pub body_id: hir::BodyId, @@ -340,6 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &delegation.qself, &delegation.path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index e105026ebd1..d828c9856b9 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -23,7 +23,7 @@ use super::{ GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt, }; use crate::errors::YieldInClosure; -use crate::{fluent_generated, FnDeclKind, ImplTraitPosition}; +use crate::{fluent_generated, AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition}; impl<'hir> LoweringContext<'_, 'hir> { fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] { @@ -281,6 +281,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); @@ -328,6 +329,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, )), @@ -387,7 +389,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let node_id = self.next_node_id(); // HACK(min_generic_const_args): see lower_anon_const - if !arg.is_potential_trivial_const_arg() { + if !arg.is_potential_trivial_const_arg(true) { // Add a definition for the in-band const def. self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span); } @@ -1291,6 +1293,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); @@ -1311,6 +1314,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); @@ -1336,6 +1340,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index efd3ae336af..3f48fe67dbb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -485,9 +485,23 @@ enum ParamMode { Optional, } +#[derive(Copy, Clone, Debug)] +enum AllowReturnTypeNotation { + /// Only in types, since RTN is denied later during HIR lowering. + Yes, + /// All other positions (path expr, method, use tree). + No, +} + enum GenericArgsMode { + /// Allow paren sugar, don't allow RTN. ParenSugar, + /// Allow RTN, don't allow paren sugar. + ReturnTypeNotation, + // Error if parenthesized generics or RTN are encountered. Err, + /// Silence errors when lowering generics. Only used with `Res::Err`. + Silence, } impl<'a, 'hir> LoweringContext<'a, 'hir> { @@ -1226,7 +1240,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let id = self.lower_node_id(t.id); - let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None); + let qpath = self.lower_qpath( + t.id, + qself, + path, + param_mode, + AllowReturnTypeNotation::Yes, + itctx, + None, + ); self.ty_path(id, t.span, qpath) } @@ -2203,6 +2225,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &None, &p.path, ParamMode::Explicit, + AllowReturnTypeNotation::No, itctx, Some(modifiers), ) { @@ -2341,6 +2364,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &None, path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); @@ -2419,6 +2443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); @@ -2441,7 +2466,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// See [`hir::ConstArg`] for when to use this function vs /// [`Self::lower_anon_const_to_const_arg`]. fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { - if c.value.is_potential_trivial_const_arg() { + if c.value.is_potential_trivial_const_arg(true) { // HACK(min_generic_const_args): see DefCollector::visit_anon_const // Over there, we guess if this is a bare param and only create a def if // we think it's not. However we may can guess wrong (see there for example) diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index d82bdd526b7..584d94ebe2d 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -11,7 +11,7 @@ use super::errors::{ ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, }; use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt}; -use crate::ImplTraitPosition; +use crate::{AllowReturnTypeNotation, ImplTraitPosition}; impl<'a, 'hir> LoweringContext<'a, 'hir> { pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> { @@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); @@ -55,6 +56,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); @@ -66,6 +68,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, + AllowReturnTypeNotation::No, ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 2ab30eff6d8..03c8097e4c3 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -5,6 +5,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; use rustc_middle::span_bug; +use rustc_session::parse::add_feature_diagnostics; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; @@ -15,10 +16,9 @@ use super::errors::{ GenericTypeWithParentheses, UseAngleBrackets, }; use super::{ - GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode, - ResolverAstLoweringExt, + AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition, + LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt, }; -use crate::ImplTraitPosition; impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "trace", skip(self))] @@ -28,6 +28,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<ptr::P<QSelf>>, p: &Path, param_mode: ParamMode, + allow_return_type_notation: AllowReturnTypeNotation, itctx: ImplTraitContext, // modifiers of the impl/bound if this is a trait path modifiers: Option<ast::TraitBoundModifiers>, @@ -103,8 +104,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { { GenericArgsMode::ParenSugar } + Res::Def(DefKind::AssocFn, _) if i + 1 == proj_start => { + match allow_return_type_notation { + AllowReturnTypeNotation::Yes => GenericArgsMode::ReturnTypeNotation, + AllowReturnTypeNotation::No => GenericArgsMode::Err, + } + } // Avoid duplicated errors. - Res::Err => GenericArgsMode::ParenSugar, + Res::Err => GenericArgsMode::Silence, // An error _ => GenericArgsMode::Err, }; @@ -164,11 +171,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // 3. `<<std::vec::Vec<T>>::IntoIter>::Item` // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone` for (i, segment) in p.segments.iter().enumerate().skip(proj_start) { + // If this is a type-dependent `T::method(..)`. + let generic_args_mode = if i + 1 == p.segments.len() + && matches!(allow_return_type_notation, AllowReturnTypeNotation::Yes) + { + GenericArgsMode::ReturnTypeNotation + } else { + GenericArgsMode::Err + }; + let hir_segment = self.arena.alloc(self.lower_path_segment( p.span, segment, param_mode, - GenericArgsMode::Err, + generic_args_mode, itctx, None, )); @@ -238,11 +254,46 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } GenericArgs::Parenthesized(data) => match generic_args_mode { - GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data( - data, - itctx, - bound_modifier_allowed_features, - ), + GenericArgsMode::ReturnTypeNotation => { + let mut err = if !data.inputs.is_empty() { + self.dcx().create_err(BadReturnTypeNotation::Inputs { + span: data.inputs_span, + }) + } else if let FnRetTy::Ty(ty) = &data.output { + self.dcx().create_err(BadReturnTypeNotation::Output { + span: data.inputs_span.shrink_to_hi().to(ty.span), + }) + } else { + self.dcx().create_err(BadReturnTypeNotation::NeedsDots { + span: data.inputs_span, + }) + }; + if !self.tcx.features().return_type_notation + && self.tcx.sess.is_nightly_build() + { + add_feature_diagnostics( + &mut err, + &self.tcx.sess, + sym::return_type_notation, + ); + } + err.emit(); + ( + GenericArgsCtor { + args: Default::default(), + constraints: &[], + parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation, + span: path_span, + }, + false, + ) + } + GenericArgsMode::ParenSugar | GenericArgsMode::Silence => self + .lower_parenthesized_parameter_data( + data, + itctx, + bound_modifier_allowed_features, + ), GenericArgsMode::Err => { // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>` let sub = if !data.inputs.is_empty() { @@ -279,7 +330,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } }, GenericArgs::ParenthesizedElided(span) => { - self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span }); + match generic_args_mode { + GenericArgsMode::ReturnTypeNotation | GenericArgsMode::Silence => { + // Ok + } + GenericArgsMode::ParenSugar | GenericArgsMode::Err => { + self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span }); + } + } ( GenericArgsCtor { args: Default::default(), diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 24cf3f061a5..8838b15d29d 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -61,6 +61,9 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call Conv::CCmseNonSecureCall => { sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented"); } + Conv::CCmseNonSecureEntry => { + sess.dcx().fatal("C-cmse-nonsecure-entry call conv is not yet implemented"); + } Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => { unreachable!("tried to use {c:?} call conv which only exists on an unsupported target"); diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 26718792f5f..0fa8c9d3f19 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -422,6 +422,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if let Conv::RiscvInterrupt { kind } = self.conv { func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str())); } + if let Conv::CCmseNonSecureEntry = self.conv { + func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry")) + } attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs }); let mut i = 0; @@ -659,9 +662,11 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { impl From<Conv> for llvm::CallConv { fn from(conv: Conv) -> Self { match conv { - Conv::C | Conv::Rust | Conv::CCmseNonSecureCall | Conv::RiscvInterrupt { .. } => { - llvm::CCallConv - } + Conv::C + | Conv::Rust + | Conv::CCmseNonSecureCall + | Conv::CCmseNonSecureEntry + | Conv::RiscvInterrupt { .. } => llvm::CCallConv, Conv::Cold => llvm::ColdCallConv, Conv::PreserveMost => llvm::PreserveMost, Conv::PreserveAll => llvm::PreserveAll, diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 6df63eec513..489259da856 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -483,9 +483,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx); attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) { - to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry")); - } if let Some(align) = codegen_fn_attrs.alignment { llvm::set_alignment(llfn, align); } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 137e481f08c..9bd8a84f5a3 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -195,24 +195,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } } - sym::cmse_nonsecure_entry => { - if let Some(fn_sig) = fn_sig() - && !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. }) - { - struct_span_code_err!( - tcx.dcx(), - attr.span, - E0776, - "`#[cmse_nonsecure_entry]` requires C ABI" - ) - .emit(); - } - if !tcx.sess.target.llvm_target.contains("thumbv8m") { - struct_span_code_err!(tcx.dcx(), attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension") - .emit(); - } - codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY - } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, sym::track_caller => { let is_closure = tcx.is_closure_like(did.to_def_id()); diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index f13c46e8bef..25712095e76 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -15,6 +15,7 @@ use crate::traits::*; pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx: &FunctionCx<'a, 'tcx, Bx>, + traversal_order: &[mir::BasicBlock], ) -> BitSet<mir::Local> { let mir = fx.mir; let dominators = mir.basic_blocks.dominators(); @@ -24,13 +25,7 @@ pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( .map(|decl| { let ty = fx.monomorphize(decl.ty); let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span); - if layout.is_zst() { - LocalKind::ZST - } else if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) { - LocalKind::Unused - } else { - LocalKind::Memory - } + if layout.is_zst() { LocalKind::ZST } else { LocalKind::Unused } }) .collect(); @@ -44,7 +39,8 @@ pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // If there exists a local definition that dominates all uses of that local, // the definition should be visited first. Traverse blocks in an order that // is a topological sort of dominance partial order. - for (bb, data) in traversal::reverse_postorder(mir) { + for bb in traversal_order.iter().copied() { + let data = &mir.basic_blocks[bb]; analyzer.visit_basic_block_data(bb, data); } @@ -77,11 +73,22 @@ struct LocalAnalyzer<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> { impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> LocalAnalyzer<'a, 'b, 'tcx, Bx> { fn define(&mut self, local: mir::Local, location: DefLocation) { + let fx = self.fx; let kind = &mut self.locals[local]; + let decl = &fx.mir.local_decls[local]; match *kind { LocalKind::ZST => {} LocalKind::Memory => {} - LocalKind::Unused => *kind = LocalKind::SSA(location), + LocalKind::Unused => { + let ty = fx.monomorphize(decl.ty); + let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span); + *kind = + if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) { + LocalKind::SSA(location) + } else { + LocalKind::Memory + }; + } LocalKind::SSA(_) => *kind = LocalKind::Memory, } } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 61e9b9bd774..68fb5cb2206 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -218,7 +218,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx); - let memory_locals = analyze::non_ssa_locals(&fx); + let traversal_order = traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance); + let memory_locals = analyze::non_ssa_locals(&fx, &traversal_order); // Allocate variable and temp allocas let local_values = { @@ -277,17 +278,20 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); - let reachable_blocks = traversal::mono_reachable_as_bitset(mir, cx.tcx(), instance); + let mut unreached_blocks = BitSet::new_filled(mir.basic_blocks.len()); + // Codegen the body of each reachable block using our reverse postorder list. + for bb in traversal_order { + fx.codegen_block(bb); + unreached_blocks.remove(bb); + } - // Codegen the body of each block using reverse postorder - for (bb, _) in traversal::reverse_postorder(mir) { - if reachable_blocks.contains(bb) { - fx.codegen_block(bb); - } else { - // We want to skip this block, because it's not reachable. But we still create - // the block so terminators in other blocks can reference it. - fx.codegen_block_as_unreachable(bb); - } + // FIXME: These empty unreachable blocks are *mostly* a waste. They are occasionally + // targets for a SwitchInt terminator, but the reimplementation of the mono-reachable + // simplification in SwitchInt lowering sometimes misses cases that + // mono_reachable_reverse_postorder manages to figure out. + // The solution is to do something like post-mono GVN. But for now we have this hack. + for bb in unreached_blocks.iter() { + fx.codegen_block_as_unreachable(bb); } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0775.md b/compiler/rustc_error_codes/src/error_codes/E0775.md index 9bafd52f75c..efbd51e89ea 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0775.md +++ b/compiler/rustc_error_codes/src/error_codes/E0775.md @@ -1,13 +1,14 @@ +#### Note: this error code is no longer emitted by the compiler. + `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension. Erroneous code example: -```compile_fail,E0775 +```ignore (no longer emitted) #![feature(cmse_nonsecure_entry)] -#[cmse_nonsecure_entry] -pub extern "C" fn entry_function() {} +pub extern "C-cmse-nonsecure-entry" fn entry_function() {} ``` To fix this error, compile your code for a Rust target that supports the diff --git a/compiler/rustc_error_codes/src/error_codes/E0776.md b/compiler/rustc_error_codes/src/error_codes/E0776.md index d65beebe07c..e46d498d1c2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0776.md +++ b/compiler/rustc_error_codes/src/error_codes/E0776.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + `#[cmse_nonsecure_entry]` functions require a C ABI Erroneous code example: -```compile_fail,E0776 +```ignore (no longer emitted) #![feature(cmse_nonsecure_entry)] #[no_mangle] diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 11cad0b8f97..8631de65ec8 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -681,4 +681,5 @@ E0800: 0800, // E0723, // unstable feature in `const` context // E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`. // E0744, // merged into E0728 +// E0776, // Removed; cmse_nonsecure_entry is now `C-cmse-nonsecure-entry` // E0796, // unused error code. We use `static_mut_refs` lint instead. diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 0d56a005f15..84ae351ed72 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -41,7 +41,9 @@ use crate::errors::{ }; use crate::fluent_generated; use crate::mbe::diagnostics::annotate_err_with_kind; -use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod}; +use crate::module::{ + mod_dir_path, mod_file_path_from_attr, parse_external_mod, DirOwnership, ParsedExternalMod, +}; use crate::placeholders::{placeholder, PlaceholderExpander}; macro_rules! ast_fragments { @@ -1202,8 +1204,14 @@ impl InvocationCollectorNode for P<ast::Item> { ecx.current_expansion.dir_ownership, *inline, ); + // If the module was parsed from an external file, recover its path. + // This lets `parse_external_mod` catch cycles if it's self-referential. + let file_path = match inline { + Inline::Yes => None, + Inline::No => mod_file_path_from_attr(ecx.sess, &attrs, &dir_path), + }; node.attrs = attrs; - (None, dir_path, dir_ownership) + (file_path, dir_path, dir_ownership) } ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 13348376851..27a9a330f3c 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -171,7 +171,7 @@ fn mod_file_path<'a>( /// Derive a submodule path from the first found `#[path = "path_string"]`. /// The provided `dir_path` is joined with the `path_string`. -fn mod_file_path_from_attr( +pub(crate) fn mod_file_path_from_attr( sess: &Session, attrs: &[Attribute], dir_path: &Path, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 3b7e0d82d0f..fa5f152132a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -551,10 +551,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, experimental!(register_tool), ), - gated!( - cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing, - EncodeCrossCrate::No, experimental!(cmse_nonsecure_entry) - ), // RFC 2632 gated!( const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 40333c3953a..edc8e5f0752 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -395,7 +395,7 @@ declare_features! ( (unstable, closure_lifetime_binder, "1.64.0", Some(97362)), /// Allows `#[track_caller]` on closures and coroutines. (unstable, closure_track_caller, "1.57.0", Some(87417)), - /// Allows to use the `#[cmse_nonsecure_entry]` attribute. + /// Allows `extern "C-cmse-nonsecure-entry" fn()`. (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)), /// Allows `async {}` expressions in const contexts. (unstable, const_async_blocks, "1.53.0", Some(85368)), diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 633ccacedfc..09d466339ff 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -37,7 +37,7 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got} hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here -hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters +hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated {$what} of a trait with uninferred generic parameters .suggestion = use a fully qualified path with inferred lifetimes hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes @@ -48,6 +48,8 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found} +hir_analysis_bad_return_type_notation_position = return type notation not allowed in this position yet + hir_analysis_cannot_capture_late_bound_const = cannot capture late-bound const parameter in {$what} .label = parameter defined here @@ -478,7 +480,7 @@ hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`, bu hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]` -hir_analysis_too_large_static = extern static is too large for the current architecture +hir_analysis_too_large_static = extern static is too large for the target architecture hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]` .suggestion = remove this annotation diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index d0b0c08aa79..14ea7816291 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -9,6 +9,8 @@ use rustc_middle::ty::{self, Ty, TyCtxt, Upcast}; use rustc_span::def_id::DefId; use rustc_span::Span; +use crate::hir_ty_lowering::OnlySelfBounds; + /// Collects together a list of type bounds. These lists of bounds occur in many places /// in Rust's syntax: /// @@ -50,6 +52,7 @@ impl<'tcx> Bounds<'tcx> { span: Span, polarity: ty::PredicatePolarity, constness: ty::BoundConstness, + only_self_bounds: OnlySelfBounds, ) { let clause = ( bound_trait_ref @@ -66,7 +69,10 @@ impl<'tcx> Bounds<'tcx> { self.clauses.push(clause); } - if !tcx.features().effects { + // FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else. + // Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated + // type bounds. + if !tcx.features().effects || only_self_bounds.0 { return; } // For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index ac9976148e2..4c59f7540ee 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -460,7 +460,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { [] => (generics.span, format!("<{lt_name}>")), [bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")), }; - mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion { + mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion { fspan: lt_sp, first: sugg, sspan: span.with_hi(item_segment.ident.span.lo()), @@ -502,11 +502,12 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } Ty::new_error( self.tcx(), - self.tcx().dcx().emit_err(errors::AssociatedTypeTraitUninferredGenericParams { + self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams { span, inferred_sugg, bound, mpart_sugg, + what: "type", }), ) } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index d62727e76b5..7a254c884c2 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -10,6 +10,7 @@ use rustc_span::Span; use rustc_type_ir::Upcast; use tracing::{debug, instrument}; +use super::predicates_of::assert_only_contains_predicates_from; use super::ItemCtxt; use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter}; @@ -56,6 +57,9 @@ fn associated_type_bounds<'tcx>( tcx.def_path_str(assoc_item_def_id.to_def_id()), all_bounds ); + + assert_only_contains_predicates_from(filter, all_bounds, item_ty); + all_bounds } @@ -108,18 +112,21 @@ pub(super) fn explicit_item_bounds_with_filter( Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item(); let opaque_ty = item.expect_opaque_ty(); - return ty::EarlyBinder::bind(opaque_type_bounds( + let item_ty = Ty::new_projection_from_args( + tcx, + def_id.to_def_id(), + ty::GenericArgs::identity_for_item(tcx, def_id), + ); + let bounds = opaque_type_bounds( tcx, opaque_def_id.expect_local(), opaque_ty.bounds, - Ty::new_projection_from_args( - tcx, - def_id.to_def_id(), - ty::GenericArgs::identity_for_item(tcx, def_id), - ), + item_ty, item.span, filter, - )); + ); + assert_only_contains_predicates_from(filter, bounds, item_ty); + return ty::EarlyBinder::bind(bounds); } Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!( tcx.def_span(def_id), @@ -167,7 +174,9 @@ pub(super) fn explicit_item_bounds_with_filter( }) => { let args = GenericArgs::identity_for_item(tcx, def_id); let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); - opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter) + let bounds = opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter); + assert_only_contains_predicates_from(filter, bounds, item_ty); + bounds } // Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`, when we're // asking for the item bounds of the *opaques* in a trait's default method signature, we @@ -184,15 +193,18 @@ pub(super) fn explicit_item_bounds_with_filter( }; let args = GenericArgs::identity_for_item(tcx, def_id); let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); - tcx.arena.alloc_slice( + let bounds = &*tcx.arena.alloc_slice( &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter) .to_vec() .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }), - ) + ); + assert_only_contains_predicates_from(filter, bounds, item_ty); + bounds } hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[], _ => bug!("item_bounds called on {:?}", def_id), }; + ty::EarlyBinder::bind(bounds) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 7243e85ce98..67d8813d1f7 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -240,7 +240,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen for predicate in hir_generics.predicates { match predicate { hir::WherePredicate::BoundPredicate(bound_pred) => { - let ty = icx.lower_ty(bound_pred.bounded_ty); + let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); + let bound_vars = tcx.late_bound_vars(bound_pred.hir_id); // Keep the type around in a dummy predicate, in case of no bounds. // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` @@ -676,9 +677,63 @@ pub(super) fn implied_predicates_with_filter<'tcx>( _ => {} } + assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param); + ty::EarlyBinder::bind(implied_bounds) } +// Make sure when elaborating supertraits, probing for associated types, etc., +// we really truly are elaborating clauses that have `Self` as their self type. +// This is very important since downstream code relies on this being correct. +pub(super) fn assert_only_contains_predicates_from<'tcx>( + filter: PredicateFilter, + bounds: &'tcx [(ty::Clause<'tcx>, Span)], + ty: Ty<'tcx>, +) { + if !cfg!(debug_assertions) { + return; + } + + match filter { + PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => { + for (clause, _) in bounds { + match clause.kind().skip_binder() { + ty::ClauseKind::Trait(trait_predicate) => { + assert_eq!( + trait_predicate.self_ty(), + ty, + "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}" + ); + } + ty::ClauseKind::Projection(projection_predicate) => { + assert_eq!( + projection_predicate.self_ty(), + ty, + "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}" + ); + } + ty::ClauseKind::TypeOutlives(outlives_predicate) => { + assert_eq!( + outlives_predicate.0, ty, + "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}" + ); + } + + ty::ClauseKind::RegionOutlives(_) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) => { + bug!( + "unexpected non-`Self` predicate when computing `{filter:?}` implied bounds: {clause:?}" + ); + } + } + } + } + PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {} + } +} + /// Returns the predicates defined on `item_def_id` of the form /// `X: Foo` where `X` is the type parameter `def_id`. #[instrument(level = "trace", skip(tcx))] @@ -770,6 +825,10 @@ impl<'tcx> ItemCtxt<'tcx> { continue; }; + // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we + // want to only consider predicates with `Self: ...`, but we don't want + // `OnlySelfBounds(true)` since we want to collect the nested associated + // type bound as well. let (only_self_bounds, assoc_name) = match filter { PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => { (OnlySelfBounds(false), None) @@ -780,14 +839,10 @@ impl<'tcx> ItemCtxt<'tcx> { } }; - // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we - // want to only consider predicates with `Self: ...`, but we don't want - // `OnlySelfBounds(true)` since we want to collect the nested associated - // type bound as well. let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) { ty } else if matches!(filter, PredicateFilter::All) { - self.lower_ty(predicate.bounded_ty) + self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty) } else { continue; }; diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 53dcede91c3..d1601446b6f 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -889,7 +889,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { (pair, r) }) .unzip(); + self.record_late_bound_vars(hir_id, binders); + + // If this is an RTN type in the self type, then append those to the binder. + self.try_append_return_type_notation_params(hir_id, bounded_ty); + // Even if there are no lifetimes defined here, we still wrap it in a binder // scope. If there happens to be a nested poly trait ref (an error), that // will be `Concatenating` anyways, so we don't have to worry about the depth @@ -1635,9 +1640,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // } // ``` // and a bound that looks like: - // `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>` + // `for<'a> T::Trait<'a, x(..): for<'b> Other<'b>>` // this is going to expand to something like: - // `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`. + // `for<'a> for<'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`. if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { let bound_vars = if let Some(type_def_id) = type_def_id @@ -1839,6 +1844,178 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { let old_value = self.map.defs.swap_remove(&lifetime_ref.hir_id); assert_eq!(old_value, Some(bad_def)); } + + // When we have a return type notation type in a where clause, like + // `where <T as Trait>::method(..): Send`, we need to introduce new bound + // vars to the existing where clause's binder, to represent the lifetimes + // elided by the return-type-notation syntax. + // + // For example, given + // ``` + // trait Foo { + // async fn x<'r>(); + // } + // ``` + // and a bound that looks like: + // `for<'a, 'b> <T as Trait<'a>>::x(): Other<'b>` + // this is going to expand to something like: + // `for<'a, 'b, 'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: Other<'b>`. + // + // We handle this similarly for associated-type-bound style return-type-notation + // in `visit_segment_args`. + fn try_append_return_type_notation_params( + &mut self, + hir_id: HirId, + hir_ty: &'tcx hir::Ty<'tcx>, + ) { + let hir::TyKind::Path(qpath) = hir_ty.kind else { + // We only care about path types here. All other self types + // (including nesting the RTN type in another type) don't do + // anything. + return; + }; + + let (mut bound_vars, item_def_id, item_segment) = match qpath { + // If we have a fully qualified method, then we don't need to do any special lookup. + hir::QPath::Resolved(_, path) + if let [.., item_segment] = &path.segments[..] + && item_segment.args.is_some_and(|args| { + matches!( + args.parenthesized, + hir::GenericArgsParentheses::ReturnTypeNotation + ) + }) => + { + match path.res { + Res::Err => return, + Res::Def(DefKind::AssocFn, item_def_id) => (vec![], item_def_id, item_segment), + _ => bug!("only expected method resolution for fully qualified RTN"), + } + } + + // If we have a type-dependent path, then we do need to do some lookup. + hir::QPath::TypeRelative(qself, item_segment) + if item_segment.args.is_some_and(|args| { + matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation) + }) => + { + // First, ignore a qself that isn't a type or `Self` param. Those are the + // only ones that support `T::Assoc` anyways in HIR lowering. + let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = qself.kind else { + return; + }; + match path.res { + Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => { + // Get the generics of this type's hir owner. This is *different* + // from the generics of the parameter's definition, since we want + // to be able to resolve an RTN path on a nested body (e.g. method + // inside an impl) using the where clauses on the method. + // FIXME(return_type_notation): Think of some better way of doing this. + let Some(generics) = self.tcx.hir_owner_node(hir_id.owner).generics() + else { + return; + }; + + // Look for the first bound that contains an associated type that + // matches the segment that we're looking for. We ignore any subsequent + // bounds since we'll be emitting a hard error in HIR lowering, so this + // is purely speculative. + let one_bound = generics.predicates.iter().find_map(|predicate| { + let hir::WherePredicate::BoundPredicate(predicate) = predicate else { + return None; + }; + let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) = + predicate.bounded_ty.kind + else { + return None; + }; + if bounded_path.res != path.res { + return None; + } + predicate.bounds.iter().find_map(|bound| { + let hir::GenericBound::Trait(trait_, _) = bound else { + return None; + }; + BoundVarContext::supertrait_hrtb_vars( + self.tcx, + trait_.trait_ref.trait_def_id()?, + item_segment.ident, + ty::AssocKind::Fn, + ) + }) + }); + let Some((bound_vars, assoc_item)) = one_bound else { + return; + }; + (bound_vars, assoc_item.def_id, item_segment) + } + // If we have a self type alias (in an impl), try to resolve an + // associated item from one of the supertraits of the impl's trait. + Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => { + let hir::ItemKind::Impl(hir::Impl { of_trait: Some(trait_ref), .. }) = self + .tcx + .hir_node_by_def_id(impl_def_id.expect_local()) + .expect_item() + .kind + else { + return; + }; + let Some(trait_def_id) = trait_ref.trait_def_id() else { + return; + }; + let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars( + self.tcx, + trait_def_id, + item_segment.ident, + ty::AssocKind::Fn, + ) else { + return; + }; + (bound_vars, assoc_item.def_id, item_segment) + } + _ => return, + } + } + + _ => return, + }; + + // Append the early-bound vars on the function, and then the late-bound ones. + // We actually turn type parameters into higher-ranked types here, but we + // deny them later in HIR lowering. + bound_vars.extend(self.tcx.generics_of(item_def_id).own_params.iter().map(|param| { + match param.kind { + ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region( + ty::BoundRegionKind::BrNamed(param.def_id, param.name), + ), + ty::GenericParamDefKind::Type { .. } => { + ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name)) + } + ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const, + } + })); + bound_vars.extend(self.tcx.fn_sig(item_def_id).instantiate_identity().bound_vars()); + + // SUBTLE: Stash the old bound vars onto the *item segment* before appending + // the new bound vars. We do this because we need to know how many bound vars + // are present on the binder explicitly (i.e. not return-type-notation vars) + // to do bound var shifting correctly in HIR lowering. + // + // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`, + // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's + // parent) will include `'a` AND all the early- and late-bound vars of the + // method. But when lowering the RTN type, we just want the list of vars + // we used to resolve the trait ref. We explicitly stored those back onto + // the item segment, since there's no other good place to put them. + // + // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`. + // And this is exercised in: + // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`. + let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id).unwrap(); + let existing_bound_vars_saved = existing_bound_vars.clone(); + existing_bound_vars.extend(bound_vars); + self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved); + } } /// Detects late-bound lifetimes and inserts them into diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index e4e5f76ae32..4edb68e6199 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -780,14 +780,15 @@ pub(crate) struct PlaceholderNotAllowedItemSignatures { #[derive(Diagnostic)] #[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)] -pub(crate) struct AssociatedTypeTraitUninferredGenericParams { +pub(crate) struct AssociatedItemTraitUninferredGenericParams { #[primary_span] pub span: Span, #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")] pub inferred_sugg: Option<Span>, pub bound: String, #[subdiagnostic] - pub mpart_sugg: Option<AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion>, + pub mpart_sugg: Option<AssociatedItemTraitUninferredGenericParamsMultipartSuggestion>, + pub what: &'static str, } #[derive(Subdiagnostic)] @@ -795,7 +796,7 @@ pub(crate) struct AssociatedTypeTraitUninferredGenericParams { hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion, applicability = "maybe-incorrect" )] -pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion { +pub(crate) struct AssociatedItemTraitUninferredGenericParamsMultipartSuggestion { #[suggestion_part(code = "{first}")] pub fspan: Span, pub first: String, @@ -1693,3 +1694,10 @@ pub(crate) struct CmseCallGeneric { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_bad_return_type_notation_position)] +pub(crate) struct BadReturnTypeNotation { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index bffe68f9b74..6f7f3128347 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -6,6 +6,7 @@ use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::HirId; use rustc_middle::bug; use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt}; use rustc_span::symbol::Ident; @@ -15,6 +16,7 @@ use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, use smallvec::SmallVec; use tracing::{debug, instrument}; +use super::errors::GenericsArgsErrExtend; use crate::bounds::Bounds; use crate::errors; use crate::hir_ty_lowering::{ @@ -332,74 +334,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .or_insert(constraint.span); let projection_term = if let ty::AssocKind::Fn = assoc_kind { - let mut emitted_bad_param_err = None; - // If we have an method return type bound, then we need to instantiate - // the method's early bound params with suitable late-bound params. - let mut num_bound_vars = candidate.bound_vars().len(); - let args = - candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| { - let arg = match param.kind { - ty::GenericParamDefKind::Lifetime => ty::Region::new_bound( - tcx, - ty::INNERMOST, - ty::BoundRegion { - var: ty::BoundVar::from_usize(num_bound_vars), - kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name), - }, - ) - .into(), - ty::GenericParamDefKind::Type { .. } => { - let guar = *emitted_bad_param_err.get_or_insert_with(|| { - self.dcx().emit_err( - crate::errors::ReturnTypeNotationIllegalParam::Type { - span: path_span, - param_span: tcx.def_span(param.def_id), - }, - ) - }); - Ty::new_error(tcx, guar).into() - } - ty::GenericParamDefKind::Const { .. } => { - let guar = *emitted_bad_param_err.get_or_insert_with(|| { - self.dcx().emit_err( - crate::errors::ReturnTypeNotationIllegalParam::Const { - span: path_span, - param_span: tcx.def_span(param.def_id), - }, - ) - }); - ty::Const::new_error(tcx, guar).into() - } - }; - num_bound_vars += 1; - arg - }); - - // Next, we need to check that the return-type notation is being used on - // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). - let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output(); - let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() - && tcx.is_impl_trait_in_trait(alias_ty.def_id) - { - alias_ty.into() - } else { - return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit { - span: constraint.span, - ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), - fn_span: tcx.hir().span_if_local(assoc_item.def_id), - note: (), - })); - }; - - // Finally, move the fn return type's bound vars over to account for the early bound - // params (and trait ref's late bound params). This logic is very similar to - // `rustc_middle::ty::predicate::Clause::instantiate_supertrait` - // and it's no coincidence why. - let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); - let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args); - let bound_vars = tcx.late_bound_vars(constraint.hir_id); - ty::Binder::bind_with_vars(instantiation_output, bound_vars) + ty::Binder::bind_with_vars( + self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(), + bound_vars, + ) } else { // Create the generic arguments for the associated type or constant by joining the // parent arguments (the arguments of the trait) and the own arguments (the ones of @@ -525,6 +464,269 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } Ok(()) } + + /// Lower a type, possibly specially handling the type if it's a return type notation + /// which we otherwise deny in other positions. + pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { + let hir::TyKind::Path(qpath) = hir_ty.kind else { + return self.lower_ty(hir_ty); + }; + + let tcx = self.tcx(); + match qpath { + hir::QPath::Resolved(opt_self_ty, path) + if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..] + && item_segment.args.is_some_and(|args| { + matches!( + args.parenthesized, + hir::GenericArgsParentheses::ReturnTypeNotation + ) + }) => + { + // We don't allow generics on the module segments. + let _ = + self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None); + + let item_def_id = match path.res { + Res::Def(DefKind::AssocFn, item_def_id) => item_def_id, + Res::Err => { + return Ty::new_error_with_message( + tcx, + hir_ty.span, + "failed to resolve RTN", + ); + } + _ => bug!("only expected method resolution for fully qualified RTN"), + }; + let trait_def_id = tcx.parent(item_def_id); + + // Good error for `where Trait::method(..): Send`. + let Some(self_ty) = opt_self_ty else { + return self.error_missing_qpath_self_ty( + trait_def_id, + hir_ty.span, + item_segment, + ); + }; + let self_ty = self.lower_ty(self_ty); + + let trait_ref = self.lower_mono_trait_ref( + hir_ty.span, + trait_def_id, + self_ty, + trait_segment, + false, + ty::BoundConstness::NotConst, + ); + + // SUBTLE: As noted at the end of `try_append_return_type_notation_params` + // in `resolve_bound_vars`, we stash the explicit bound vars of the where + // clause onto the item segment of the RTN type. This allows us to know + // how many bound vars are *not* coming from the signature of the function + // from lowering RTN itself. + // + // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`, + // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's + // parent) will include `'a` AND all the early- and late-bound vars of the + // method. But when lowering the RTN type, we just want the list of vars + // we used to resolve the trait ref. We explicitly stored those back onto + // the item segment, since there's no other good place to put them. + let candidate = + ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id)); + + match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) { + Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty), + Err(guar) => Ty::new_error(tcx, guar), + } + } + hir::QPath::TypeRelative(qself, item_segment) + if item_segment.args.is_some_and(|args| { + matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation) + }) => + { + match self + .resolve_type_relative_return_type_notation( + qself, + item_segment, + hir_ty.hir_id, + hir_ty.span, + ) + .and_then(|(candidate, item_def_id)| { + self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) + }) { + Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty), + Err(guar) => Ty::new_error(tcx, guar), + } + } + _ => self.lower_ty(hir_ty), + } + } + + /// Perform type-dependent lookup for a *method* for return type notation. + /// This generally mirrors `<dyn HirTyLowerer>::lower_assoc_path`. + fn resolve_type_relative_return_type_notation( + &self, + qself: &'tcx hir::Ty<'tcx>, + item_segment: &'tcx hir::PathSegment<'tcx>, + qpath_hir_id: HirId, + span: Span, + ) -> Result<(ty::PolyTraitRef<'tcx>, DefId), ErrorGuaranteed> { + let tcx = self.tcx(); + let qself_ty = self.lower_ty(qself); + let assoc_ident = item_segment.ident; + let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind { + path.res + } else { + Res::Err + }; + + let bound = match (qself_ty.kind(), qself_res) { + (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { + // `Self` in an impl of a trait -- we have a concrete self type and a + // trait reference. + let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else { + // A cycle error occurred, most likely. + self.dcx().span_bug(span, "expected cycle error"); + }; + + self.probe_single_bound_for_assoc_item( + || { + traits::supertraits( + tcx, + ty::Binder::dummy(trait_ref.instantiate_identity()), + ) + }, + AssocItemQSelf::SelfTyAlias, + ty::AssocKind::Fn, + assoc_ident, + span, + None, + )? + } + ( + &ty::Param(_), + Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did), + ) => self.probe_single_ty_param_bound_for_assoc_item( + param_did.expect_local(), + qself.span, + ty::AssocKind::Fn, + assoc_ident, + span, + )?, + _ => { + if let Err(reported) = qself_ty.error_reported() { + return Err(reported); + } else { + // FIXME(return_type_notation): Provide some structured suggestion here. + let err = struct_span_code_err!( + self.dcx(), + span, + E0223, + "ambiguous associated function" + ); + return Err(err.emit()); + } + } + }; + + // Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`, + // which may happen via a higher-ranked where clause or supertrait. + // This is the same restrictions as associated types; even though we could + // support it, it just makes things a lot more difficult to support in + // `resolve_bound_vars`, since we'd need to introduce those as elided + // bound vars on the where clause too. + if bound.has_bound_vars() { + return Err(self.tcx().dcx().emit_err( + errors::AssociatedItemTraitUninferredGenericParams { + span, + inferred_sugg: Some(span.with_hi(item_segment.ident.span.lo())), + bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder(),), + mpart_sugg: None, + what: "function", + }, + )); + } + + let trait_def_id = bound.def_id(); + let assoc_ty = self + .probe_assoc_item(assoc_ident, ty::AssocKind::Fn, qpath_hir_id, span, trait_def_id) + .expect("failed to find associated type"); + + Ok((bound, assoc_ty.def_id)) + } + + /// Do the common parts of lowering an RTN type. This involves extending the + /// candidate binder to include all of the early- and late-bound vars that are + /// defined on the function itself, and constructing a projection to the RPITIT + /// return type of that function. + fn lower_return_type_notation_ty( + &self, + candidate: ty::PolyTraitRef<'tcx>, + item_def_id: DefId, + path_span: Span, + ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> { + let tcx = self.tcx(); + let mut emitted_bad_param_err = None; + // If we have an method return type bound, then we need to instantiate + // the method's early bound params with suitable late-bound params. + let mut num_bound_vars = candidate.bound_vars().len(); + let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| { + let arg = match param.kind { + ty::GenericParamDefKind::Lifetime => ty::Region::new_bound( + tcx, + ty::INNERMOST, + ty::BoundRegion { + var: ty::BoundVar::from_usize(num_bound_vars), + kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name), + }, + ) + .into(), + ty::GenericParamDefKind::Type { .. } => { + let guar = *emitted_bad_param_err.get_or_insert_with(|| { + self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type { + span: path_span, + param_span: tcx.def_span(param.def_id), + }) + }); + Ty::new_error(tcx, guar).into() + } + ty::GenericParamDefKind::Const { .. } => { + let guar = *emitted_bad_param_err.get_or_insert_with(|| { + self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const { + span: path_span, + param_span: tcx.def_span(param.def_id), + }) + }); + ty::Const::new_error(tcx, guar).into() + } + }; + num_bound_vars += 1; + arg + }); + + // Next, we need to check that the return-type notation is being used on + // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). + let output = tcx.fn_sig(item_def_id).skip_binder().output(); + let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() + && tcx.is_impl_trait_in_trait(alias_ty.def_id) + { + alias_ty + } else { + return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit { + span: path_span, + ty: tcx.liberate_late_bound_regions(item_def_id, output), + fn_span: tcx.hir().span_if_local(item_def_id), + note: (), + })); + }; + + // Finally, move the fn return type's bound vars over to account for the early bound + // params (and trait ref's late bound params). This logic is very similar to + // `rustc_middle::ty::predicate::Clause::instantiate_supertrait` + // and it's no coincidence why. + let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); + Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args)) + } } /// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7163352e8a4..35eebcb6be1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -53,7 +53,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::{debug, debug_span, instrument}; use crate::bounds::Bounds; -use crate::errors::{AmbiguousLifetimeBound, WildPatTy}; +use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy}; use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; @@ -719,6 +719,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span, polarity, constness, + only_self_bounds, ); let mut dup_constraints = FxIndexMap::default(); @@ -813,17 +814,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - /// Search for a trait bound on a type parameter whose trait defines the associated type given by `assoc_name`. + /// Search for a trait bound on a type parameter whose trait defines the associated item + /// given by `assoc_name` and `kind`. /// /// This fails if there is no such bound in the list of candidates or if there are multiple /// candidates in which case it reports ambiguity. /// /// `ty_param_def_id` is the `LocalDefId` of the type parameter. #[instrument(level = "debug", skip_all, ret)] - fn probe_single_ty_param_bound_for_assoc_ty( + fn probe_single_ty_param_bound_for_assoc_item( &self, ty_param_def_id: LocalDefId, ty_param_span: Span, + kind: ty::AssocKind, assoc_name: Ident, span: Span, ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> { @@ -841,7 +844,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name) }, AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span), - ty::AssocKind::Type, + kind, assoc_name, span, None, @@ -1081,9 +1084,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ( &ty::Param(_), Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did), - ) => self.probe_single_ty_param_bound_for_assoc_ty( + ) => self.probe_single_ty_param_bound_for_assoc_item( param_did.expect_local(), qself.span, + ty::AssocKind::Type, assoc_ident, span, )?, @@ -1545,48 +1549,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?trait_def_id); let Some(self_ty) = opt_self_ty else { - let path_str = tcx.def_path_str(trait_def_id); - - let def_id = self.item_def_id(); - debug!(item_def_id = ?def_id); - - // FIXME: document why/how this is different from `tcx.local_parent(def_id)` - let parent_def_id = - tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id(); - debug!(?parent_def_id); - - // If the trait in segment is the same as the trait defining the item, - // use the `<Self as ..>` syntax in the error. - let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id; - let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id; - - let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait { - vec!["Self".to_string()] - } else { - // Find all the types that have an `impl` for the trait. - tcx.all_impls(trait_def_id) - .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) - .filter(|header| { - // Consider only accessible traits - tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) - && header.polarity != ty::ImplPolarity::Negative - }) - .map(|header| header.trait_ref.instantiate_identity().self_ty()) - // We don't care about blanket impls. - .filter(|self_ty| !self_ty.has_non_region_param()) - .map(|self_ty| tcx.erase_regions(self_ty).to_string()) - .collect() - }; - // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that - // references the trait. Relevant for the first case in - // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs` - let reported = self.report_ambiguous_assoc_ty( - span, - &type_names, - &[path_str], - item_segment.ident.name, - ); - return Ty::new_error(tcx, reported); + return self.error_missing_qpath_self_ty(trait_def_id, span, item_segment); }; debug!(?self_ty); @@ -1600,6 +1563,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_projection_from_args(tcx, item_def_id, item_args) } + fn error_missing_qpath_self_ty( + &self, + trait_def_id: DefId, + span: Span, + item_segment: &hir::PathSegment<'tcx>, + ) -> Ty<'tcx> { + let tcx = self.tcx(); + let path_str = tcx.def_path_str(trait_def_id); + + let def_id = self.item_def_id(); + debug!(item_def_id = ?def_id); + + // FIXME: document why/how this is different from `tcx.local_parent(def_id)` + let parent_def_id = + tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id(); + debug!(?parent_def_id); + + // If the trait in segment is the same as the trait defining the item, + // use the `<Self as ..>` syntax in the error. + let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id; + let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id; + + let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait { + vec!["Self".to_string()] + } else { + // Find all the types that have an `impl` for the trait. + tcx.all_impls(trait_def_id) + .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) + .filter(|header| { + // Consider only accessible traits + tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) + && header.polarity != ty::ImplPolarity::Negative + }) + .map(|header| header.trait_ref.instantiate_identity().self_ty()) + // We don't care about blanket impls. + .filter(|self_ty| !self_ty.has_non_region_param()) + .map(|self_ty| tcx.erase_regions(self_ty).to_string()) + .collect() + }; + // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that + // references the trait. Relevant for the first case in + // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs` + let reported = + self.report_ambiguous_assoc_ty(span, &type_names, &[path_str], item_segment.ident.name); + Ty::new_error(tcx, reported) + } + pub fn prohibit_generic_args<'a>( &self, segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone, @@ -1930,7 +1940,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .tcx() .dcx() .span_delayed_bug(path.span, "path with `Res::Err` but no error emitted"); - Ty::new_error(self.tcx(), e) + Ty::new_error(tcx, e) } Res::Def(..) => { assert_eq!( @@ -2061,6 +2071,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) } + // If we encounter a fully qualified path with RTN generics, then it must have + // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore + // it's certainly in an illegal position. + hir::TyKind::Path(hir::QPath::Resolved(_, path)) + if path.segments.last().and_then(|segment| segment.args).is_some_and(|args| { + matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation) + }) => + { + let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span }); + Ty::new_error(tcx, guar) + } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself)); @@ -2085,6 +2106,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } + // If we encounter a type relative path with RTN generics, then it must have + // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore + // it's certainly in an illegal position. + hir::TyKind::Path(hir::QPath::TypeRelative(_, segment)) + if segment.args.is_some_and(|args| { + matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation) + }) => + { + let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span }); + Ty::new_error(tcx, guar) + } hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => { debug!(?qself, ?segment); let ty = self.lower_ty(qself); diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index f39d83a2a6f..81d940a3f9b 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("{v} bits") } else { // `u128` should definitely be able to hold the size of different architectures - // larger sizes should be reported as error `are too big for the current architecture` + // larger sizes should be reported as error `are too big for the target architecture` // otherwise we have a bug somewhere bug!("{:?} overflow for u128", size) } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index d81052b5e24..ce4ee45c485 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -332,6 +332,9 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { return; } + // Issue #45127: don't enforce `snake_case` for binary crates as binaries are not intended + // to be distributed and depended on like libraries. The lint is not suppressed for cdylib + // or staticlib because it's not clear what the desired lint behavior for those are. if cx.tcx.crate_types().iter().all(|&crate_type| crate_type == CrateType::Executable) { return; } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index f9d0cd49708..3d042f21745 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1320,7 +1320,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } fn is_internal_abi(&self, abi: SpecAbi) -> bool { - matches!(abi, SpecAbi::Rust | SpecAbi::RustCall | SpecAbi::RustIntrinsic) + matches!( + abi, + SpecAbi::Rust | SpecAbi::RustCall | SpecAbi::RustCold | SpecAbi::RustIntrinsic + ) } /// Find any fn-ptr types with external ABIs in `ty`. diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 2b9d9a07a98..39485a324f2 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -103,5 +103,5 @@ middle_unknown_layout = the type `{$ty}` has an unknown layout middle_values_too_big = - values of the type `{$ty}` are too big for the current architecture + values of the type `{$ty}` are too big for the target architecture middle_written_to_path = the full type name has been written to '{$path}' diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index b7d290e58d2..90dff0f5c7d 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -120,9 +120,7 @@ bitflags::bitflags! { /// #[ffi_const]: applies clang's `const` attribute to a foreign function /// declaration. const FFI_CONST = 1 << 12; - /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a - /// function as an entry function from Non-Secure code. - const CMSE_NONSECURE_ENTRY = 1 << 13; + // (Bit 13 was used for `#[cmse_nonsecure_entry]`, but is now unused.) // (Bit 14 was used for `#[coverage(off)]`, but is now unused.) /// `#[used(linker)]`: /// indicates that neither LLVM nor the linker will eliminate this function. diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 183b898253e..63ce47ef327 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -71,7 +71,7 @@ impl<'tcx> BasicBlocks<'tcx> { #[inline] pub fn reverse_postorder(&self) -> &[BasicBlock] { self.cache.reverse_postorder.get_or_init(|| { - let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK).collect(); + let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, ()).collect(); rpo.reverse(); rpo }) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e312e65cc21..54dcfaf5d54 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1424,6 +1424,19 @@ impl<'tcx> BasicBlockData<'tcx> { pub fn is_empty_unreachable(&self) -> bool { self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable) } + + /// Like [`Terminator::successors`] but tries to use information available from the [`Instance`] + /// to skip successors like the `false` side of an `if const {`. + /// + /// This is used to implement [`traversal::mono_reachable`] and + /// [`traversal::mono_reachable_reverse_postorder`]. + pub fn mono_successors(&self, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Successors<'_> { + if let Some((bits, targets)) = Body::try_const_mono_switchint(tcx, instance, self) { + targets.successors_for_value(bits) + } else { + self.terminator().successors() + } + } } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 962b93a25aa..c34e22eb873 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -413,6 +413,17 @@ mod helper { use super::*; pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a; pub type SuccessorsMut<'a> = impl DoubleEndedIterator<Item = &'a mut BasicBlock> + 'a; + + impl SwitchTargets { + /// Like [`SwitchTargets::target_for_value`], but returning the same type as + /// [`Terminator::successors`]. + #[inline] + pub fn successors_for_value(&self, value: u128) -> Successors<'_> { + let target = self.target_for_value(value); + (&[]).into_iter().copied().chain(Some(target)) + } + } + impl<'tcx> TerminatorKind<'tcx> { #[inline] pub fn successors(&self) -> Successors<'_> { diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 245e9096bad..b8b74da401c 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -104,36 +104,46 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { /// ``` /// /// A Postorder traversal of this graph is `D B C A` or `D C B A` -pub struct Postorder<'a, 'tcx> { +pub struct Postorder<'a, 'tcx, C> { basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>, visited: BitSet<BasicBlock>, visit_stack: Vec<(BasicBlock, Successors<'a>)>, root_is_start_block: bool, + extra: C, } -impl<'a, 'tcx> Postorder<'a, 'tcx> { +impl<'a, 'tcx, C> Postorder<'a, 'tcx, C> +where + C: Customization<'tcx>, +{ pub fn new( basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>, root: BasicBlock, - ) -> Postorder<'a, 'tcx> { + extra: C, + ) -> Postorder<'a, 'tcx, C> { let mut po = Postorder { basic_blocks, visited: BitSet::new_empty(basic_blocks.len()), visit_stack: Vec::new(), root_is_start_block: root == START_BLOCK, + extra, }; - let data = &po.basic_blocks[root]; - - if let Some(ref term) = data.terminator { - po.visited.insert(root); - po.visit_stack.push((root, term.successors())); - po.traverse_successor(); - } + po.visit(root); + po.traverse_successor(); po } + fn visit(&mut self, bb: BasicBlock) { + if !self.visited.insert(bb) { + return; + } + let data = &self.basic_blocks[bb]; + let successors = C::successors(data, self.extra); + self.visit_stack.push((bb, successors)); + } + fn traverse_successor(&mut self) { // This is quite a complex loop due to 1. the borrow checker not liking it much // and 2. what exactly is going on is not clear @@ -183,16 +193,15 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { // since we've already visited `E`, that child isn't added to the stack. The last // two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A] while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) { - if self.visited.insert(bb) { - if let Some(term) = &self.basic_blocks[bb].terminator { - self.visit_stack.push((bb, term.successors())); - } - } + self.visit(bb); } } } -impl<'tcx> Iterator for Postorder<'_, 'tcx> { +impl<'tcx, C> Iterator for Postorder<'_, 'tcx, C> +where + C: Customization<'tcx>, +{ type Item = BasicBlock; fn next(&mut self) -> Option<BasicBlock> { @@ -232,6 +241,40 @@ pub fn postorder<'a, 'tcx>( reverse_postorder(body).rev() } +/// Lets us plug in some additional logic and data into a Postorder traversal. Or not. +pub trait Customization<'tcx>: Copy { + fn successors<'a>(_: &'a BasicBlockData<'tcx>, _: Self) -> Successors<'a>; +} + +impl<'tcx> Customization<'tcx> for () { + fn successors<'a>(data: &'a BasicBlockData<'tcx>, _: ()) -> Successors<'a> { + data.terminator().successors() + } +} + +impl<'tcx> Customization<'tcx> for (TyCtxt<'tcx>, Instance<'tcx>) { + fn successors<'a>( + data: &'a BasicBlockData<'tcx>, + (tcx, instance): (TyCtxt<'tcx>, Instance<'tcx>), + ) -> Successors<'a> { + data.mono_successors(tcx, instance) + } +} + +pub fn mono_reachable_reverse_postorder<'a, 'tcx>( + body: &'a Body<'tcx>, + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, +) -> Vec<BasicBlock> { + let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, (tcx, instance)); + let mut items = Vec::with_capacity(body.basic_blocks.len()); + while let Some(block) = iter.next() { + items.push(block); + } + items.reverse(); + items +} + /// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular /// order. /// @@ -358,14 +401,8 @@ impl<'a, 'tcx> Iterator for MonoReachable<'a, 'tcx> { let data = &self.body[idx]; - if let Some((bits, targets)) = - Body::try_const_mono_switchint(self.tcx, self.instance, data) - { - let target = targets.target_for_value(bits); - self.add_work([target]); - } else { - self.add_work(data.terminator().successors()); - } + let targets = data.mono_successors(self.tcx, self.instance); + self.add_work(targets); return Some((idx, data)); } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 877c54c5649..941091b71d3 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -264,7 +264,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { match *self { LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"), LayoutError::SizeOverflow(ty) => { - write!(f, "values of the type `{ty}` are too big for the current architecture") + write!(f, "values of the type `{ty}` are too big for the target architecture") } LayoutError::NormalizationFailure(t, e) => write!( f, @@ -1191,6 +1191,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> | RiscvInterruptM | RiscvInterruptS | CCmseNonSecureCall + | CCmseNonSecureEntry | Unadjusted => false, Rust | RustCall | RustCold | RustIntrinsic => { tcx.sess.panic_strategy() == PanicStrategy::Unwind diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2f4dc8abfcd..841f255dc3a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -188,9 +188,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | [sym::rustc_must_implement_one_of, ..] | [sym::rustc_deny_explicit_impl, ..] | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target), - [sym::cmse_nonsecure_entry, ..] => { - self.check_cmse_nonsecure_entry(hir_id, attr, span, target) - } [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), [sym::must_use, ..] => self.check_must_use(hir_id, attr, target), @@ -563,27 +560,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition. - fn check_cmse_nonsecure_entry( - &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, - ) { - match target { - Target::Fn - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {} - _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); - } - } - } - /// Debugging aid for `object_lifetime_default` query. fn check_object_lifetime_default(&self, hir_id: HirId) { let tcx = self.tcx; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6458c888431..fc9d8f998dc 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -138,6 +138,61 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { ); assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } + + /// Determines whether the const argument `AnonConst` is a simple macro call, optionally + /// surrounded with braces. + /// + /// If this const argument *is* a trivial macro call then the id for the macro call is + /// returned along with the information required to build the anon const's def if + /// the macro call expands to a non-trivial expression. + fn is_const_arg_trivial_macro_expansion( + &self, + anon_const: &'a AnonConst, + ) -> Option<(PendingAnonConstInfo, NodeId)> { + let (block_was_stripped, expr) = anon_const.value.maybe_unwrap_block(); + match expr { + Expr { kind: ExprKind::MacCall(..), id, .. } => Some(( + PendingAnonConstInfo { + id: anon_const.id, + span: anon_const.value.span, + block_was_stripped, + }, + *id, + )), + _ => None, + } + } + + /// Determines whether the expression `const_arg_sub_expr` is a simple macro call, sometimes + /// surrounded with braces if a set of braces has not already been entered. This is required + /// as `{ N }` is treated as equivalent to a bare parameter `N` whereas `{{ N }}` is treated as + /// a real block expression and is lowered to an anonymous constant which is not allowed to use + /// generic parameters. + /// + /// If this expression is a trivial macro call then the id for the macro call is + /// returned along with the information required to build the anon const's def if + /// the macro call expands to a non-trivial expression. + fn is_const_arg_sub_expr_trivial_macro_expansion( + &self, + const_arg_sub_expr: &'a Expr, + ) -> Option<(PendingAnonConstInfo, NodeId)> { + let pending_anon = self.pending_anon_const_info.unwrap_or_else(|| + panic!("Checking expr is trivial macro call without having entered anon const: `{const_arg_sub_expr:?}`"), + ); + + let (block_was_stripped, expr) = if pending_anon.block_was_stripped { + (true, const_arg_sub_expr) + } else { + const_arg_sub_expr.maybe_unwrap_block() + }; + + match expr { + Expr { kind: ExprKind::MacCall(..), id, .. } => { + Some((PendingAnonConstInfo { block_was_stripped, ..pending_anon }, *id)) + } + _ => None, + } + } } impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { @@ -354,12 +409,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { // items will be messed up, but that's ok because there can't be any if we're just looking // for bare idents. - if matches!(constant.value.maybe_unwrap_block().kind, ExprKind::MacCall(..)) { - // See self.pending_anon_const_info for explanation - self.pending_anon_const_info = - Some(PendingAnonConstInfo { id: constant.id, span: constant.value.span }); - return visit::walk_anon_const(self, constant); - } else if constant.value.is_potential_trivial_const_arg() { + if let Some((pending_anon, macro_invoc)) = + self.is_const_arg_trivial_macro_expansion(constant) + { + self.pending_anon_const_info = Some(pending_anon); + return self.visit_macro_invoc(macro_invoc); + } else if constant.value.is_potential_trivial_const_arg(true) { return visit::walk_anon_const(self, constant); } @@ -368,23 +423,36 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } fn visit_expr(&mut self, expr: &'a Expr) { - if matches!(expr.kind, ExprKind::MacCall(..)) { - return self.visit_macro_invoc(expr.id); + // If we're visiting the expression of a const argument that was a macro call then + // check if it is *still* unknown whether it is a trivial const arg or not. If so + // recurse into the macro call and delay creating the anon const def until expansion. + if self.pending_anon_const_info.is_some() + && let Some((pending_anon, macro_invoc)) = + self.is_const_arg_sub_expr_trivial_macro_expansion(expr) + { + self.pending_anon_const_info = Some(pending_anon); + return self.visit_macro_invoc(macro_invoc); } - let grandparent_def = if let Some(pending_anon) = self.pending_anon_const_info.take() { - // See self.pending_anon_const_info for explanation - if !expr.is_potential_trivial_const_arg() { + // See self.pending_anon_const_info for explanation + let parent_def = self + .pending_anon_const_info + .take() + // If we already stripped away a set of braces then do not do it again when determining + // if the macro expanded to a trivial const arg. This arises in cases such as: + // `Foo<{ bar!() }>` where `bar!()` expands to `{ N }`. This should not be considered a + // trivial const argument even though `{ N }` by itself *is*. + .filter(|pending_anon| { + !expr.is_potential_trivial_const_arg(!pending_anon.block_was_stripped) + }) + .map(|pending_anon| { self.create_def(pending_anon.id, kw::Empty, DefKind::AnonConst, pending_anon.span) - } else { - self.parent_def - } - } else { - self.parent_def - }; + }) + .unwrap_or(self.parent_def); - self.with_parent(grandparent_def, |this| { + self.with_parent(parent_def, |this| { let parent_def = match expr.kind { + ExprKind::MacCall(..) => return this.visit_macro_invoc(expr.id), ExprKind::Closure(..) | ExprKind::Gen(..) => { this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span) } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ac03a3ac42c..4c84e3621dc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -404,6 +404,8 @@ pub(crate) enum PathSource<'a> { Delegation, /// An arg in a `use<'a, N>` precise-capturing bound. PreciseCapturingArg(Namespace), + // Paths that end with `(..)`, for return type notation. + ReturnTypeNotation, } impl<'a> PathSource<'a> { @@ -413,7 +415,8 @@ impl<'a> PathSource<'a> { PathSource::Expr(..) | PathSource::Pat | PathSource::TupleStruct(..) - | PathSource::Delegation => ValueNS, + | PathSource::Delegation + | PathSource::ReturnTypeNotation => ValueNS, PathSource::TraitItem(ns) => ns, PathSource::PreciseCapturingArg(ns) => ns, } @@ -425,7 +428,8 @@ impl<'a> PathSource<'a> { | PathSource::Expr(..) | PathSource::Pat | PathSource::Struct - | PathSource::TupleStruct(..) => true, + | PathSource::TupleStruct(..) + | PathSource::ReturnTypeNotation => true, PathSource::Trait(_) | PathSource::TraitItem(..) | PathSource::Delegation @@ -471,7 +475,7 @@ impl<'a> PathSource<'a> { }, _ => "value", }, - PathSource::Delegation => "function", + PathSource::ReturnTypeNotation | PathSource::Delegation => "function", PathSource::PreciseCapturingArg(..) => "type or const parameter", } } @@ -540,6 +544,10 @@ impl<'a> PathSource<'a> { Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true, _ => false, }, + PathSource::ReturnTypeNotation => match res { + Res::Def(DefKind::AssocFn, _) => true, + _ => false, + }, PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)), PathSource::PreciseCapturingArg(ValueNS) => { matches!(res, Res::Def(DefKind::ConstParam, _)) @@ -565,8 +573,8 @@ impl<'a> PathSource<'a> { (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425, (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532, (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531, - (PathSource::TraitItem(..), true) => E0575, - (PathSource::TraitItem(..), false) => E0576, + (PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575, + (PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576, (PathSource::PreciseCapturingArg(..), true) => E0799, (PathSource::PreciseCapturingArg(..), false) => E0800, } @@ -781,7 +789,20 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r } TyKind::Path(qself, path) => { self.diag_metadata.current_type_path = Some(ty); - self.smart_resolve_path(ty.id, qself, path, PathSource::Type); + + // If we have a path that ends with `(..)`, then it must be + // return type notation. Resolve that path in the *value* + // namespace. + let source = if let Some(seg) = path.segments.last() + && let Some(args) = &seg.args + && matches!(**args, GenericArgs::ParenthesizedElided(..)) + { + PathSource::ReturnTypeNotation + } else { + PathSource::Type + }; + + self.smart_resolve_path(ty.id, qself, path, source); // Check whether we should interpret this as a bare trait object. if qself.is_none() @@ -1920,7 +1941,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { PathSource::Trait(..) | PathSource::TraitItem(..) | PathSource::Type - | PathSource::PreciseCapturingArg(..) => false, + | PathSource::PreciseCapturingArg(..) + | PathSource::ReturnTypeNotation => false, PathSource::Expr(..) | PathSource::Pat | PathSource::Struct @@ -4524,7 +4546,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); self.resolve_anon_const_manual( - constant.value.is_potential_trivial_const_arg(), + constant.value.is_potential_trivial_const_arg(true), anon_const_kind, |this| this.resolve_expr(&constant.value, None), ) @@ -4688,7 +4710,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // that is how they will be later lowered to HIR. if const_args.contains(&idx) { self.resolve_anon_const_manual( - argument.is_potential_trivial_const_arg(), + argument.is_potential_trivial_const_arg(true), AnonConstKind::ConstArg(IsRepeatExpr::No), |this| this.resolve_expr(argument, None), ); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c05bd9e72ea..3bb1f6b52a7 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -190,6 +190,11 @@ impl InvocationParent { #[derive(Copy, Debug, Clone)] struct PendingAnonConstInfo { + // A const arg is only a "trivial" const arg if it has at *most* one set of braces + // around the argument. We track whether we have stripped an outter brace so that + // if a macro expands to a braced expression *and* the macro was itself inside of + // some braces then we can consider it to be a non-trivial const argument. + block_was_stripped: bool, id: NodeId, span: Span, } diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index f52cb010a87..e9c3b3ffc1d 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -470,6 +470,7 @@ impl RustcInternal for Abi { Abi::AvrInterrupt => rustc_target::spec::abi::Abi::AvrInterrupt, Abi::AvrNonBlockingInterrupt => rustc_target::spec::abi::Abi::AvrNonBlockingInterrupt, Abi::CCmseNonSecureCall => rustc_target::spec::abi::Abi::CCmseNonSecureCall, + Abi::CCmseNonSecureEntry => rustc_target::spec::abi::Abi::CCmseNonSecureEntry, Abi::System { unwind } => rustc_target::spec::abi::Abi::System { unwind }, Abi::RustIntrinsic => rustc_target::spec::abi::Abi::RustIntrinsic, Abi::RustCall => rustc_target::spec::abi::Abi::RustCall, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index 9f554ec6c35..06f01aebf9b 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -105,6 +105,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv { Conv::PreserveAll => CallConvention::PreserveAll, Conv::ArmAapcs => CallConvention::ArmAapcs, Conv::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall, + Conv::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry, Conv::Msp430Intr => CallConvention::Msp430Intr, Conv::PtxKernel => CallConvention::PtxKernel, Conv::X86Fastcall => CallConvention::X86Fastcall, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index efbb0f244fc..74bdf97ac44 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -910,6 +910,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::spec::abi::Abi { abi::Abi::AvrInterrupt => Abi::AvrInterrupt, abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt, abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall, + abi::Abi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry, abi::Abi::System { unwind } => Abi::System { unwind }, abi::Abi::RustIntrinsic => Abi::RustIntrinsic, abi::Abi::RustCall => Abi::RustCall, diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 060ee4a1bc2..f4469467249 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -779,6 +779,7 @@ pub enum Conv { // Target-specific calling conventions. ArmAapcs, CCmseNonSecureCall, + CCmseNonSecureEntry, Msp430Intr, @@ -972,6 +973,7 @@ impl FromStr for Conv { "RustCold" => Ok(Conv::Rust), "ArmAapcs" => Ok(Conv::ArmAapcs), "CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall), + "CCmseNonSecureEntry" => Ok(Conv::CCmseNonSecureEntry), "Msp430Intr" => Ok(Conv::Msp430Intr), "PtxKernel" => Ok(Conv::PtxKernel), "X86Fastcall" => Ok(Conv::X86Fastcall), diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs index 9436e34d380..5fcf5be101f 100644 --- a/compiler/rustc_target/src/json.rs +++ b/compiler/rustc_target/src/json.rs @@ -103,6 +103,7 @@ impl ToJson for crate::abi::call::Conv { Self::PreserveAll => "PreserveAll", Self::ArmAapcs => "ArmAapcs", Self::CCmseNonSecureCall => "CCmseNonSecureCall", + Self::CCmseNonSecureEntry => "CCmseNonSecureEntry", Self::Msp430Intr => "Msp430Intr", Self::PtxKernel => "PtxKernel", Self::X86Fastcall => "X86Fastcall", diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index cc383f88fbc..cac0cf9959d 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -48,6 +48,7 @@ pub enum Abi { AvrInterrupt, AvrNonBlockingInterrupt, CCmseNonSecureCall, + CCmseNonSecureEntry, System { unwind: bool, }, @@ -124,6 +125,7 @@ const AbiDatas: &[AbiData] = &[ AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" }, AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" }, AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" }, + AbiData { abi: Abi::CCmseNonSecureEntry, name: "C-cmse-nonsecure-entry" }, AbiData { abi: Abi::System { unwind: false }, name: "system" }, AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" }, AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" }, @@ -244,6 +246,10 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> { feature: sym::abi_c_cmse_nonsecure_call, explain: "C-cmse-nonsecure-call ABI is experimental and subject to change", }), + "C-cmse-nonsecure-entry" => Err(AbiDisabled::Unstable { + feature: sym::cmse_nonsecure_entry, + explain: "C-cmse-nonsecure-entry ABI is experimental and subject to change", + }), _ => Err(AbiDisabled::Unrecognized), } } @@ -286,15 +292,16 @@ impl Abi { AvrInterrupt => 23, AvrNonBlockingInterrupt => 24, CCmseNonSecureCall => 25, + CCmseNonSecureEntry => 26, // Cross-platform ABIs - System { unwind: false } => 26, - System { unwind: true } => 27, - RustIntrinsic => 28, - RustCall => 29, - Unadjusted => 30, - RustCold => 31, - RiscvInterruptM => 32, - RiscvInterruptS => 33, + System { unwind: false } => 27, + System { unwind: true } => 28, + RustIntrinsic => 29, + RustCall => 30, + Unadjusted => 31, + RustCold => 32, + RiscvInterruptM => 33, + RiscvInterruptS => 34, }; debug_assert!( AbiDatas diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1d478f84c43..ec4f5ef79d1 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2724,7 +2724,10 @@ impl Target { } X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), Aapcs { .. } => "arm" == self.arch, - CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]), + CCmseNonSecureCall | CCmseNonSecureEntry => { + ["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"] + .contains(&&self.llvm_target[..]) + } Win64 { .. } | SysV64 { .. } => self.arch == "x86_64", PtxKernel => self.arch == "nvptx64", Msp430Interrupt => self.arch == "msp430", diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 2de6ee9cf91..1f11ee3f939 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2269,12 +2269,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } rustc_transmute::Reason::SrcSizeOverflow => { format!( - "values of the type `{src}` are too big for the current architecture" + "values of the type `{src}` are too big for the target architecture" ) } rustc_transmute::Reason::DstSizeOverflow => { format!( - "values of the type `{dst}` are too big for the current architecture" + "values of the type `{dst}` are too big for the target architecture" ) } rustc_transmute::Reason::DstHasStricterAlignment { diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 2d0c2e83690..00d38350b20 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -312,6 +312,7 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv { SysV64 { .. } => Conv::X86_64SysV, Aapcs { .. } => Conv::ArmAapcs, CCmseNonSecureCall => Conv::CCmseNonSecureCall, + CCmseNonSecureEntry => Conv::CCmseNonSecureEntry, PtxKernel => Conv::PtxKernel, Msp430Interrupt => Conv::Msp430Intr, X86Interrupt => Conv::X86Intr, diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 317bec3050c..dc73d9c2188 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -433,6 +433,7 @@ pub enum CallConvention { // Target-specific calling conventions. ArmAapcs, CCmseNonSecureCall, + CCmseNonSecureEntry, Msp430Intr, diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs index 5bad3d5ae7a..011d19f6143 100644 --- a/compiler/stable_mir/src/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -1062,6 +1062,7 @@ pub enum Abi { AvrInterrupt, AvrNonBlockingInterrupt, CCmseNonSecureCall, + CCmseNonSecureEntry, System { unwind: bool }, RustIntrinsic, RustCall, diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index d58a016b502..83977350832 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2087,7 +2087,31 @@ impl FromUtf8Error { #[cfg(not(no_global_oom_handling))] #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")] pub fn into_utf8_lossy(self) -> String { - String::from_utf8_lossy_owned(self.bytes) + const REPLACEMENT: &str = "\u{FFFD}"; + + let mut res = { + let mut v = Vec::with_capacity(self.bytes.len()); + + // `Utf8Error::valid_up_to` returns the maximum index of validated + // UTF-8 bytes. Copy the valid bytes into the output buffer. + v.extend_from_slice(&self.bytes[..self.error.valid_up_to()]); + + // SAFETY: This is safe because the only bytes present in the buffer + // were validated as UTF-8 by the call to `String::from_utf8` which + // produced this `FromUtf8Error`. + unsafe { String::from_utf8_unchecked(v) } + }; + + let iter = self.bytes[self.error.valid_up_to()..].utf8_chunks(); + + for chunk in iter { + res.push_str(chunk.valid()); + if !chunk.invalid().is_empty() { + res.push_str(REPLACEMENT); + } + } + + res } /// Returns the bytes that were attempted to convert to a `String`. diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index ffc9a233b66..1d07a7690da 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -28,6 +28,7 @@ #![feature(iter_next_chunk)] #![feature(round_char_boundary)] #![feature(slice_partition_dedup)] +#![feature(string_from_utf8_lossy_owned)] #![feature(string_remove_matches)] #![feature(const_btree_len)] #![feature(const_trait_impl)] diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs index dc03c4860e8..d996c55f946 100644 --- a/library/alloc/tests/string.rs +++ b/library/alloc/tests/string.rs @@ -115,6 +115,43 @@ fn test_from_utf8_lossy() { } #[test] +fn test_fromutf8error_into_lossy() { + fn func(input: &[u8]) -> String { + String::from_utf8(input.to_owned()).unwrap_or_else(|e| e.into_utf8_lossy()) + } + + let xs = b"hello"; + let ys = "hello".to_owned(); + assert_eq!(func(xs), ys); + + let xs = "ศไทย中华Việt Nam".as_bytes(); + let ys = "ศไทย中华Việt Nam".to_owned(); + assert_eq!(func(xs), ys); + + let xs = b"Hello\xC2 There\xFF Goodbye"; + assert_eq!(func(xs), "Hello\u{FFFD} There\u{FFFD} Goodbye".to_owned()); + + let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye"; + assert_eq!(func(xs), "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye".to_owned()); + + let xs = b"\xF5foo\xF5\x80bar"; + assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}\u{FFFD}bar".to_owned()); + + let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz"; + assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz".to_owned()); + + let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz"; + assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz".to_owned()); + + let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar"; + assert_eq!(func(xs), "\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar".to_owned()); + + // surrogates + let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar"; + assert_eq!(func(xs), "\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar".to_owned()); +} + +#[test] fn test_from_utf16() { let pairs = [ ( diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 5451e45f6c8..962da6643dd 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1761,6 +1761,8 @@ mod prim_ref {} /// - `i32` is ABI-compatible with `NonZero<i32>`, and similar for all other integer types. /// - If `T` is guaranteed to be subject to the [null pointer /// optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible. +/// Furthermore, if `U` satisfies the requirements [outlined here](result/index.html#representation), +/// then `T` and `Result<T, U>` and `Result<U, T>` are all ABI-compatible. /// /// Furthermore, ABI compatibility satisfies the following general properties: /// diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile index 855465aa38e..475542b3356 100644 --- a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile @@ -25,5 +25,5 @@ ENV CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \ ENV HOSTS=arm-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs +ENV RUST_CONFIGURE_ARGS --enable-full-tools --enable-profiler --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md b/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md index 338fbc4b2bf..ca95ccf33ac 100644 --- a/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md +++ b/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md @@ -15,10 +15,10 @@ LLVM, the Rust compiler and the linker are providing TrustZone-M feature. One of the things provided, with this unstable feature, is the -`cmse_nonsecure_entry` attribute. This attribute marks a Secure function as an +`C-cmse-nonsecure-entry` ABI. This ABI marks a Secure function as an entry function (see [section 5.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details). -With this attribute, the compiler will do the following: +With this ABI, the compiler will do the following: * add a special symbol on the function which is the `__acle_se_` prefix and the standard function name * constrain the number of parameters to avoid using the Non-Secure stack @@ -38,11 +38,11 @@ gateway veneer. <!-- NOTE(ignore) this example is specific to thumbv8m targets --> ``` rust,ignore +#![no_std] #![feature(cmse_nonsecure_entry)] #[no_mangle] -#[cmse_nonsecure_entry] -pub extern "C" fn entry_function(input: u32) -> u32 { +pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { input + 6 } ``` diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs index e4966690d8c..654fb564848 100644 --- a/src/tools/clippy/clippy_utils/src/mir/mod.rs +++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs @@ -30,7 +30,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) - locals.len() ]; - traversal::Postorder::new(&mir.basic_blocks, location.block) + traversal::Postorder::new(&mir.basic_blocks, location.block, ()) .collect::<Vec<_>>() .into_iter() .rev() diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index c3276d82d4f..76fe17316ac 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c0838c8ebec23fb87855bb6de3a287981cb1df98 +6ce376774c0bc46ac8be247bca93ff5a1287a8fc diff --git a/src/tools/miri/rustfmt.toml b/src/tools/miri/rustfmt.toml index be5af7379ea..3f9311d9d1a 100644 --- a/src/tools/miri/rustfmt.toml +++ b/src/tools/miri/rustfmt.toml @@ -1,4 +1,4 @@ -version = "Two" +style_edition = "2024" use_small_heuristics = "Max" match_arm_blocks = false match_arm_leading_pipes = "Preserve" diff --git a/src/tools/miri/tests/fail/type-too-large.stderr b/src/tools/miri/tests/fail/type-too-large.stderr index 15ad8f1764d..cd27b246389 100644 --- a/src/tools/miri/tests/fail/type-too-large.stderr +++ b/src/tools/miri/tests/fail/type-too-large.stderr @@ -1,8 +1,8 @@ -error: post-monomorphization error: values of the type `[u8; 2305843011361177600]` are too big for the current architecture +error: post-monomorphization error: values of the type `[u8; 2305843011361177600]` are too big for the target architecture --> tests/fail/type-too-large.rs:LL:CC | LL | _fat = [0; (1u64 << 61) as usize + (1u64 << 31) as usize]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843011361177600]` are too big for the current architecture + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843011361177600]` are too big for the target architecture | = note: BACKTRACE: = note: inside `main` at tests/fail/type-too-large.rs:LL:CC diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 2f4e764f4ce..26ab02558a1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -377,6 +377,7 @@ pub enum FnAbi { AvrNonBlockingInterrupt, C, CCmseNonsecureCall, + CCmseNonsecureEntry, CDecl, CDeclUnwind, CUnwind, @@ -434,6 +435,7 @@ impl FnAbi { s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt, s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt, s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall, + s if *s == sym::C_dash_cmse_dash_nonsecure_dash_entry => FnAbi::CCmseNonsecureEntry, s if *s == sym::C_dash_unwind => FnAbi::CUnwind, s if *s == sym::C => FnAbi::C, s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind, @@ -477,6 +479,7 @@ impl FnAbi { FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt", FnAbi::C => "C", FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call", + FnAbi::CCmseNonsecureEntry => "C-cmse-nonsecure-entry", FnAbi::CDecl => "C-decl", FnAbi::CDeclUnwind => "cdecl-unwind", FnAbi::CUnwind => "C-unwind", diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs index 1a06e0a3a0e..b0e417e6b33 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs @@ -32,6 +32,7 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[ "riscv-interrupt-m", "riscv-interrupt-s", "C-cmse-nonsecure-call", + "C-cmse-nonsecure-entry", "wasm", "system", "system-unwind", diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 7eb8e4a5e2e..c066f504891 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -94,6 +94,7 @@ define_symbols! { avr_dash_interrupt = "avr-interrupt", avr_dash_non_dash_blocking_dash_interrupt = "avr-non-blocking-interrupt", C_dash_cmse_dash_nonsecure_dash_call = "C-cmse-nonsecure-call", + C_dash_cmse_dash_nonsecure_dash_entry = "C-cmse-nonsecure-entry", C_dash_unwind = "C-unwind", cdecl_dash_unwind = "cdecl-unwind", fastcall_dash_unwind = "fastcall-unwind", diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index b2de3457dec..3879f350e94 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -467,7 +467,6 @@ ui/closures/issue-87814-2.rs ui/closures/issue-90871.rs ui/closures/issue-97607.rs ui/closures/issue-99565.rs -ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs ui/codegen/auxiliary/issue-97708-aux.rs ui/codegen/issue-101585-128bit-repeat.rs ui/codegen/issue-16602-1.rs @@ -552,7 +551,6 @@ ui/const-generics/infer/issue-77092.rs ui/const-generics/issue-102124.rs ui/const-generics/issue-105689.rs ui/const-generics/issue-106419-struct-with-multiple-const-params.rs -ui/const-generics/issue-112505-overflow.rs ui/const-generics/issue-46511.rs ui/const-generics/issue-66451.rs ui/const-generics/issue-70408.rs @@ -2717,7 +2715,6 @@ ui/limits/issue-15919-32.rs ui/limits/issue-15919-64.rs ui/limits/issue-17913.rs ui/limits/issue-55878.rs -ui/limits/issue-56762.rs ui/limits/issue-69485-var-size-diffs-too-large.rs ui/limits/issue-75158-64.rs ui/linkage-attr/auxiliary/issue-12133-dylib.rs diff --git a/tests/assembly/cmse.rs b/tests/assembly/cmse.rs new file mode 100644 index 00000000000..acad77b2513 --- /dev/null +++ b/tests/assembly/cmse.rs @@ -0,0 +1,26 @@ +//@ assembly-output: emit-asm +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1 +//@ needs-llvm-components: arm +#![crate_type = "lib"] +#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)] +#![no_core] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} + +// CHECK-LABEL: __acle_se_entry_point +// CHECK: bxns +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 { + 0 +} + +// CHECK-LABEL: call_nonsecure +// CHECK: blxns +#[no_mangle] +pub fn call_nonsecure( + f: unsafe extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64, +) -> u64 { + unsafe { f(0, 1, 2, 3) } +} diff --git a/tests/codegen/constant-branch.rs b/tests/codegen/constant-branch.rs index a2710cc4b25..8fc8fb4f57a 100644 --- a/tests/codegen/constant-branch.rs +++ b/tests/codegen/constant-branch.rs @@ -7,18 +7,19 @@ // CHECK-LABEL: @if_bool #[no_mangle] pub fn if_bool() { - // CHECK: br label %{{.+}} + // CHECK-NOT: br i1 + // CHECK-NOT: switch _ = if true { 0 } else { 1 }; - // CHECK: br label %{{.+}} _ = if false { 0 } else { 1 }; } // CHECK-LABEL: @if_constant_int_eq #[no_mangle] pub fn if_constant_int_eq() { + // CHECK-NOT: br i1 + // CHECK-NOT: switch let val = 0; - // CHECK: br label %{{.+}} _ = if val == 0 { 0 } else { 1 }; // CHECK: br label %{{.+}} @@ -28,23 +29,20 @@ pub fn if_constant_int_eq() { // CHECK-LABEL: @if_constant_match #[no_mangle] pub fn if_constant_match() { - // CHECK: br label %{{.+}} + // CHECK-NOT: br i1 + // CHECK-NOT: switch _ = match 1 { 1 => 2, 2 => 3, _ => 4, }; - // CHECK: br label %{{.+}} _ = match 1 { 2 => 3, _ => 4, }; - // CHECK: br label %[[MINUS1:.+]] _ = match -1 { - // CHECK: [[MINUS1]]: - // CHECK: store i32 1 -1 => 1, _ => 0, } diff --git a/tests/codegen/no-alloca-inside-if-false.rs b/tests/codegen/no-alloca-inside-if-false.rs new file mode 100644 index 00000000000..a231c7e808a --- /dev/null +++ b/tests/codegen/no-alloca-inside-if-false.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 -Cpanic=abort +// Check that there's an alloca for the reference and the vector, but nothing else. +// We use panic=abort because unwinding panics give hint::black_box a cleanup block, which has +// another alloca. + +#![crate_type = "lib"] + +#[inline(never)] +fn test<const SIZE: usize>() { + // CHECK-LABEL: no_alloca_inside_if_false::test + // CHECK: start: + // CHECK-NEXT: alloca [{{12|24}} x i8] + // CHECK-NOT: alloca + if const { SIZE < 4096 } { + let arr = [0u8; SIZE]; + std::hint::black_box(&arr); + } else { + let vec = vec![0u8; SIZE]; + std::hint::black_box(&vec); + } +} + +// CHECK-LABEL: @main +#[no_mangle] +pub fn main() { + test::<8192>(); +} diff --git a/tests/crashes/125476.rs b/tests/crashes/125476.rs index aa9a081388d..ad739639b72 100644 --- a/tests/crashes/125476.rs +++ b/tests/crashes/125476.rs @@ -1,4 +1,4 @@ //@ known-bug: rust-lang/rust#125476 //@ only-x86_64 -pub struct Data([u8; usize::MAX >> 16]); +pub struct Data([u8; usize::MAX >> 2]); const _: &'static [Data] = &[]; diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs index a8c8a85c5aa..af64901ace0 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs @@ -16,4 +16,22 @@ fn bar<T: Trait<method() -> (): Send>>() {} fn baz<T: Trait<method(): Send>>() {} //~^ ERROR return type notation arguments must be elided with `..` +fn foo_path<T: Trait>() where T::method(i32): Send {} +//~^ ERROR argument types not allowed with return type notation + +fn bar_path<T: Trait>() where T::method() -> (): Send {} +//~^ ERROR return type not allowed with return type notation + +fn baz_path<T: Trait>() where T::method(): Send {} +//~^ ERROR return type notation arguments must be elided with `..` + +fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {} +//~^ ERROR expected associated type + +fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {} +//~^ ERROR expected associated type + +fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {} +//~^ ERROR expected associated type + fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr index 7e1695984f1..68081470087 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr @@ -1,3 +1,21 @@ +error[E0575]: expected associated type, found associated function `Trait::method` + --> $DIR/bad-inputs-and-output.rs:28:36 + | +LL | fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type + +error[E0575]: expected associated type, found associated function `Trait::method` + --> $DIR/bad-inputs-and-output.rs:31:36 + | +LL | fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type + +error[E0575]: expected associated type, found associated function `Trait::method` + --> $DIR/bad-inputs-and-output.rs:34:36 + | +LL | fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {} + | ^^^^^^^^^^^^^^^^^^^^^^ not a associated type + warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bad-inputs-and-output.rs:3:12 | @@ -25,5 +43,24 @@ error: return type notation arguments must be elided with `..` LL | fn baz<T: Trait<method(): Send>>() {} | ^^ help: add `..`: `(..)` -error: aborting due to 3 previous errors; 1 warning emitted +error: argument types not allowed with return type notation + --> $DIR/bad-inputs-and-output.rs:19:40 + | +LL | fn foo_path<T: Trait>() where T::method(i32): Send {} + | ^^^^^ help: remove the input types: `()` + +error: return type not allowed with return type notation + --> $DIR/bad-inputs-and-output.rs:22:42 + | +LL | fn bar_path<T: Trait>() where T::method() -> (): Send {} + | ^^^^^^ help: remove the return type + +error: return type notation arguments must be elided with `..` + --> $DIR/bad-inputs-and-output.rs:25:40 + | +LL | fn baz_path<T: Trait>() where T::method(): Send {} + | ^^ help: add `..`: `(..)` + +error: aborting due to 9 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0575`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs b/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs index f507d82afec..185c0523633 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs @@ -10,17 +10,12 @@ trait Tr { fn foo<T: Tr>() where T::method(..): Send, - //~^ ERROR return type notation not allowed in this position yet - //~| ERROR expected type, found function <T as Tr>::method(..): Send, - //~^ ERROR return type notation not allowed in this position yet - //~| ERROR expected associated type, found associated function `Tr::method` { let _ = T::CONST::(..); //~^ ERROR return type notation not allowed in this position yet let _: T::method(..); //~^ ERROR return type notation not allowed in this position yet - //~| ERROR expected type, found function } fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr b/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr index cb45de59c7e..dca2bdeab0a 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr @@ -1,9 +1,3 @@ -error[E0575]: expected associated type, found associated function `Tr::method` - --> $DIR/bare-path.rs:15:5 - | -LL | <T as Tr>::method(..): Send, - | ^^^^^^^^^^^^^^^^^^^^^ not a associated type - warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bare-path.rs:1:12 | @@ -14,53 +8,16 @@ LL | #![feature(return_type_notation)] = note: `#[warn(incomplete_features)]` on by default error: return type notation not allowed in this position yet - --> $DIR/bare-path.rs:19:23 + --> $DIR/bare-path.rs:15:23 | LL | let _ = T::CONST::(..); | ^^^^ error: return type notation not allowed in this position yet - --> $DIR/bare-path.rs:21:21 + --> $DIR/bare-path.rs:17:12 | LL | let _: T::method(..); - | ^^^^ - -error: return type notation not allowed in this position yet - --> $DIR/bare-path.rs:12:14 - | -LL | T::method(..): Send, - | ^^^^ - -error: return type notation not allowed in this position yet - --> $DIR/bare-path.rs:15:22 - | -LL | <T as Tr>::method(..): Send, - | ^^^^ - -error: expected type, found function - --> $DIR/bare-path.rs:12:8 - | -LL | T::method(..): Send, - | ^^^^^^ unexpected function - | -note: the associated function is defined here - --> $DIR/bare-path.rs:7:5 - | -LL | fn method() -> impl Sized; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected type, found function - --> $DIR/bare-path.rs:21:15 - | -LL | let _: T::method(..); - | ^^^^^^ unexpected function - | -note: the associated function is defined here - --> $DIR/bare-path.rs:7:5 - | -LL | fn method() -> impl Sized; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0575`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs new file mode 100644 index 00000000000..d4f21f47c6c --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs @@ -0,0 +1,52 @@ +//@ check-pass + +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Trait<'a> { + fn late<'b>(&'b self, _: &'a ()) -> impl Sized; + fn early<'b: 'b>(&'b self, _: &'a ()) -> impl Sized; +} + +#[allow(refining_impl_trait_internal)] +impl<'a> Trait<'a> for () { + fn late<'b>(&'b self, _: &'a ()) -> i32 { 1 } + fn early<'b: 'b>(&'b self, _: &'a ()) -> i32 { 1 } +} + +trait Other<'c> {} +impl Other<'_> for i32 {} + +fn test<T>(t: &T) +where + T: for<'a, 'c> Trait<'a, late(..): Other<'c>>, + // which is basically: + // for<'a, 'c> Trait<'a, for<'b> method<'b>: Other<'c>>, + T: for<'a, 'c> Trait<'a, early(..): Other<'c>>, + // which is basically: + // for<'a, 'c> Trait<'a, for<'b> method<'b>: Other<'c>>, +{ + is_other_impl(t.late(&())); + is_other_impl(t.early(&())); +} + +fn test_path<T>(t: &T) +where +T: for<'a> Trait<'a>, + for<'a, 'c> <T as Trait<'a>>::late(..): Other<'c>, + // which is basically: + // for<'a, 'b, 'c> <T as Trait<'a>>::method::<'b>: Other<'c> + for<'a, 'c> <T as Trait<'a>>::early(..): Other<'c>, + // which is basically: + // for<'a, 'b, 'c> <T as Trait<'a>>::method::<'b>: Other<'c> +{ + is_other_impl(t.late(&())); + is_other_impl(t.early(&())); +} + +fn is_other_impl(_: impl for<'c> Other<'c>) {} + +fn main() { + test(&()); + test(&()); +} diff --git a/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr new file mode 100644 index 00000000000..c67231c07f7 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/higher-ranked-bound-works.rs:3:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs new file mode 100644 index 00000000000..9bdc2d00233 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs @@ -0,0 +1,42 @@ +//@ check-pass + +#![allow(non_camel_case_types)] +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Foo { + type test; + + fn test() -> impl Bar; +} + +fn call_path<T: Foo>() +where + T::test(..): Bar, +{ +} + +fn call_bound<T: Foo<test(..): Bar>>() {} + +trait Bar {} +struct NotBar; +struct YesBar; +impl Bar for YesBar {} + +impl Foo for () { + type test = NotBar; + + // Use refinement here so we can observe `YesBar: Bar`. + #[allow(refining_impl_trait_internal)] + fn test() -> YesBar { + YesBar + } +} + +fn main() { + // If `T::test(..)` resolved to the GAT (erroneously), then this would be + // an error since `<() as Foo>::bar` -- the associated type -- does not + // implement `Bar`, but the return type of the method does. + call_path::<()>(); + call_bound::<()>(); +} diff --git a/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr new file mode 100644 index 00000000000..f4ece074b28 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/namespace-conflict.rs:4:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs index d283c6eab37..35d6dd799c7 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs @@ -5,7 +5,10 @@ trait Trait { fn method() {} } -fn test<T: Trait<method(..): Send>>() {} -//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait` +fn bound<T: Trait<method(..): Send>>() {} +//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait` + +fn path<T>() where T: Trait, T::method(..): Send {} +//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait` fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr index 79ced3c96ed..e308c927bf0 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr @@ -8,15 +8,26 @@ LL | #![feature(return_type_notation)] = note: `#[warn(incomplete_features)]` on by default error: return type notation used on function that is not `async` and does not return `impl Trait` - --> $DIR/non-rpitit.rs:8:18 + --> $DIR/non-rpitit.rs:8:19 | LL | fn method() {} | ----------- this function must be `async` or return `impl Trait` ... -LL | fn test<T: Trait<method(..): Send>>() {} - | ^^^^^^^^^^^^^^^^ +LL | fn bound<T: Trait<method(..): Send>>() {} + | ^^^^^^^^^^^^^^^^ | = note: function returns `()`, which is not compatible with associated type return bounds -error: aborting due to 1 previous error; 1 warning emitted +error: return type notation used on function that is not `async` and does not return `impl Trait` + --> $DIR/non-rpitit.rs:11:30 + | +LL | fn method() {} + | ----------- this function must be `async` or return `impl Trait` +... +LL | fn path<T>() where T: Trait, T::method(..): Send {} + | ^^^^^^^^^^^^^ + | + = note: function returns `()`, which is not compatible with associated type return bounds + +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs new file mode 100644 index 00000000000..d94ec6b74d9 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs @@ -0,0 +1,42 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +fn function() {} + +fn not_a_method() +where + function(..): Send, + //~^ ERROR expected function, found function `function` + //~| ERROR return type notation not allowed in this position yet +{ +} + +fn not_a_method_and_typoed() +where + function(): Send, + //~^ ERROR expected type, found function `function` +{ +} + +trait Tr { + fn method(); +} + +// Forgot the `T::` +fn maybe_method_overlaps<T: Tr>() +where + method(..): Send, + //~^ ERROR cannot find function `method` in this scope + //~| ERROR return type notation not allowed in this position yet +{ +} + +// Forgot the `T::`, AND typoed `(..)` to `()` +fn maybe_method_overlaps_and_typoed<T: Tr>() +where + method(): Send, + //~^ ERROR cannot find type `method` in this scope +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr new file mode 100644 index 00000000000..8add2d46296 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr @@ -0,0 +1,49 @@ +error[E0575]: expected function, found function `function` + --> $DIR/not-a-method.rs:8:5 + | +LL | function(..): Send, + | ^^^^^^^^^^^^ not a function + +error[E0573]: expected type, found function `function` + --> $DIR/not-a-method.rs:16:5 + | +LL | function(): Send, + | ^^^^^^^^^^ not a type + +error[E0576]: cannot find function `method` in this scope + --> $DIR/not-a-method.rs:28:5 + | +LL | method(..): Send, + | ^^^^^^ not found in this scope + +error[E0412]: cannot find type `method` in this scope + --> $DIR/not-a-method.rs:37:5 + | +LL | method(): Send, + | ^^^^^^ not found in this scope + +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/not-a-method.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: return type notation not allowed in this position yet + --> $DIR/not-a-method.rs:8:5 + | +LL | function(..): Send, + | ^^^^^^^^^^^^ + +error: return type notation not allowed in this position yet + --> $DIR/not-a-method.rs:28:5 + | +LL | method(..): Send, + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0412, E0573, E0575, E0576. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs new file mode 100644 index 00000000000..cb42c33e364 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs @@ -0,0 +1,27 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait A { + fn method() -> impl Sized; +} +trait B { + fn method() -> impl Sized; +} + +fn ambiguous<T: A + B>() +where + T::method(..): Send, + //~^ ERROR ambiguous associated function `method` in bounds of `T` +{ +} + +trait Sub: A + B {} + +fn ambiguous_via_supertrait<T: Sub>() +where + T::method(..): Send, + //~^ ERROR ambiguous associated function `method` in bounds of `T` +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr new file mode 100644 index 00000000000..e841049ac66 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr @@ -0,0 +1,54 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-ambiguous.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0221]: ambiguous associated function `method` in bounds of `T` + --> $DIR/path-ambiguous.rs:13:5 + | +LL | fn method() -> impl Sized; + | -------------------------- ambiguous `method` from `A` +... +LL | fn method() -> impl Sized; + | -------------------------- ambiguous `method` from `B` +... +LL | T::method(..): Send, + | ^^^^^^^^^^^^^ ambiguous associated function `method` + | +help: use fully-qualified syntax to disambiguate + | +LL | <T as B>::method(..): Send, + | ~~~~~~~~~~ +help: use fully-qualified syntax to disambiguate + | +LL | <T as A>::method(..): Send, + | ~~~~~~~~~~ + +error[E0221]: ambiguous associated function `method` in bounds of `T` + --> $DIR/path-ambiguous.rs:22:5 + | +LL | fn method() -> impl Sized; + | -------------------------- ambiguous `method` from `A` +... +LL | fn method() -> impl Sized; + | -------------------------- ambiguous `method` from `B` +... +LL | T::method(..): Send, + | ^^^^^^^^^^^^^ ambiguous associated function `method` + | +help: use fully-qualified syntax to disambiguate + | +LL | <T as B>::method(..): Send, + | ~~~~~~~~~~ +help: use fully-qualified syntax to disambiguate + | +LL | <T as A>::method(..): Send, + | ~~~~~~~~~~ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0221`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs new file mode 100644 index 00000000000..56abd167fb6 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs @@ -0,0 +1,24 @@ +//@ check-pass + +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Trait { + fn method() -> impl Sized; +} + +fn is_send(_: impl Send) {} + +struct W<T>(T); + +impl<T> W<T> { + fn test() + where + T: Trait, + T::method(..): Send, + { + is_send(T::method()); + } +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr new file mode 100644 index 00000000000..3db033d8cf5 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-constrained-in-method.rs:3:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs new file mode 100644 index 00000000000..a4d8f005371 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs @@ -0,0 +1,25 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait A<'a> { + fn method() -> impl Sized; +} +trait B: for<'a> A<'a> {} + +fn higher_ranked<T>() +where + T: for<'a> A<'a>, + T::method(..): Send, + //~^ ERROR cannot use the associated function of a trait with uninferred generic parameters +{ +} + +fn higher_ranked_via_supertrait<T>() +where + T: B, + T::method(..): Send, + //~^ ERROR cannot use the associated function of a trait with uninferred generic parameters +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr new file mode 100644 index 00000000000..22de6165503 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr @@ -0,0 +1,34 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-higher-ranked.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0212]: cannot use the associated function of a trait with uninferred generic parameters + --> $DIR/path-higher-ranked.rs:12:5 + | +LL | T::method(..): Send, + | ^^^^^^^^^^^^^ + | +help: use a fully qualified path with inferred lifetimes + | +LL | <T as A<'_>>::method(..): Send, + | ~~~~~~~~~~~~~~ + +error[E0212]: cannot use the associated function of a trait with uninferred generic parameters + --> $DIR/path-higher-ranked.rs:20:5 + | +LL | T::method(..): Send, + | ^^^^^^^^^^^^^ + | +help: use a fully qualified path with inferred lifetimes + | +LL | <T as A<'_>>::method(..): Send, + | ~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0212`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs b/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs new file mode 100644 index 00000000000..c1a7b95ca2d --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs @@ -0,0 +1,25 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait A { + #[allow(non_camel_case_types)] + type bad; +} + +fn fully_qualified<T: A>() +where + <T as A>::method(..): Send, + //~^ ERROR cannot find method or associated constant `method` in trait `A` + <T as A>::bad(..): Send, + //~^ ERROR expected method or associated constant, found associated type `A::bad` +{ +} + +fn type_dependent<T: A>() +where + T::method(..): Send, + //~^ associated function `method` not found for `T` +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr new file mode 100644 index 00000000000..0130c3bc614 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr @@ -0,0 +1,33 @@ +error[E0576]: cannot find method or associated constant `method` in trait `A` + --> $DIR/path-missing.rs:11:15 + | +LL | <T as A>::method(..): Send, + | ^^^^^^ not found in `A` + +error[E0575]: expected method or associated constant, found associated type `A::bad` + --> $DIR/path-missing.rs:13:5 + | +LL | <T as A>::bad(..): Send, + | ^^^^^^^^^^^^^^^^^ + | + = note: can't use a type alias as a constructor + +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-missing.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0220]: associated function `method` not found for `T` + --> $DIR/path-missing.rs:20:8 + | +LL | T::method(..): Send, + | ^^^^^^ associated function `method` not found + +error: aborting due to 3 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0220, E0575, E0576. +For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs new file mode 100644 index 00000000000..d2636789c10 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs @@ -0,0 +1,15 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Trait { + fn method() -> impl Sized; +} + +fn test() +where + Trait::method(..): Send, + //~^ ERROR ambiguous associated type +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr new file mode 100644 index 00000000000..d66b0a109fc --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr @@ -0,0 +1,23 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-no-qself.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0223]: ambiguous associated type + --> $DIR/path-no-qself.rs:10:5 + | +LL | Trait::method(..): Send, + | ^^^^^^^^^^^^^^^^^ + | +help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path + | +LL | <Example as Trait>::method: Send, + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs new file mode 100644 index 00000000000..b0e6ea852b0 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs @@ -0,0 +1,21 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Trait { + fn method() -> impl Sized; +} + +struct Adt; + +fn non_param_qself() +where + <()>::method(..): Send, + //~^ ERROR ambiguous associated function + i32::method(..): Send, + //~^ ERROR ambiguous associated function + Adt::method(..): Send, + //~^ ERROR ambiguous associated function +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr new file mode 100644 index 00000000000..cd1aa9813e3 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr @@ -0,0 +1,30 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-non-param-qself.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0223]: ambiguous associated function + --> $DIR/path-non-param-qself.rs:12:5 + | +LL | <()>::method(..): Send, + | ^^^^^^^^^^^^^^^^ + +error[E0223]: ambiguous associated function + --> $DIR/path-non-param-qself.rs:14:5 + | +LL | i32::method(..): Send, + | ^^^^^^^^^^^^^^^ + +error[E0223]: ambiguous associated function + --> $DIR/path-non-param-qself.rs:16:5 + | +LL | Adt::method(..): Send, + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs new file mode 100644 index 00000000000..0cf84457ba7 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs @@ -0,0 +1,27 @@ +//@ check-pass + +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Foo { + fn method() -> impl Sized; +} + +trait Bar: Foo { + fn other() + where + Self::method(..): Send; +} + +fn is_send(_: impl Send) {} + +impl<T: Foo> Bar for T { + fn other() + where + Self::method(..): Send, + { + is_send(Self::method()); + } +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr new file mode 100644 index 00000000000..ab33647583c --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-self-qself.rs:3:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs new file mode 100644 index 00000000000..693a300eb1d --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs @@ -0,0 +1,22 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Foo { + fn method<T>() -> impl Sized; +} + +fn test<T: Foo>() +where + <T as Foo>::method(..): Send, + //~^ ERROR return type notation is not allowed for functions that have type parameters +{ +} + +fn test_type_dependent<T: Foo>() +where + <T as Foo>::method(..): Send, + //~^ ERROR return type notation is not allowed for functions that have type parameters +{ +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr new file mode 100644 index 00000000000..0d33d4f97d7 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr @@ -0,0 +1,29 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-type-param.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error: return type notation is not allowed for functions that have type parameters + --> $DIR/path-type-param.rs:10:5 + | +LL | fn method<T>() -> impl Sized; + | - type parameter declared here +... +LL | <T as Foo>::method(..): Send, + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: return type notation is not allowed for functions that have type parameters + --> $DIR/path-type-param.rs:17:5 + | +LL | fn method<T>() -> impl Sized; + | - type parameter declared here +... +LL | <T as Foo>::method(..): Send, + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs new file mode 100644 index 00000000000..a5b0b0e4e25 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs @@ -0,0 +1,25 @@ +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Trait { + fn method() -> impl Sized; +} + +struct DoesntWork; +impl Trait for DoesntWork { + fn method() -> impl Sized { + std::ptr::null_mut::<()>() + // This isn't `Send`. + } +} + +fn test<T: Trait>() +where + T::method(..): Send, +{ +} + +fn main() { + test::<DoesntWork>(); + //~^ ERROR `*mut ()` cannot be sent between threads safely +} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr new file mode 100644 index 00000000000..7d32a428555 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr @@ -0,0 +1,36 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-unsatisfied.rs:1:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0277]: `*mut ()` cannot be sent between threads safely + --> $DIR/path-unsatisfied.rs:23:12 + | +LL | fn method() -> impl Sized { + | ---------- within this `impl Sized` +... +LL | test::<DoesntWork>(); + | ^^^^^^^^^^ `*mut ()` cannot be sent between threads safely + | + = help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()`, which is required by `impl Sized: Send` +note: required because it appears within the type `impl Sized` + --> $DIR/path-unsatisfied.rs:10:20 + | +LL | fn method() -> impl Sized { + | ^^^^^^^^^^ +note: required by a bound in `test` + --> $DIR/path-unsatisfied.rs:18:20 + | +LL | fn test<T: Trait>() + | ---- required by a bound in this function +LL | where +LL | T::method(..): Send, + | ^^^^ required by this bound in `test` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-works.rs b/tests/ui/associated-type-bounds/return-type-notation/path-works.rs new file mode 100644 index 00000000000..027bc89f13e --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-works.rs @@ -0,0 +1,23 @@ +//@ check-pass + +#![feature(return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Trait { + fn method() -> impl Sized; +} + +struct Works; +impl Trait for Works { + fn method() -> impl Sized {} +} + +fn test<T: Trait>() +where + T::method(..): Send, +{ +} + +fn main() { + test::<Works>(); +} diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr new file mode 100644 index 00000000000..b1ec8069ba0 --- /dev/null +++ b/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/path-works.rs:3:12 + | +LL | #![feature(return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs index bea5faf7253..cb196471fd7 100644 --- a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs +++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs @@ -1,13 +1,7 @@ // This checks that the attribute validation ICE in issue #105594 doesn't // recur. -// -//@ ignore-thumbv8m.base-none-eabi -#![feature(cmse_nonsecure_entry)] fn main() {} #[track_caller] //~ ERROR attribute should be applied to a function static _A: () = (); - -#[cmse_nonsecure_entry] //~ ERROR attribute should be applied to a function -static _B: () = (); //~| ERROR #[cmse_nonsecure_entry]` is only valid for targets diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr index c6b2d6e7813..1248967c47b 100644 --- a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr +++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr @@ -1,26 +1,11 @@ error[E0739]: attribute should be applied to a function definition - --> $DIR/issue-105594-invalid-attr-validation.rs:9:1 + --> $DIR/issue-105594-invalid-attr-validation.rs:6:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ LL | static _A: () = (); | ------------------- not a function definition -error: attribute should be applied to a function definition - --> $DIR/issue-105594-invalid-attr-validation.rs:12:1 - | -LL | #[cmse_nonsecure_entry] - | ^^^^^^^^^^^^^^^^^^^^^^^ -LL | static _B: () = (); - | ------------------- not a function definition - -error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension - --> $DIR/issue-105594-invalid-attr-validation.rs:12:1 - | -LL | #[cmse_nonsecure_entry] - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0739, E0775. -For more information about an error, try `rustc --explain E0739`. +For more information about this error, try `rustc --explain E0739`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs new file mode 100644 index 00000000000..37c8319d98d --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs @@ -0,0 +1,20 @@ +//@ build-pass +//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib +//@ needs-llvm-components: arm +#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items, intrinsics)] +#![no_core] +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +impl Copy for u32 {} + +#[no_mangle] +pub extern "C-cmse-nonsecure-entry" fn test( + f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32, + a: u32, + b: u32, + c: u32, +) -> u32 { + f(a, b, c, 42) +} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs index 02d5f20febc..6061451b2e9 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs @@ -1,10 +1,9 @@ // gate-test-cmse_nonsecure_entry #[no_mangle] -#[cmse_nonsecure_entry] -//~^ ERROR [E0775] -//~| ERROR [E0658] -pub extern "C" fn entry_function(input: u32) -> u32 { +pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + //~^ ERROR [E0570] + //~| ERROR [E0658] input + 6 } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr index beb9716d590..dabf16cab30 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr @@ -1,20 +1,20 @@ -error[E0658]: the `#[cmse_nonsecure_entry]` attribute is an experimental feature - --> $DIR/gate_test.rs:4:1 +error[E0658]: C-cmse-nonsecure-entry ABI is experimental and subject to change + --> $DIR/gate_test.rs:4:12 | -LL | #[cmse_nonsecure_entry] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #75835 <https://github.com/rust-lang/rust/issues/75835> for more information = help: add `#![feature(cmse_nonsecure_entry)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target --> $DIR/gate_test.rs:4:1 | -LL | #[cmse_nonsecure_entry] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors -Some errors have detailed explanations: E0658, E0775. -For more information about an error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0570, E0658. +For more information about an error, try `rustc --explain E0570`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs deleted file mode 100644 index a839406cd0a..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Regression test for the ICE described in #83475. - -#![crate_type="lib"] - -#![feature(cmse_nonsecure_entry)] -#[cmse_nonsecure_entry] -//~^ ERROR: attribute should be applied to a function definition -struct XEmpty2; -//~^ NOTE: not a function definition diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr deleted file mode 100644 index 26d3bfe7837..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: attribute should be applied to a function definition - --> $DIR/issue-83475.rs:6:1 - | -LL | #[cmse_nonsecure_entry] - | ^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct XEmpty2; - | --------------- not a function definition - -error: aborting due to 1 previous error - diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs index e197f94096d..de6888fae62 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs @@ -3,14 +3,14 @@ //@ needs-llvm-components: arm #![feature(cmse_nonsecure_entry, no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#![crate_type = "lib"] +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for u32 {} #[no_mangle] -#[cmse_nonsecure_entry] -pub extern "C" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { +pub extern "C-cmse-nonsecure-entry" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { d } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs index e2da3ebb6ae..4413c461c04 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs @@ -3,14 +3,19 @@ //@ needs-llvm-components: arm #![feature(cmse_nonsecure_entry, no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } -#[lang="copy"] -trait Copy { } +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} impl Copy for u32 {} #[no_mangle] -#[cmse_nonsecure_entry] -pub extern "C" fn entry_function(_: u32, _: u32, _: u32, _: u32, e: u32) -> u32 { +pub extern "C-cmse-nonsecure-entry" fn entry_function( + _: u32, + _: u32, + _: u32, + _: u32, + e: u32, +) -> u32 { e } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr new file mode 100644 index 00000000000..26409279fbe --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr @@ -0,0 +1,9 @@ +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/trustzone-only.rs:20:1 + | +LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs index 87eccb4fc6e..a4ea7a1757d 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs @@ -1,10 +1,25 @@ -//@ ignore-thumbv8m.main-none-eabi -#![feature(cmse_nonsecure_entry)] +//@ revisions: x86 aarch64 thumb7 +// +//@[x86] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86] needs-llvm-components: x86 +//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@[aarch64] needs-llvm-components: aarch64 +//@[thumb7] compile-flags: --target thumbv7em-none-eabi +//@[thumb7] needs-llvm-components: arm +#![feature(no_core, lang_items, rustc_attrs, cmse_nonsecure_entry)] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +impl Copy for u32 {} #[no_mangle] -#[cmse_nonsecure_entry] //~ ERROR [E0775] -pub extern "C" fn entry_function(input: u32) -> u32 { - input + 6 +pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + //~^ ERROR [E0570] + input } fn main() {} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr deleted file mode 100644 index 3e6954394f4..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension - --> $DIR/trustzone-only.rs:5:1 - | -LL | #[cmse_nonsecure_entry] - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0775`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr new file mode 100644 index 00000000000..26409279fbe --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr @@ -0,0 +1,9 @@ +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/trustzone-only.rs:20:1 + | +LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr new file mode 100644 index 00000000000..26409279fbe --- /dev/null +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr @@ -0,0 +1,9 @@ +error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target + --> $DIR/trustzone-only.rs:20:1 + | +LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs deleted file mode 100644 index db4f90e9923..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -//@ needs-llvm-components: arm -#![feature(cmse_nonsecure_entry, no_core, lang_items)] -#![no_core] -#[lang = "sized"] -trait Sized {} - -#[lang = "copy"] -trait Copy {} - -#[no_mangle] -#[cmse_nonsecure_entry] -//~^ ERROR `#[cmse_nonsecure_entry]` requires C ABI [E0776] -pub fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 { - d -} diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr deleted file mode 100644 index c3fae3d8bbb..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI - --> $DIR/wrong-abi.rs:12:1 - | -LL | #[cmse_nonsecure_entry] - | ^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0776`. diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.rs new file mode 100644 index 00000000000..33630205369 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.rs @@ -0,0 +1,14 @@ +macro_rules! y { + () => { + N + }; +} + +struct A<const N: usize>; + +fn foo<const N: usize>() -> A<{ y!() }> { + A::<1> + //~^ ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.stderr new file mode 100644 index 00000000000..4461477f3e9 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/trivial-const-arg-macro-braced-expansion.rs:10:5 + | +LL | fn foo<const N: usize>() -> A<{ y!() }> { + | ----------- expected `A<N>` because of return type +LL | A::<1> + | ^^^^^^ expected `N`, found `1` + | + = note: expected struct `A<N>` + found struct `A<1>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.rs new file mode 100644 index 00000000000..5a9e62561dc --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.rs @@ -0,0 +1,15 @@ +macro_rules! y { + () => { + N + //~^ ERROR: generic parameters may not be used in const operations + }; +} + +struct A<const N: usize>; + +#[rustfmt::skip] +fn foo<const N: usize>() -> A<{{ y!() }}> { + A::<1> +} + +fn main() {} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr new file mode 100644 index 00000000000..e40d05924b1 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr @@ -0,0 +1,15 @@ +error: generic parameters may not be used in const operations + --> $DIR/trivial-const-arg-macro-nested-braces-2.rs:3:9 + | +LL | N + | ^ cannot perform const operation using `N` +... +LL | fn foo<const N: usize>() -> A<{{ y!() }}> { + | ---- in this macro invocation + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.rs new file mode 100644 index 00000000000..45c0768dde4 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.rs @@ -0,0 +1,15 @@ +#[rustfmt::skip] +macro_rules! y { + () => { + { N } + //~^ ERROR: generic parameters may not be used in const operations + }; +} + +struct A<const N: usize>; + +fn foo<const N: usize>() -> A<{ y!() }> { + A::<1> +} + +fn main() {} diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr new file mode 100644 index 00000000000..b91d6c7a024 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr @@ -0,0 +1,15 @@ +error: generic parameters may not be used in const operations + --> $DIR/trivial-const-arg-macro-nested-braces.rs:4:11 + | +LL | { N } + | ^ cannot perform const operation using `N` +... +LL | fn foo<const N: usize>() -> A<{ y!() }> { + | ---- in this macro invocation + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/early/trivial-const-arg-nested-braces.rs b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.rs new file mode 100644 index 00000000000..941ba6bfea7 --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.rs @@ -0,0 +1,9 @@ +struct A<const N: usize>; + +#[rustfmt::skip] +fn foo<const N: usize>() -> A<{ { N } }> { + //~^ ERROR: generic parameters may not be used in const operations + A::<1> +} + +fn main() {} diff --git a/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr new file mode 100644 index 00000000000..d60516ba4bc --- /dev/null +++ b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/trivial-const-arg-nested-braces.rs:4:35 + | +LL | fn foo<const N: usize>() -> A<{ { N } }> { + | ^ cannot perform const operation using `N` + | + = help: const parameters may only be used as standalone arguments, i.e. `N` + = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/issue-112505-overflow.rs b/tests/ui/const-generics/issue-112505-overflow.rs deleted file mode 100644 index 0dd7776d595..00000000000 --- a/tests/ui/const-generics/issue-112505-overflow.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(transmute_generic_consts)] - -fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 239] { - unsafe { std::mem::transmute(v) } //~ ERROR cannot transmute between types of different sizes -} - -fn main() { } diff --git a/tests/ui/const-generics/issue-112505-overflow.stderr b/tests/ui/const-generics/issue-112505-overflow.stderr deleted file mode 100644 index 0bd3f6eddd4..00000000000 --- a/tests/ui/const-generics/issue-112505-overflow.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/issue-112505-overflow.rs:4:14 - | -LL | unsafe { std::mem::transmute(v) } - | ^^^^^^^^^^^^^^^^^^^ - | - = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) - = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs index 7faf670e468..95c71160567 100644 --- a/tests/ui/const-generics/transmute-fail.rs +++ b/tests/ui/const-generics/transmute-fail.rs @@ -1,3 +1,8 @@ +// ignore-tidy-linelength +//@ normalize-stderr-32bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big" +//@ normalize-stderr-64bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big" + + #![feature(transmute_generic_consts)] #![feature(generic_const_exprs)] #![allow(incomplete_features)] @@ -31,6 +36,11 @@ fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 7777 } } +fn overflow_more(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 239] { + unsafe { std::mem::transmute(v) } //~ ERROR cannot transmute between types of different sizes +} + + fn transpose<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { unsafe { std::mem::transmute(v) diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index 4a20034910d..638ce790345 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -1,11 +1,11 @@ error: the constant `W` is not of type `usize` - --> $DIR/transmute-fail.rs:12:42 + --> $DIR/transmute-fail.rs:17:42 | LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] { | ^^^^^^^^^^^^^ expected `usize`, found `bool` error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:7:9 + --> $DIR/transmute-fail.rs:12:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -14,13 +14,13 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; W + 1]; H]` (size can vary because of [u32; W + 1]) error: the constant `W` is not of type `usize` - --> $DIR/transmute-fail.rs:15:9 + --> $DIR/transmute-fail.rs:20:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:22:9 + --> $DIR/transmute-fail.rs:27:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -29,16 +29,25 @@ LL | std::mem::transmute(v) = note: target type: `[u32; W * H * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:29:9 + --> $DIR/transmute-fail.rs:34:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture) - = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture) + = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type $REALLY_TOO_BIG are too big for the target architecture) + = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type $REALLY_TOO_BIG are too big for the target architecture) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:36:9 + --> $DIR/transmute-fail.rs:40:14 + | +LL | unsafe { std::mem::transmute(v) } + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type $REALLY_TOO_BIG are too big for the target architecture) + = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type $REALLY_TOO_BIG are too big for the target architecture) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/transmute-fail.rs:46:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -47,7 +56,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:47:9 + --> $DIR/transmute-fail.rs:57:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -56,7 +65,7 @@ LL | std::mem::transmute(v) = note: target type: `[u32; W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:54:9 + --> $DIR/transmute-fail.rs:64:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -65,7 +74,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:63:9 + --> $DIR/transmute-fail.rs:73:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -74,7 +83,7 @@ LL | std::mem::transmute(v) = note: target type: `[u32; D * W * H]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:72:9 + --> $DIR/transmute-fail.rs:82:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -83,7 +92,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:79:9 + --> $DIR/transmute-fail.rs:89:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -92,7 +101,7 @@ LL | std::mem::transmute(v) = note: target type: `[u8; L * 2]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:86:9 + --> $DIR/transmute-fail.rs:96:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -101,7 +110,7 @@ LL | std::mem::transmute(v) = note: target type: `[u16; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:93:9 + --> $DIR/transmute-fail.rs:103:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -110,7 +119,7 @@ LL | std::mem::transmute(v) = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/transmute-fail.rs:102:9 + --> $DIR/transmute-fail.rs:112:9 | LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ @@ -118,6 +127,6 @@ LL | std::mem::transmute(v) = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H]) = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W]) -error: aborting due to 14 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs index dc68f6cf71f..a1922c98ef6 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs @@ -3,7 +3,7 @@ //@ compile-flags:-C debuginfo=2 //@ build-fail -//@ error-pattern: too big for the current architecture +//@ error-pattern: too big for the target architecture //@ normalize-stderr-64bit: "18446744073709551615" -> "SIZE" //@ normalize-stderr-32bit: "4294967295" -> "SIZE" diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr index 06aad9616cb..a3772e509ed 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr @@ -1,4 +1,4 @@ -error: values of the type `[u8; usize::MAX]` are too big for the current architecture +error: values of the type `[u8; usize::MAX]` are too big for the target architecture error: aborting due to 1 previous error diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs index 2b6e85362b6..3456cd55b75 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs @@ -5,7 +5,7 @@ //@ compile-flags:-C debuginfo=2 //@ build-fail -//@ error-pattern: too big for the current architecture +//@ error-pattern: too big for the target architecture //@ normalize-stderr-64bit: "18446744073709551615" -> "SIZE" //@ normalize-stderr-32bit: "4294967295" -> "SIZE" diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr index 06aad9616cb..a3772e509ed 100644 --- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr +++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr @@ -1,4 +1,4 @@ -error: values of the type `[u8; usize::MAX]` are too big for the current architecture +error: values of the type `[u8; usize::MAX]` are too big for the target architecture error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-static-size-overflow.rs b/tests/ui/extern/extern-static-size-overflow.rs index a96ce0cf47e..f33e482aa66 100644 --- a/tests/ui/extern/extern-static-size-overflow.rs +++ b/tests/ui/extern/extern-static-size-overflow.rs @@ -4,31 +4,13 @@ struct ReallyBig { } // The limit for "too big for the current architecture" is dependent on the target pointer size -// however it's artificially limited on 64 bits -// logic copied from rustc_target::abi::TargetDataLayout::obj_size_bound() +// but is artificially limited due to LLVM's internal architecture +// logic based on rustc_target::abi::TargetDataLayout::obj_size_bound() const fn max_size() -> usize { - #[cfg(target_pointer_width = "16")] - { - 1 << 15 - } - - #[cfg(target_pointer_width = "32")] - { - 1 << 31 - } - - #[cfg(target_pointer_width = "64")] - { - 1 << 47 - } - - #[cfg(not(any( - target_pointer_width = "16", - target_pointer_width = "32", - target_pointer_width = "64" - )))] - { - isize::MAX as usize + if usize::BITS < 61 { + 1 << (usize::BITS - 1) + } else { + 1 << 61 } } diff --git a/tests/ui/extern/extern-static-size-overflow.stderr b/tests/ui/extern/extern-static-size-overflow.stderr index 1c926399591..c6490e96a8e 100644 --- a/tests/ui/extern/extern-static-size-overflow.stderr +++ b/tests/ui/extern/extern-static-size-overflow.stderr @@ -1,17 +1,17 @@ -error: extern static is too large for the current architecture - --> $DIR/extern-static-size-overflow.rs:38:5 +error: extern static is too large for the target architecture + --> $DIR/extern-static-size-overflow.rs:20:5 | LL | static BAZ: [u8; max_size()]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: extern static is too large for the current architecture - --> $DIR/extern-static-size-overflow.rs:39:5 +error: extern static is too large for the target architecture + --> $DIR/extern-static-size-overflow.rs:21:5 | LL | static UWU: [usize; usize::MAX]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: extern static is too large for the current architecture - --> $DIR/extern-static-size-overflow.rs:40:5 +error: extern static is too large for the target architecture + --> $DIR/extern-static-size-overflow.rs:22:5 | LL | static A: ReallyBig; | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/layout/size-of-val-raw-too-big.rs b/tests/ui/layout/size-of-val-raw-too-big.rs index 8d82c78d953..dfca6d6eb76 100644 --- a/tests/ui/layout/size-of-val-raw-too-big.rs +++ b/tests/ui/layout/size-of-val-raw-too-big.rs @@ -1,7 +1,7 @@ //@ build-fail //@ compile-flags: --crate-type lib //@ only-32bit Layout computation rejects this layout for different reasons on 64-bit. -//@ error-pattern: too big for the current architecture +//@ error-pattern: too big for the target architecture #![feature(core_intrinsics)] #![allow(internal_features)] diff --git a/tests/ui/layout/size-of-val-raw-too-big.stderr b/tests/ui/layout/size-of-val-raw-too-big.stderr index aa9abd644fa..886bba9ec9d 100644 --- a/tests/ui/layout/size-of-val-raw-too-big.stderr +++ b/tests/ui/layout/size-of-val-raw-too-big.stderr @@ -1,4 +1,4 @@ -error: values of the type `Example` are too big for the current architecture +error: values of the type `Example` are too big for the target architecture error: aborting due to 1 previous error diff --git a/tests/ui/layout/too-big-with-padding.rs b/tests/ui/layout/too-big-with-padding.rs index 76703100145..8423ad2e1d6 100644 --- a/tests/ui/layout/too-big-with-padding.rs +++ b/tests/ui/layout/too-big-with-padding.rs @@ -10,7 +10,7 @@ #[repr(C, align(2))] pub struct Example([u8; 0x7fffffff]); -pub fn lib(_x: Example) {} //~ERROR: too big for the current architecture +pub fn lib(_x: Example) {} //~ERROR: too big for the target architecture #[lang = "sized"] pub trait Sized {} diff --git a/tests/ui/layout/too-big-with-padding.stderr b/tests/ui/layout/too-big-with-padding.stderr index 71309788dac..fc3b4db049a 100644 --- a/tests/ui/layout/too-big-with-padding.stderr +++ b/tests/ui/layout/too-big-with-padding.stderr @@ -1,4 +1,4 @@ -error: values of the type `Example` are too big for the current architecture +error: values of the type `Example` are too big for the target architecture --> $DIR/too-big-with-padding.rs:13:1 | LL | pub fn lib(_x: Example) {} diff --git a/tests/ui/limits/huge-array-simple-32.rs b/tests/ui/limits/huge-array-simple-32.rs index 6ff981cd160..db75cc57e9a 100644 --- a/tests/ui/limits/huge-array-simple-32.rs +++ b/tests/ui/limits/huge-array-simple-32.rs @@ -4,6 +4,6 @@ #![allow(arithmetic_overflow)] fn main() { - let _fat: [u8; (1<<31)+(1<<15)] = //~ ERROR too big for the current architecture + let _fat: [u8; (1<<31)+(1<<15)] = //~ ERROR too big for the target architecture [0; (1u32<<31) as usize +(1u32<<15) as usize]; } diff --git a/tests/ui/limits/huge-array-simple-32.stderr b/tests/ui/limits/huge-array-simple-32.stderr index 1b86b02297f..33979915feb 100644 --- a/tests/ui/limits/huge-array-simple-32.stderr +++ b/tests/ui/limits/huge-array-simple-32.stderr @@ -1,4 +1,4 @@ -error: values of the type `[u8; 2147516416]` are too big for the current architecture +error: values of the type `[u8; 2147516416]` are too big for the target architecture --> $DIR/huge-array-simple-32.rs:7:9 | LL | let _fat: [u8; (1<<31)+(1<<15)] = diff --git a/tests/ui/limits/huge-array-simple-64.rs b/tests/ui/limits/huge-array-simple-64.rs index 13b284503bf..d2838e0d41e 100644 --- a/tests/ui/limits/huge-array-simple-64.rs +++ b/tests/ui/limits/huge-array-simple-64.rs @@ -4,6 +4,6 @@ #![allow(arithmetic_overflow)] fn main() { - let _fat: [u8; (1<<61)+(1<<31)] = //~ ERROR too big for the current architecture + let _fat: [u8; (1<<61)+(1<<31)] = //~ ERROR too big for the target architecture [0; (1u64<<61) as usize +(1u64<<31) as usize]; } diff --git a/tests/ui/limits/huge-array-simple-64.stderr b/tests/ui/limits/huge-array-simple-64.stderr index 8d395c3c6a9..46df288d4f7 100644 --- a/tests/ui/limits/huge-array-simple-64.stderr +++ b/tests/ui/limits/huge-array-simple-64.stderr @@ -1,4 +1,4 @@ -error: values of the type `[u8; 2305843011361177600]` are too big for the current architecture +error: values of the type `[u8; 2305843011361177600]` are too big for the target architecture --> $DIR/huge-array-simple-64.rs:7:9 | LL | let _fat: [u8; (1<<61)+(1<<31)] = diff --git a/tests/ui/limits/huge-array.stderr b/tests/ui/limits/huge-array.stderr index 2ebaf17a138..ce0c0d650c2 100644 --- a/tests/ui/limits/huge-array.stderr +++ b/tests/ui/limits/huge-array.stderr @@ -1,4 +1,4 @@ -error: values of the type `[[u8; 1518599999]; 1518600000]` are too big for the current architecture +error: values of the type `[[u8; 1518599999]; 1518600000]` are too big for the target architecture --> $DIR/huge-array.rs:4:9 | LL | let s: [T; 1518600000] = [t; 1518600000]; diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs index cf6e637388c..5664d0ba516 100644 --- a/tests/ui/limits/huge-enum.rs +++ b/tests/ui/limits/huge-enum.rs @@ -6,9 +6,9 @@ type BIG = Option<[u32; (1<<29)-1]>; #[cfg(target_pointer_width = "64")] -type BIG = Option<[u32; (1<<45)-1]>; +type BIG = Option<[u32; (1<<59)-1]>; fn main() { let big: BIG = None; - //~^ ERROR are too big for the current architecture + //~^ ERROR are too big for the target architecture } diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.stderr index fcd40607af4..18168b3fa5c 100644 --- a/tests/ui/limits/huge-enum.stderr +++ b/tests/ui/limits/huge-enum.stderr @@ -1,4 +1,4 @@ -error: values of the type `Option<TYPE>` are too big for the current architecture +error: values of the type `Option<TYPE>` are too big for the target architecture --> $DIR/huge-enum.rs:12:9 | LL | let big: BIG = None; diff --git a/tests/ui/limits/issue-56762.rs b/tests/ui/limits/huge-static.rs index 17b3ad8b01e..4709b46e59d 100644 --- a/tests/ui/limits/issue-56762.rs +++ b/tests/ui/limits/huge-static.rs @@ -1,6 +1,9 @@ -//@ only-x86_64 +//@ only-64bit -const HUGE_SIZE: usize = !0usize / 8; +// This test validates we gracefully fail computing a const or static of absurdly large size. +// The oddly-specific number is because of LLVM measuring object sizes in bits. + +const HUGE_SIZE: usize = 1 << 61; pub struct TooBigArray { diff --git a/tests/ui/limits/issue-56762.stderr b/tests/ui/limits/huge-static.stderr index 3a6c3559ac1..684efeeb4a3 100644 --- a/tests/ui/limits/issue-56762.stderr +++ b/tests/ui/limits/huge-static.stderr @@ -1,14 +1,14 @@ error[E0080]: could not evaluate static initializer - --> $DIR/issue-56762.rs:16:1 + --> $DIR/huge-static.rs:19:1 | LL | static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843009213693951]` are too big for the current architecture + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843009213693952]` are too big for the target architecture error[E0080]: could not evaluate static initializer - --> $DIR/issue-56762.rs:19:1 + --> $DIR/huge-static.rs:22:1 | LL | static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843009213693951]` are too big for the current architecture + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843009213693952]` are too big for the target architecture error: aborting due to 2 previous errors diff --git a/tests/ui/limits/huge-struct.rs b/tests/ui/limits/huge-struct.rs index b9e90b3e9d1..f7ce4f26db1 100644 --- a/tests/ui/limits/huge-struct.rs +++ b/tests/ui/limits/huge-struct.rs @@ -1,7 +1,9 @@ +// ignore-tidy-linelength //@ build-fail //@ normalize-stderr-test: "S32" -> "SXX" //@ normalize-stderr-test: "S1M" -> "SXX" -//@ error-pattern: too big for the current +//@ normalize-stderr-32bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big" +//@ normalize-stderr-64bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big" struct S32<T> { v0: T, @@ -44,6 +46,6 @@ struct S1M<T> { val: S1k<S1k<T>> } fn main() { let fat: Option<S1M<S1M<S1M<u32>>>> = None; - //~^ ERROR are too big for the current architecture + //~^ ERROR are too big for the target architecture } diff --git a/tests/ui/limits/huge-struct.stderr b/tests/ui/limits/huge-struct.stderr index 782db20c7f3..b10455ffd2d 100644 --- a/tests/ui/limits/huge-struct.stderr +++ b/tests/ui/limits/huge-struct.stderr @@ -1,5 +1,5 @@ -error: values of the type `SXX<SXX<SXX<u32>>>` are too big for the current architecture - --> $DIR/huge-struct.rs:46:9 +error: values of the type $REALLY_TOO_BIG are too big for the target architecture + --> $DIR/huge-struct.rs:48:9 | LL | let fat: Option<SXX<SXX<SXX<u32>>>> = None; | ^^^ diff --git a/tests/ui/limits/issue-15919-32.stderr b/tests/ui/limits/issue-15919-32.stderr index abd65ff3c9e..f162838d37d 100644 --- a/tests/ui/limits/issue-15919-32.stderr +++ b/tests/ui/limits/issue-15919-32.stderr @@ -1,4 +1,4 @@ -error: values of the type `[usize; usize::MAX]` are too big for the current architecture +error: values of the type `[usize; usize::MAX]` are too big for the target architecture --> $DIR/issue-15919-32.rs:5:9 | LL | let x = [0usize; 0xffff_ffff]; diff --git a/tests/ui/limits/issue-15919-64.stderr b/tests/ui/limits/issue-15919-64.stderr index d1f0cc39c18..cd443f2065b 100644 --- a/tests/ui/limits/issue-15919-64.stderr +++ b/tests/ui/limits/issue-15919-64.stderr @@ -1,4 +1,4 @@ -error: values of the type `[usize; usize::MAX]` are too big for the current architecture +error: values of the type `[usize; usize::MAX]` are too big for the target architecture --> $DIR/issue-15919-64.rs:5:9 | LL | let x = [0usize; 0xffff_ffff_ffff_ffff]; diff --git a/tests/ui/limits/issue-17913.rs b/tests/ui/limits/issue-17913.rs index 325923f32f3..24fd3b542e6 100644 --- a/tests/ui/limits/issue-17913.rs +++ b/tests/ui/limits/issue-17913.rs @@ -1,6 +1,6 @@ //@ build-fail //@ normalize-stderr-test: "\[&usize; \d+\]" -> "[&usize; usize::MAX]" -//@ error-pattern: too big for the current architecture +//@ error-pattern: too big for the target architecture #[cfg(target_pointer_width = "64")] fn main() { diff --git a/tests/ui/limits/issue-17913.stderr b/tests/ui/limits/issue-17913.stderr index 893730cbbd2..e9c3c14e181 100644 --- a/tests/ui/limits/issue-17913.stderr +++ b/tests/ui/limits/issue-17913.stderr @@ -1,4 +1,4 @@ -error: values of the type `[&usize; usize::MAX]` are too big for the current architecture +error: values of the type `[&usize; usize::MAX]` are too big for the target architecture --> $SRC_DIR/alloc/src/boxed.rs:LL:COL error: aborting due to 1 previous error diff --git a/tests/ui/limits/issue-55878.rs b/tests/ui/limits/issue-55878.rs index 4d91a173240..81696e226fd 100644 --- a/tests/ui/limits/issue-55878.rs +++ b/tests/ui/limits/issue-55878.rs @@ -2,7 +2,7 @@ //@ normalize-stderr-64bit: "18446744073709551615" -> "SIZE" //@ normalize-stderr-32bit: "4294967295" -> "SIZE" -//@ error-pattern: are too big for the current architecture +//@ error-pattern: are too big for the target architecture fn main() { println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>()); } diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr index 97ca0f4fb59..0a5f17be804 100644 --- a/tests/ui/limits/issue-55878.stderr +++ b/tests/ui/limits/issue-55878.stderr @@ -1,7 +1,7 @@ error[E0080]: evaluation of constant value failed --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | - = note: values of the type `[u8; usize::MAX]` are too big for the current architecture + = note: values of the type `[u8; usize::MAX]` are too big for the target architecture | note: inside `std::mem::size_of::<[u8; usize::MAX]>` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL diff --git a/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs b/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs index 9c150c119d0..6133183a55c 100644 --- a/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs +++ b/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs @@ -3,7 +3,7 @@ //@ compile-flags: -Zmir-opt-level=0 fn main() { - Bug::V([0; !0]); //~ ERROR are too big for the current + Bug::V([0; !0]); //~ ERROR are too big for the target } enum Bug { diff --git a/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr b/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr index 7b9b8f76d0c..7fa0ab95981 100644 --- a/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr +++ b/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr @@ -1,4 +1,4 @@ -error: values of the type `[u8; usize::MAX]` are too big for the current architecture +error: values of the type `[u8; usize::MAX]` are too big for the target architecture --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:5 | LL | Bug::V([0; !0]); diff --git a/tests/ui/limits/issue-75158-64.stderr b/tests/ui/limits/issue-75158-64.stderr index 06aad9616cb..a3772e509ed 100644 --- a/tests/ui/limits/issue-75158-64.stderr +++ b/tests/ui/limits/issue-75158-64.stderr @@ -1,4 +1,4 @@ -error: values of the type `[u8; usize::MAX]` are too big for the current architecture +error: values of the type `[u8; usize::MAX]` are too big for the target architecture error: aborting due to 1 previous error diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs deleted file mode 100644 index f8aad88ecee..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -//@ check-pass -#![crate_name = "NonSnakeCase"] - -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs deleted file mode 100644 index c077d81e9e5..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -//@ compile-flags: --crate-name NonSnakeCase -//@ check-pass - -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs deleted file mode 100644 index 278f7cfd3ee..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -//@ check-pass -#![crate_type = "bin"] -#![crate_name = "NonSnakeCase"] - -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs deleted file mode 100644 index 781c6794fc2..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -#![crate_type = "cdylib"] -#![crate_name = "NonSnakeCase"] -//~^ ERROR crate `NonSnakeCase` should have a snake case name -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs deleted file mode 100644 index 3f65295f068..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -#![crate_type = "dylib"] -#![crate_name = "NonSnakeCase"] -//~^ ERROR crate `NonSnakeCase` should have a snake case name -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs deleted file mode 100644 index 20c58e66aa6..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -#![crate_type = "lib"] -#![crate_name = "NonSnakeCase"] -//~^ ERROR crate `NonSnakeCase` should have a snake case name -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs deleted file mode 100644 index f0f2fa4393e..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -#![crate_type = "proc-macro"] -#![crate_name = "NonSnakeCase"] -//~^ ERROR crate `NonSnakeCase` should have a snake case name -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr deleted file mode 100644 index e0091057bc9..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate-proc-macro.rs:3:18 - | -LL | #![crate_name = "NonSnakeCase"] - | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` - | -note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate-proc-macro.rs:5:9 - | -LL | #![deny(non_snake_case)] - | ^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs deleted file mode 100644 index 1a558def3d0..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -#![crate_type = "rlib"] -#![crate_name = "NonSnakeCase"] -//~^ ERROR crate `NonSnakeCase` should have a snake case name -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs deleted file mode 100644 index 2ec53c15eb8..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ only-x86_64-unknown-linux-gnu -#![crate_type = "staticlib"] -#![crate_name = "NonSnakeCase"] -//~^ ERROR crate `NonSnakeCase` should have a snake case name -#![deny(non_snake_case)] - -fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr deleted file mode 100644 index 4ee6d5bd4d4..00000000000 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate-staticlib.rs:3:18 - | -LL | #![crate_name = "NonSnakeCase"] - | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` - | -note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate-staticlib.rs:5:9 - | -LL | #![deny(non_snake_case)] - | ^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr index a68c0e832b8..9bccb270627 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate-lib.rs:3:18 + --> $DIR/lint-non-snake-case-crate.rs:25:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate-lib.rs:5:9 + --> $DIR/lint-non-snake-case-crate.rs:27:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr index 6e9d54bd5bc..9bccb270627 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate-rlib.rs:3:18 + --> $DIR/lint-non-snake-case-crate.rs:25:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate-rlib.rs:5:9 + --> $DIR/lint-non-snake-case-crate.rs:27:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr index 4ee1a9cb3dd..9bccb270627 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate-dylib.rs:3:18 + --> $DIR/lint-non-snake-case-crate.rs:25:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate-dylib.rs:5:9 + --> $DIR/lint-non-snake-case-crate.rs:27:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr index f9167aa8df3..9bccb270627 100644 --- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.stderr +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr @@ -1,11 +1,11 @@ error: crate `NonSnakeCase` should have a snake case name - --> $DIR/lint-non-snake-case-crate-cdylib.rs:3:18 + --> $DIR/lint-non-snake-case-crate.rs:25:18 | LL | #![crate_name = "NonSnakeCase"] | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` | note: the lint level is defined here - --> $DIR/lint-non-snake-case-crate-cdylib.rs:5:9 + --> $DIR/lint-non-snake-case-crate.rs:27:9 | LL | #![deny(non_snake_case)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr new file mode 100644 index 00000000000..9bccb270627 --- /dev/null +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr @@ -0,0 +1,14 @@ +error: crate `NonSnakeCase` should have a snake case name + --> $DIR/lint-non-snake-case-crate.rs:25:18 + | +LL | #![crate_name = "NonSnakeCase"] + | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-crate.rs:27:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs new file mode 100644 index 00000000000..57604d99a07 --- /dev/null +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs @@ -0,0 +1,29 @@ +//! Don't lint on binary crate with non-snake-case names. +//! +//! See <https://github.com/rust-lang/rust/issues/45127>. + +//@ revisions: bin_ cdylib_ dylib_ lib_ proc_macro_ rlib_ staticlib_ + +// Should not fire on binary crates. +//@[bin_] compile-flags: --crate-type=bin +//@[bin_] check-pass + +// But should fire on non-binary crates. + +//@[cdylib_] ignore-musl (dylibs are not supported) +//@[dylib_] ignore-musl (dylibs are not supported) +//@[dylib_] ignore-wasm (dylib is not supported) +//@[proc_macro_] ignore-wasm (dylib is not supported) + +//@[cdylib_] compile-flags: --crate-type=cdylib +//@[dylib_] compile-flags: --crate-type=dylib +//@[lib_] compile-flags: --crate-type=lib +//@[proc_macro_] compile-flags: --crate-type=proc-macro +//@[rlib_] compile-flags: --crate-type=rlib +//@[staticlib_] compile-flags: --crate-type=staticlib + +#![crate_name = "NonSnakeCase"] +//[cdylib_,dylib_,lib_,proc_macro_,rlib_,staticlib_]~^ ERROR crate `NonSnakeCase` should have a snake case name +#![deny(non_snake_case)] + +fn main() {} diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr new file mode 100644 index 00000000000..9bccb270627 --- /dev/null +++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr @@ -0,0 +1,14 @@ +error: crate `NonSnakeCase` should have a snake case name + --> $DIR/lint-non-snake-case-crate.rs:25:18 + | +LL | #![crate_name = "NonSnakeCase"] + | ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case` + | +note: the lint level is defined here + --> $DIR/lint-non-snake-case-crate.rs:27:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs b/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs new file mode 100644 index 00000000000..dc929e14527 --- /dev/null +++ b/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs @@ -0,0 +1,14 @@ +//@ check-pass +#![feature(rust_cold_cc)] + +// extern "rust-cold" is a "Rust" ABI so we accept `repr(Rust)` types as arg/ret without warnings. + +pub extern "rust-cold" fn f(_: ()) -> Result<(), ()> { + Ok(()) +} + +extern "rust-cold" { + pub fn g(_: ()) -> Result<(), ()>; +} + +fn main() {} diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs new file mode 100644 index 00000000000..ff28548b795 --- /dev/null +++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs @@ -0,0 +1,6 @@ +//@ error-pattern: circular modules +// Regression test for #97589: a doc-comment on a circular module bypassed cycle detection + +#![crate_type = "lib"] + +pub mod recursive; diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.stderr b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.stderr new file mode 100644 index 00000000000..02d6406775a --- /dev/null +++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.stderr @@ -0,0 +1,8 @@ +error: circular modules: $DIR/recursive.rs -> $DIR/recursive.rs + --> $DIR/recursive.rs:6:1 + | +LL | mod recursive; + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs new file mode 100644 index 00000000000..3d758be8c05 --- /dev/null +++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs @@ -0,0 +1,6 @@ +//@ ignore-test: this is an auxiliary file for circular-module-with-doc-comment-issue-97589.rs + +//! this comment caused the circular dependency checker to break + +#[path = "recursive.rs"] +mod recursive; diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout index da67a57f420..4415b3c858e 100644 --- a/tests/ui/print-calling-conventions.stdout +++ b/tests/ui/print-calling-conventions.stdout @@ -1,5 +1,6 @@ C C-cmse-nonsecure-call +C-cmse-nonsecure-entry C-unwind Rust aapcs diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs index 348bf839b69..ea3cbabf302 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs @@ -39,7 +39,6 @@ impl const Foo for NonConstAdd { #[const_trait] trait Baz { type Qux: Add; - //~^ ERROR the trait bound } impl const Baz for NonConstAdd { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index 405212b52c7..c20b53c210f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr @@ -12,17 +12,5 @@ error: using `#![feature(effects)]` without enabling next trait solver globally = note: the next trait solver must be enabled globally for the effects feature to work correctly = help: use `-Znext-solver` to enable -error[E0277]: the trait bound `Add::{synthetic#0}: Compat` is not satisfied - --> $DIR/assoc-type.rs:41:15 - | -LL | type Qux: Add; - | ^^^ the trait `Compat` is not implemented for `Add::{synthetic#0}` - | -help: consider further restricting the associated type - | -LL | trait Baz where Add::{synthetic#0}: Compat { - | ++++++++++++++++++++++++++++++++ - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs index 06ee421fc32..71e5a0c728d 100644 --- a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs +++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs @@ -1,8 +1,8 @@ pub fn foo(num: i32) -> i32 { let foo: i32::from_be(num); //~^ ERROR expected type, found local variable `num` - //~| ERROR parenthesized type parameters may only be used with a `Fn` trait - //~| ERROR ambiguous associated type + //~| ERROR argument types not allowed with return type notation + //~| ERROR return type notation not allowed in this position yet foo } diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr index b90ae051fb7..83a5441e3c0 100644 --- a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr +++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr @@ -6,29 +6,22 @@ LL | let foo: i32::from_be(num); | | | help: use `=` if you meant to assign -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/let-binding-init-expr-as-ty.rs:2:19 +error: argument types not allowed with return type notation + --> $DIR/let-binding-init-expr-as-ty.rs:2:26 | LL | let foo: i32::from_be(num); - | ^^^^^^^^^^^^ only `Fn` traits may use parentheses + | ^^^^^ help: remove the input types: `()` | -help: use angle brackets instead - | -LL | let foo: i32::from_be<num>; - | ~ ~ + = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information + = help: add `#![feature(return_type_notation)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0223]: ambiguous associated type +error: return type notation not allowed in this position yet --> $DIR/let-binding-init-expr-as-ty.rs:2:14 | LL | let foo: i32::from_be(num); | ^^^^^^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path - | -LL | let foo: <i32 as Example>::from_be; - | ~~~~~~~~~~~~~~~~~~~~~~~~~ error: aborting due to 3 previous errors -Some errors have detailed explanations: E0214, E0223, E0573. -For more information about an error, try `rustc --explain E0214`. +For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/transmutability/arrays/huge-len.stderr b/tests/ui/transmutability/arrays/huge-len.stderr index 1fa16c649d4..2f8a86df0a7 100644 --- a/tests/ui/transmutability/arrays/huge-len.stderr +++ b/tests/ui/transmutability/arrays/huge-len.stderr @@ -2,7 +2,7 @@ error[E0277]: `()` cannot be safely transmuted into `ExplicitlyPadded` --> $DIR/huge-len.rs:21:41 | LL | assert::is_maybe_transmutable::<(), ExplicitlyPadded>(); - | ^^^^^^^^^^^^^^^^ values of the type `ExplicitlyPadded` are too big for the current architecture + | ^^^^^^^^^^^^^^^^ values of the type `ExplicitlyPadded` are too big for the target architecture | note: required by a bound in `is_maybe_transmutable` --> $DIR/huge-len.rs:8:14 @@ -17,7 +17,7 @@ error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()` --> $DIR/huge-len.rs:24:55 | LL | assert::is_maybe_transmutable::<ExplicitlyPadded, ()>(); - | ^^ values of the type `ExplicitlyPadded` are too big for the current architecture + | ^^ values of the type `ExplicitlyPadded` are too big for the target architecture | note: required by a bound in `is_maybe_transmutable` --> $DIR/huge-len.rs:8:14 |
