diff --git a/.mailmap b/.mailmap index 2a53cbf9effc4..90533e81b39ff 100644 --- a/.mailmap +++ b/.mailmap @@ -690,6 +690,7 @@ Xinye Tao Xuefeng Wu Xuefeng Wu Xuefeng Wu XuefengWu York Xiang +Yotam Ofek Youngsoo Son Youngsuk Kim Yuki Okushi diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 5eb1931152d31..85a4f1c6765ca 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -256,6 +256,9 @@ pub enum AttributeKind { /// Represents `#[link_name]`. LinkName { name: Symbol, span: Span }, + /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute) + LinkSection { name: Symbol, span: Span }, + /// Represents `#[loop_match]`. LoopMatch(Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 0d6ee77c718d3..3c55f62cc80b9 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -24,6 +24,7 @@ impl AttributeKind { DocComment { .. } => Yes, ExportName { .. } => Yes, Inline(..) => No, + LinkSection { .. } => No, MacroTransparency(..) => Yes, Repr(..) => No, Stability { .. } => Yes, diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 39652335f5553..9ad46a83f5084 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -99,6 +99,8 @@ attr_parsing_non_ident_feature = attr_parsing_null_on_export = `export_name` may not contain null characters +attr_parsing_null_on_link_section = `link_section` may not contain null characters + attr_parsing_repr_ident = meta item in `repr` must be an identifier diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 740222178ed58..e298053ab7691 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,11 +1,12 @@ use rustc_attr_data_structures::AttributeKind; -use rustc_attr_data_structures::AttributeKind::LinkName; +use rustc_attr_data_structures::AttributeKind::{LinkName, LinkSection}; use rustc_feature::{AttributeTemplate, template}; use rustc_span::{Symbol, sym}; use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; use crate::context::{AcceptContext, Stage}; use crate::parser::ArgParser; +use crate::session_diagnostics::NullOnLinkSection; pub(crate) struct LinkNameParser; @@ -28,3 +29,31 @@ impl SingleAttributeParser for LinkNameParser { Some(LinkName { name, span: cx.attr_span }) } } + +pub(crate) struct LinkSectionParser; + +impl SingleAttributeParser for LinkSectionParser { + const PATH: &[Symbol] = &[sym::link_section]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value(cx.attr_span, None); + return None; + }; + let Some(name) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + if name.as_str().contains('\0') { + // `#[link_section = ...]` will be converted to a null-terminated string, + // so it may not contain any null characters. + cx.emit_err(NullOnLinkSection { span: cx.attr_span }); + return None; + } + + Some(LinkSection { name, span: cx.attr_span }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 1ac41b9c7e8b5..eee6d860550eb 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -22,7 +22,7 @@ use crate::attributes::codegen_attrs::{ use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; -use crate::attributes::link_attrs::LinkNameParser; +use crate::attributes::link_attrs::{LinkNameParser, LinkSectionParser}; use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser}; use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; use crate::attributes::must_use::MustUseParser; @@ -123,6 +123,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 7cfce5799792a..53aafaa714fa0 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -452,6 +452,13 @@ pub(crate) struct NullOnExport { pub span: Span, } +#[derive(Diagnostic)] +#[diag(attr_parsing_null_on_link_section, code = E0648)] +pub(crate) struct NullOnLinkSection { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(attr_parsing_stability_outside_std, code = E0734)] pub(crate) struct StabilityOutsideStd { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 7680f8e107439..a87c26f43f902 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -124,6 +124,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align), AttributeKind::LinkName { name, .. } => codegen_fn_attrs.link_name = Some(*name), + AttributeKind::LinkSection { name, .. } => { + codegen_fn_attrs.link_section = Some(*name) + } AttributeKind::NoMangle(attr_span) => { if tcx.opt_item_name(did.to_def_id()).is_some() { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; @@ -253,16 +256,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } } - sym::link_section => { - if let Some(val) = attr.value_str() { - if val.as_str().bytes().any(|b| b == 0) { - let msg = format!("illegal null byte in link_section value: `{val}`"); - tcx.dcx().span_err(attr.span(), msg); - } else { - codegen_fn_attrs.link_section = Some(val); - } - } - } sym::link_ordinal => { link_ordinal_span = Some(attr.span()); if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 66c4af4c935b5..10b44a1faf087 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -354,15 +354,15 @@ fn optimize_use_clone<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let destination_block = target.unwrap(); - bb.statements.push(mir::Statement { - source_info: bb.terminator().source_info, - kind: mir::StatementKind::Assign(Box::new(( + bb.statements.push(mir::Statement::new( + bb.terminator().source_info, + mir::StatementKind::Assign(Box::new(( *destination, mir::Rvalue::Use(mir::Operand::Copy( arg_place.project_deeper(&[mir::ProjectionElem::Deref], tcx), )), ))), - }); + )); bb.terminator_mut().kind = mir::TerminatorKind::Goto { target: destination_block }; } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index d0a48872f759c..df1ee0e79c243 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3055,7 +3055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn note_unmet_impls_on_type( &self, err: &mut Diag<'_>, - errors: Vec>, + errors: &[FulfillmentError<'tcx>], suggest_derive: bool, ) { let preds: Vec<_> = errors diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index b9d245069866a..87a7cd62ae5eb 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -322,7 +322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_expr.span, format!("cannot use `{}` on type `{}`", s, lhs_ty_str), ); - self.note_unmet_impls_on_type(&mut err, errors, false); + self.note_unmet_impls_on_type(&mut err, &errors, false); (err, None) } Op::BinOp(bin_op) => { @@ -382,7 +382,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(rhs_expr.span, rhs_ty_str); } let suggest_derive = self.can_eq(self.param_env, lhs_ty, rhs_ty); - self.note_unmet_impls_on_type(&mut err, errors, suggest_derive); + self.note_unmet_impls_on_type(&mut err, &errors, suggest_derive); (err, output_def_id) } }; @@ -582,22 +582,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // concatenation (e.g., "Hello " + "World!"). This means // we don't want the note in the else clause to be emitted } else if lhs_ty.has_non_region_param() { - // Look for a TraitPredicate in the Fulfillment errors, - // and use it to generate a suggestion. - // - // Note that lookup_op_method must be called again but - // with a specific rhs_ty instead of a placeholder so - // the resulting predicate generates a more specific - // suggestion for the user. - let errors = self - .lookup_op_method( - (lhs_expr, lhs_ty), - Some((rhs_expr, rhs_ty)), - lang_item_for_binop(self.tcx, op), - op.span(), - expected, - ) - .unwrap_err(); if !errors.is_empty() { for error in errors { if let Some(trait_pred) = @@ -946,7 +930,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Str | ty::Never | ty::Char | ty::Tuple(_) | ty::Array(_, _) => {} ty::Ref(_, lty, _) if *lty.kind() == ty::Str => {} _ => { - self.note_unmet_impls_on_type(&mut err, errors, true); + self.note_unmet_impls_on_type(&mut err, &errors, true); } } } diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index cae674165f0ef..ddc0b11680627 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -110,17 +110,16 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match r.kind() { - ty::ReBound(..) => { - // leave bound regions alone - r - } + // Leave bound regions alone, since they affect selection via the leak check. + ty::ReBound(..) => r, + // Leave error regions alone, since they affect selection b/c of incompleteness. + ty::ReError(_) => r, ty::ReEarlyParam(..) | ty::ReLateParam(_) | ty::ReVar(_) | ty::RePlaceholder(..) | ty::ReStatic - | ty::ReError(_) | ty::ReErased => self.cx().lifetimes.re_erased, } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index adc100941a39a..9f39908c3b2f8 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1359,7 +1359,15 @@ pub struct BasicBlockData<'tcx> { impl<'tcx> BasicBlockData<'tcx> { pub fn new(terminator: Option>, is_cleanup: bool) -> BasicBlockData<'tcx> { - BasicBlockData { statements: vec![], terminator, is_cleanup } + BasicBlockData::new_stmts(Vec::new(), terminator, is_cleanup) + } + + pub fn new_stmts( + statements: Vec>, + terminator: Option>, + is_cleanup: bool, + ) -> BasicBlockData<'tcx> { + BasicBlockData { statements, terminator, is_cleanup } } /// Accessor for terminator. diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index d98b40f0fcf13..d16477adb7767 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -16,12 +16,16 @@ pub struct Statement<'tcx> { pub kind: StatementKind<'tcx>, } -impl Statement<'_> { +impl<'tcx> Statement<'tcx> { /// Changes a statement to a nop. This is both faster than deleting instructions and avoids /// invalidating statement indices in `Location`s. pub fn make_nop(&mut self) { self.kind = StatementKind::Nop } + + pub fn new(source_info: SourceInfo, kind: StatementKind<'tcx>) -> Self { + Statement { source_info, kind } + } } impl<'tcx> StatementKind<'tcx> { diff --git a/compiler/rustc_mir_build/src/builder/cfg.rs b/compiler/rustc_mir_build/src/builder/cfg.rs index 082cdc2e2a49e..2faccc43247c5 100644 --- a/compiler/rustc_mir_build/src/builder/cfg.rs +++ b/compiler/rustc_mir_build/src/builder/cfg.rs @@ -42,7 +42,7 @@ impl<'tcx> CFG<'tcx> { ) { self.push( block, - Statement { source_info, kind: StatementKind::Assign(Box::new((place, rvalue))) }, + Statement::new(source_info, StatementKind::Assign(Box::new((place, rvalue)))), ); } @@ -88,7 +88,7 @@ impl<'tcx> CFG<'tcx> { place: Place<'tcx>, ) { let kind = StatementKind::FakeRead(Box::new((cause, place))); - let stmt = Statement { source_info, kind }; + let stmt = Statement::new(source_info, kind); self.push(block, stmt); } @@ -99,7 +99,7 @@ impl<'tcx> CFG<'tcx> { place: Place<'tcx>, ) { let kind = StatementKind::PlaceMention(Box::new(place)); - let stmt = Statement { source_info, kind }; + let stmt = Statement::new(source_info, kind); self.push(block, stmt); } @@ -110,7 +110,7 @@ impl<'tcx> CFG<'tcx> { /// syntax (e.g. `continue` or `if !`) that would otherwise not appear in MIR. pub(crate) fn push_coverage_span_marker(&mut self, block: BasicBlock, source_info: SourceInfo) { let kind = StatementKind::Coverage(coverage::CoverageKind::SpanMarker); - let stmt = Statement { source_info, kind }; + let stmt = Statement::new(source_info, kind); self.push(block, stmt); } diff --git a/compiler/rustc_mir_build/src/builder/coverageinfo.rs b/compiler/rustc_mir_build/src/builder/coverageinfo.rs index a80bd4f3c8009..aa43b273cff5c 100644 --- a/compiler/rustc_mir_build/src/builder/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/builder/coverageinfo.rs @@ -61,10 +61,10 @@ impl BlockMarkerGen { block: BasicBlock, ) -> BlockMarkerId { let id = self.next_block_marker_id(); - let marker_statement = mir::Statement { + let marker_statement = mir::Statement::new( source_info, - kind: mir::StatementKind::Coverage(CoverageKind::BlockMarker { id }), - }; + mir::StatementKind::Coverage(CoverageKind::BlockMarker { id }), + ); cfg.push(block, marker_statement); id diff --git a/compiler/rustc_mir_build/src/builder/custom/parse.rs b/compiler/rustc_mir_build/src/builder/custom/parse.rs index 91e284604b68c..10154461c3395 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse.rs @@ -315,10 +315,8 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { let stmt = self.statement_as_expr(*stmt_id)?; let span = self.thir[stmt].span; let statement = self.parse_statement(stmt)?; - data.statements.push(Statement { - source_info: SourceInfo { span, scope: self.source_scope }, - kind: statement, - }); + data.statements + .push(Statement::new(SourceInfo { span, scope: self.source_scope }, statement)); } let Some(trailing) = block.expr else { return Err(self.expr_error(expr_id, "terminator")) }; diff --git a/compiler/rustc_mir_build/src/builder/expr/as_place.rs b/compiler/rustc_mir_build/src/builder/expr/as_place.rs index 99148504a8761..7c851ec465bdc 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_place.rs @@ -489,16 +489,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let place = place_builder.to_place(this); this.cfg.push( block, - Statement { - source_info: ty_source_info, - kind: StatementKind::AscribeUserType( + Statement::new( + ty_source_info, + StatementKind::AscribeUserType( Box::new(( place, UserTypeProjection { base: annotation_index, projs: vec![] }, )), Variance::Invariant, ), - }, + ), ); } block.and(place_builder) @@ -518,16 +518,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); this.cfg.push( block, - Statement { - source_info: ty_source_info, - kind: StatementKind::AscribeUserType( + Statement::new( + ty_source_info, + StatementKind::AscribeUserType( Box::new(( Place::from(temp), UserTypeProjection { base: annotation_index, projs: vec![] }, )), Variance::Invariant, ), - }, + ), ); } block.and(PlaceBuilder::from(temp)) diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index 9e07dd5da7e26..975226bb642a7 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -175,10 +175,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // and therefore is not considered during coroutine auto-trait // determination. See the comment about `box` at `yield_in_scope`. let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span)); - this.cfg.push( - block, - Statement { source_info, kind: StatementKind::StorageLive(result) }, - ); + this.cfg + .push(block, Statement::new(source_info, StatementKind::StorageLive(result))); if let Some(scope) = scope.temp_lifetime { // schedule a shallow free of that memory, lest we unwind: this.schedule_drop_storage_and_value(expr_span, scope, result); @@ -278,12 +276,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; this.cfg.push( block, - Statement { + Statement::new( source_info, - kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::Assume(Operand::Move(assert_place)), - )), - }, + StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume( + Operand::Move(assert_place), + ))), + ), ); } @@ -789,7 +787,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(upvar_span); let temp = this.local_decls.push(LocalDecl::new(upvar_ty, upvar_span)); - this.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) }); + this.cfg.push(block, Statement::new(source_info, StatementKind::StorageLive(temp))); let arg_place_builder = unpack!(block = this.as_place_builder(block, arg)); diff --git a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs index 0bd61168fba05..b0ce3527d8b3d 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_temp.rs @@ -102,8 +102,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Block { expr: None, targeted_by_break: false, .. } = this.thir[block] && expr_ty.is_never() => {} _ => { - this.cfg - .push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) }); + this.cfg.push(block, Statement::new(source_info, StatementKind::StorageLive(temp))); // In constants, `temp_lifetime` is `None` for temporaries that // live for the `'static` lifetime. Thus we do not drop these diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 270a7d4b15431..9600067a85fe3 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -646,9 +646,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let base = self.canonical_user_type_annotations.push(annotation.clone()); self.cfg.push( block, - Statement { - source_info: ty_source_info, - kind: StatementKind::AscribeUserType( + Statement::new( + ty_source_info, + StatementKind::AscribeUserType( Box::new((place, UserTypeProjection { base, projs: Vec::new() })), // We always use invariant as the variance here. This is because the // variance field from the ascription refers to the variance to use @@ -666,7 +666,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // ``. ty::Invariant, ), - }, + ), ); self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); @@ -828,7 +828,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> Place<'tcx> { let local_id = self.var_local_id(var, for_guard); let source_info = self.source_info(span); - self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) }); + self.cfg.push(block, Statement::new(source_info, StatementKind::StorageLive(local_id))); // Although there is almost always scope for given variable in corner cases // like #92893 we might get variable with no scope. if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id) @@ -2578,16 +2578,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let base = self.canonical_user_type_annotations.push(ascription.annotation); self.cfg.push( block, - Statement { + Statement::new( source_info, - kind: StatementKind::AscribeUserType( + StatementKind::AscribeUserType( Box::new(( ascription.source, UserTypeProjection { base, projs: Vec::new() }, )), ascription.variance, ), - }, + ), ); } } diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 1d15e7e126f70..405d47c7c79cb 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -431,13 +431,13 @@ impl DropTree { cfg.terminate(block, drop_node.data.source_info, terminator); } DropKind::ForLint => { - let stmt = Statement { - source_info: drop_node.data.source_info, - kind: StatementKind::BackwardIncompatibleDropHint { + let stmt = Statement::new( + drop_node.data.source_info, + StatementKind::BackwardIncompatibleDropHint { place: Box::new(drop_node.data.local.into()), reason: BackwardIncompatibleDropReason::Edition2024, }, - }; + ); cfg.push(block, stmt); let target = blocks[drop_node.next].unwrap(); if target != block { @@ -454,10 +454,10 @@ impl DropTree { // Root nodes don't correspond to a drop. DropKind::Storage if drop_idx == ROOT_NODE => {} DropKind::Storage => { - let stmt = Statement { - source_info: drop_node.data.source_info, - kind: StatementKind::StorageDead(drop_node.data.local), - }; + let stmt = Statement::new( + drop_node.data.source_info, + StatementKind::StorageDead(drop_node.data.local), + ); cfg.push(block, stmt); let target = blocks[drop_node.next].unwrap(); if target != block { @@ -1124,13 +1124,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { DropKind::ForLint => { self.cfg.push( block, - Statement { + Statement::new( source_info, - kind: StatementKind::BackwardIncompatibleDropHint { + StatementKind::BackwardIncompatibleDropHint { place: Box::new(local.into()), reason: BackwardIncompatibleDropReason::Edition2024, }, - }, + ), ); } DropKind::Storage => { @@ -1138,7 +1138,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { assert!(local.index() > self.arg_count); self.cfg.push( block, - Statement { source_info, kind: StatementKind::StorageDead(local) }, + Statement::new(source_info, StatementKind::StorageDead(local)), ); } } @@ -1880,13 +1880,13 @@ where cfg.push( block, - Statement { + Statement::new( source_info, - kind: StatementKind::BackwardIncompatibleDropHint { + StatementKind::BackwardIncompatibleDropHint { place: Box::new(local.into()), reason: BackwardIncompatibleDropReason::Edition2024, }, - }, + ), ); } DropKind::Storage => { @@ -1910,7 +1910,7 @@ where } // Only temps and vars need their storage dead. assert!(local.index() > arg_count); - cfg.push(block, Statement { source_info, kind: StatementKind::StorageDead(local) }); + cfg.push(block, Statement::new(source_info, StatementKind::StorageDead(local))); } } } diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 8602bb5576523..23e28a11a452b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -17,13 +17,13 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { let mut blocks = IndexVec::new(); let mut block = |n, kind| { - let nop = mir::Statement { source_info, kind: mir::StatementKind::Nop }; + let nop = mir::Statement::new(source_info, mir::StatementKind::Nop); - blocks.push(mir::BasicBlockData { - statements: std::iter::repeat(&nop).cloned().take(n).collect(), - terminator: Some(mir::Terminator { source_info, kind }), - is_cleanup: false, - }) + blocks.push(mir::BasicBlockData::new_stmts( + std::iter::repeat(&nop).cloned().take(n).collect(), + Some(mir::Terminator { source_info, kind }), + false, + )) }; let dummy_place = mir::Place { local: mir::RETURN_PLACE, projection: ty::List::empty() }; diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index bacff287859d0..26839ebf61e46 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -44,11 +44,10 @@ impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { let cur_len = body.basic_blocks.len(); let mut new_block = |source_info: SourceInfo, is_cleanup: bool, target: BasicBlock| { - let block = BasicBlockData { - statements: vec![], + let block = BasicBlockData::new( + Some(Terminator { source_info, kind: TerminatorKind::Goto { target } }), is_cleanup, - terminator: Some(Terminator { source_info, kind: TerminatorKind::Goto { target } }), - }; + ); let idx = cur_len + new_blocks.len(); new_blocks.push(block); BasicBlock::new(idx) diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index a414d120e68b5..7ae2ebaf4ff09 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -93,11 +93,11 @@ fn add_move_for_packed_drop<'tcx>( let ty = place.ty(body, tcx).ty; let temp = patch.new_temp(ty, source_info.span); - let storage_dead_block = patch.new_block(BasicBlockData { - statements: vec![Statement { source_info, kind: StatementKind::StorageDead(temp) }], - terminator: Some(Terminator { source_info, kind: TerminatorKind::Goto { target } }), + let storage_dead_block = patch.new_block(BasicBlockData::new_stmts( + vec![Statement::new(source_info, StatementKind::StorageDead(temp))], + Some(Terminator { source_info, kind: TerminatorKind::Goto { target } }), is_cleanup, - }); + )); patch.add_statement(loc, StatementKind::StorageLive(temp)); patch.add_assign(loc, Place::from(temp), Rvalue::Use(Operand::Move(*place))); diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index e5a28d1b66c8c..3c29d4624b73c 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -81,9 +81,11 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { // Emit their retags. basic_blocks[START_BLOCK].statements.splice( 0..0, - places.map(|(place, source_info)| Statement { - source_info, - kind: StatementKind::Retag(RetagKind::FnEntry, Box::new(place)), + places.map(|(place, source_info)| { + Statement::new( + source_info, + StatementKind::Retag(RetagKind::FnEntry, Box::new(place)), + ) }), ); } @@ -113,10 +115,10 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { for (source_info, dest_place, dest_block) in returns { basic_blocks[dest_block].statements.insert( 0, - Statement { + Statement::new( source_info, - kind: StatementKind::Retag(RetagKind::Default, Box::new(dest_place)), - }, + StatementKind::Retag(RetagKind::Default, Box::new(dest_place)), + ), ); } @@ -174,10 +176,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { let source_info = block_data.statements[i].source_info; block_data.statements.insert( i + 1, - Statement { - source_info, - kind: StatementKind::Retag(retag_kind, Box::new(place)), - }, + Statement::new(source_info, StatementKind::Retag(retag_kind, Box::new(place))), ); } } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 8f88613b79f35..989787504b7b8 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -51,22 +51,18 @@ fn insert_alignment_check<'tcx>( let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit); let rvalue = Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer), const_raw_ptr); let thin_ptr = local_decls.push(LocalDecl::with_source_info(const_raw_ptr, source_info)).into(); - stmts - .push(Statement { source_info, kind: StatementKind::Assign(Box::new((thin_ptr, rvalue))) }); + stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((thin_ptr, rvalue))))); // Transmute the pointer to a usize (equivalent to `ptr.addr()`). let rvalue = Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr), tcx.types.usize); let addr = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - stmts.push(Statement { source_info, kind: StatementKind::Assign(Box::new((addr, rvalue))) }); + stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((addr, rvalue))))); // Get the alignment of the pointee let alignment = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); let rvalue = Rvalue::NullaryOp(NullOp::AlignOf, pointee_ty); - stmts.push(Statement { - source_info, - kind: StatementKind::Assign(Box::new((alignment, rvalue))), - }); + stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((alignment, rvalue))))); // Subtract 1 from the alignment to get the alignment mask let alignment_mask = @@ -76,13 +72,13 @@ fn insert_alignment_check<'tcx>( user_ty: None, const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)), tcx.types.usize), })); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( alignment_mask, Rvalue::BinaryOp(BinOp::Sub, Box::new((Operand::Copy(alignment), one))), ))), - }); + )); // If this target does not have reliable alignment, further limit the mask by anding it with // the mask for the highest reliable alignment. @@ -99,31 +95,31 @@ fn insert_alignment_check<'tcx>( tcx.types.usize, ), })); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( alignment_mask, Rvalue::BinaryOp( BinOp::BitAnd, Box::new((Operand::Copy(alignment_mask), max_mask)), ), ))), - }); + )); } // BitAnd the alignment mask with the pointer let alignment_bits = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( alignment_bits, Rvalue::BinaryOp( BinOp::BitAnd, Box::new((Operand::Copy(addr), Operand::Copy(alignment_mask))), ), ))), - }); + )); // Check if the alignment bits are all zero let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into(); @@ -132,13 +128,13 @@ fn insert_alignment_check<'tcx>( user_ty: None, const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), tcx.types.usize), })); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( is_ok, Rvalue::BinaryOp(BinOp::Eq, Box::new((Operand::Copy(alignment_bits), zero.clone()))), ))), - }); + )); // Emit a check that asserts on the alignment and otherwise triggers a // AssertKind::MisalignedPointerDereference. diff --git a/compiler/rustc_mir_transform/src/check_null.rs b/compiler/rustc_mir_transform/src/check_null.rs index ad74e335bd9eb..e365d36580ad5 100644 --- a/compiler/rustc_mir_transform/src/check_null.rs +++ b/compiler/rustc_mir_transform/src/check_null.rs @@ -41,13 +41,12 @@ fn insert_null_check<'tcx>( let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit); let rvalue = Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer), const_raw_ptr); let thin_ptr = local_decls.push(LocalDecl::with_source_info(const_raw_ptr, source_info)).into(); - stmts - .push(Statement { source_info, kind: StatementKind::Assign(Box::new((thin_ptr, rvalue))) }); + stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((thin_ptr, rvalue))))); // Transmute the pointer to a usize (equivalent to `ptr.addr()`). let rvalue = Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr), tcx.types.usize); let addr = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - stmts.push(Statement { source_info, kind: StatementKind::Assign(Box::new((addr, rvalue))) }); + stmts.push(Statement::new(source_info, StatementKind::Assign(Box::new((addr, rvalue))))); let zero = Operand::Constant(Box::new(ConstOperand { span: source_info.span, @@ -71,24 +70,24 @@ fn insert_null_check<'tcx>( let rvalue = Rvalue::NullaryOp(NullOp::SizeOf, pointee_ty); let sizeof_pointee = local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new((sizeof_pointee, rvalue))), - }); + StatementKind::Assign(Box::new((sizeof_pointee, rvalue))), + )); // Check that the pointee is not a ZST. let is_pointee_not_zst = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into(); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( is_pointee_not_zst, Rvalue::BinaryOp( BinOp::Ne, Box::new((Operand::Copy(sizeof_pointee), zero.clone())), ), ))), - }); + )); // Pointer needs to be checked only if pointee is not a ZST. Operand::Copy(is_pointee_not_zst) @@ -97,38 +96,38 @@ fn insert_null_check<'tcx>( // Check whether the pointer is null. let is_null = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into(); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( is_null, Rvalue::BinaryOp(BinOp::Eq, Box::new((Operand::Copy(addr), zero))), ))), - }); + )); // We want to throw an exception if the pointer is null and the pointee is not unconditionally // allowed (which for all non-borrow place uses, is when the pointee is ZST). let should_throw_exception = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into(); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( should_throw_exception, Rvalue::BinaryOp( BinOp::BitAnd, Box::new((Operand::Copy(is_null), pointee_should_be_checked)), ), ))), - }); + )); // The final condition whether this pointer usage is ok or not. let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into(); - stmts.push(Statement { + stmts.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( is_ok, Rvalue::UnaryOp(UnOp::Not, Operand::Copy(should_throw_exception)), ))), - }); + )); // Emit a PointerCheck that asserts on the condition and otherwise triggers // a AssertKind::NullPointerDereference. diff --git a/compiler/rustc_mir_transform/src/check_pointers.rs b/compiler/rustc_mir_transform/src/check_pointers.rs index bf94f1aad24b3..4f913c1fca026 100644 --- a/compiler/rustc_mir_transform/src/check_pointers.rs +++ b/compiler/rustc_mir_transform/src/check_pointers.rs @@ -235,11 +235,11 @@ fn split_block( let block_data = &mut basic_blocks[location.block]; // Drain every statement after this one and move the current terminator to a new basic block. - let new_block = BasicBlockData { - statements: block_data.statements.split_off(location.statement_index), - terminator: block_data.terminator.take(), - is_cleanup: block_data.is_cleanup, - }; + let new_block = BasicBlockData::new_stmts( + block_data.statements.split_off(location.statement_index), + block_data.terminator.take(), + block_data.is_cleanup, + ); basic_blocks.push(new_block) } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 06c6b46a9c2aa..761d5461a996f 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -252,16 +252,16 @@ impl<'tcx> TransformVisitor<'tcx> { } }; - let statements = vec![Statement { - kind: StatementKind::Assign(Box::new((Place::return_place(), none_value))), + let statements = vec![Statement::new( source_info, - }]; + StatementKind::Assign(Box::new((Place::return_place(), none_value))), + )]; - body.basic_blocks_mut().push(BasicBlockData { + body.basic_blocks_mut().push(BasicBlockData::new_stmts( statements, - terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), - is_cleanup: false, - }); + Some(Terminator { source_info, kind: TerminatorKind::Return }), + false, + )); block } @@ -342,10 +342,10 @@ impl<'tcx> TransformVisitor<'tcx> { } }; - statements.push(Statement { - kind: StatementKind::Assign(Box::new((Place::return_place(), rvalue))), + statements.push(Statement::new( source_info, - }); + StatementKind::Assign(Box::new((Place::return_place(), rvalue))), + )); } // Create a Place referencing a coroutine struct field @@ -361,13 +361,13 @@ impl<'tcx> TransformVisitor<'tcx> { // Create a statement which changes the discriminant fn set_discr(&self, state_disc: VariantIdx, source_info: SourceInfo) -> Statement<'tcx> { let self_place = Place::from(SELF_ARG); - Statement { + Statement::new( source_info, - kind: StatementKind::SetDiscriminant { + StatementKind::SetDiscriminant { place: Box::new(self_place), variant_index: state_disc, }, - } + ) } // Create a statement which reads the discriminant into a temporary @@ -377,10 +377,10 @@ impl<'tcx> TransformVisitor<'tcx> { let temp = Place::from(local_decls_len); let self_place = Place::from(SELF_ARG); - let assign = Statement { - source_info: SourceInfo::outermost(body.span), - kind: StatementKind::Assign(Box::new((temp, Rvalue::Discriminant(self_place)))), - }; + let assign = Statement::new( + SourceInfo::outermost(body.span), + StatementKind::Assign(Box::new((temp, Rvalue::Discriminant(self_place)))), + ); (assign, temp) } } @@ -450,7 +450,7 @@ impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { && !self.always_live_locals.contains(l); if needs_storage_dead { data.statements - .push(Statement { source_info, kind: StatementKind::StorageDead(l) }); + .push(Statement::new(source_info, StatementKind::StorageDead(l))); } } @@ -596,10 +596,8 @@ fn eliminate_get_context_call<'tcx>(bb_data: &mut BasicBlockData<'tcx>) -> Local let local = arg.node.place().unwrap().local; let arg = Rvalue::Use(arg.node); - let assign = Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new((destination, arg))), - }; + let assign = + Statement::new(terminator.source_info, StatementKind::Assign(Box::new((destination, arg)))); bb_data.statements.push(assign); bb_data.terminator = Some(Terminator { source_info: terminator.source_info, @@ -1075,11 +1073,11 @@ fn insert_switch<'tcx>( let source_info = SourceInfo::outermost(body.span); body.basic_blocks_mut().raw.insert( 0, - BasicBlockData { - statements: vec![assign], - terminator: Some(Terminator { source_info, kind: switch }), - is_cleanup: false, - }, + BasicBlockData::new_stmts( + vec![assign], + Some(Terminator { source_info, kind: switch }), + false, + ), ); for b in body.basic_blocks_mut().iter_mut() { @@ -1089,11 +1087,7 @@ fn insert_switch<'tcx>( fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { let source_info = SourceInfo::outermost(body.span); - body.basic_blocks_mut().push(BasicBlockData { - statements: Vec::new(), - terminator: Some(Terminator { source_info, kind }), - is_cleanup: false, - }) + body.basic_blocks_mut().push(BasicBlockData::new(Some(Terminator { source_info, kind }), false)) } fn return_poll_ready_assign<'tcx>(tcx: TyCtxt<'tcx>, source_info: SourceInfo) -> Statement<'tcx> { @@ -1109,19 +1103,16 @@ fn return_poll_ready_assign<'tcx>(tcx: TyCtxt<'tcx>, source_info: SourceInfo) -> Box::new(AggregateKind::Adt(poll_def_id, VariantIdx::from_usize(0), args, None, None)), IndexVec::from_raw(vec![val]), ); - Statement { - kind: StatementKind::Assign(Box::new((Place::return_place(), ready_val))), - source_info, - } + Statement::new(source_info, StatementKind::Assign(Box::new((Place::return_place(), ready_val)))) } fn insert_poll_ready_block<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> BasicBlock { let source_info = SourceInfo::outermost(body.span); - body.basic_blocks_mut().push(BasicBlockData { - statements: [return_poll_ready_assign(tcx, source_info)].to_vec(), - terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), - is_cleanup: false, - }) + body.basic_blocks_mut().push(BasicBlockData::new_stmts( + [return_poll_ready_assign(tcx, source_info)].to_vec(), + Some(Terminator { source_info, kind: TerminatorKind::Return }), + false, + )) } fn insert_panic_block<'tcx>( @@ -1205,13 +1196,11 @@ fn generate_poison_block_and_redirect_unwinds_there<'tcx>( body: &mut Body<'tcx>, ) { let source_info = SourceInfo::outermost(body.span); - let poison_block = body.basic_blocks_mut().push(BasicBlockData { - statements: vec![ - transform.set_discr(VariantIdx::new(CoroutineArgs::POISONED), source_info), - ], - terminator: Some(Terminator { source_info, kind: TerminatorKind::UnwindResume }), - is_cleanup: true, - }); + let poison_block = body.basic_blocks_mut().push(BasicBlockData::new_stmts( + vec![transform.set_discr(VariantIdx::new(CoroutineArgs::POISONED), source_info)], + Some(Terminator { source_info, kind: TerminatorKind::UnwindResume }), + true, + )); for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() { let source_info = block.terminator().source_info; @@ -1345,32 +1334,28 @@ fn create_cases<'tcx>( && !transform.remap.contains(l) && !transform.always_live_locals.contains(l); if needs_storage_live { - statements - .push(Statement { source_info, kind: StatementKind::StorageLive(l) }); + statements.push(Statement::new(source_info, StatementKind::StorageLive(l))); } } if operation == Operation::Resume { // Move the resume argument to the destination place of the `Yield` terminator let resume_arg = CTX_ARG; - statements.push(Statement { + statements.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( point.resume_arg, Rvalue::Use(Operand::Move(resume_arg.into())), ))), - }); + )); } // Then jump to the real target - let block = body.basic_blocks_mut().push(BasicBlockData { + let block = body.basic_blocks_mut().push(BasicBlockData::new_stmts( statements, - terminator: Some(Terminator { - source_info, - kind: TerminatorKind::Goto { target }, - }), - is_cleanup: false, - }); + Some(Terminator { source_info, kind: TerminatorKind::Goto { target } }), + false, + )); (point.state, block) }) @@ -1540,13 +1525,13 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { let stmts = &mut body.basic_blocks_mut()[START_BLOCK].statements; stmts.insert( 0, - Statement { + Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( old_resume_local.into(), Rvalue::Use(Operand::Move(resume_local.into())), ))), - }, + ), ); let always_live_locals = always_storage_live_locals(body); diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index dc68629ec0d07..406575c4f43f4 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -87,12 +87,11 @@ fn build_pin_fut<'tcx>( const_: Const::zero_sized(pin_fut_new_unchecked_fn), })); - let storage_live = - Statement { source_info, kind: StatementKind::StorageLive(fut_pin_place.local) }; + let storage_live = Statement::new(source_info, StatementKind::StorageLive(fut_pin_place.local)); - let fut_ref_assign = Statement { + let fut_ref_assign = Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( fut_ref_place, Rvalue::Ref( tcx.lifetimes.re_erased, @@ -100,12 +99,12 @@ fn build_pin_fut<'tcx>( fut_place, ), ))), - }; + ); // call Pin::new_unchecked(&mut fut) - let pin_fut_bb = body.basic_blocks_mut().push(BasicBlockData { - statements: [storage_live, fut_ref_assign].to_vec(), - terminator: Some(Terminator { + let pin_fut_bb = body.basic_blocks_mut().push(BasicBlockData::new_stmts( + [storage_live, fut_ref_assign].to_vec(), + Some(Terminator { source_info, kind: TerminatorKind::Call { func: pin_fut_new_unchecked_fn, @@ -117,8 +116,8 @@ fn build_pin_fut<'tcx>( fn_span: span, }, }), - is_cleanup: false, - }); + false, + )); (pin_fut_bb, fut_pin_place) } @@ -156,19 +155,15 @@ fn build_poll_switch<'tcx>( let source_info = SourceInfo::outermost(body.span); let poll_discr_place = Place::from(body.local_decls.push(LocalDecl::new(poll_discr_ty, source_info.span))); - let discr_assign = Statement { + let discr_assign = Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( - poll_discr_place, - Rvalue::Discriminant(*poll_unit_place), - ))), - }; - let storage_dead = - Statement { source_info, kind: StatementKind::StorageDead(fut_pin_place.local) }; + StatementKind::Assign(Box::new((poll_discr_place, Rvalue::Discriminant(*poll_unit_place)))), + ); + let storage_dead = Statement::new(source_info, StatementKind::StorageDead(fut_pin_place.local)); let unreachable_block = insert_term_block(body, TerminatorKind::Unreachable); - body.basic_blocks_mut().push(BasicBlockData { - statements: [storage_dead, discr_assign].to_vec(), - terminator: Some(Terminator { + body.basic_blocks_mut().push(BasicBlockData::new_stmts( + [storage_dead, discr_assign].to_vec(), + Some(Terminator { source_info, kind: TerminatorKind::SwitchInt { discr: Operand::Move(poll_discr_place), @@ -179,8 +174,8 @@ fn build_poll_switch<'tcx>( ), }, }), - is_cleanup: false, - }) + false, + )) } // Gather blocks, reachable through 'drop' targets of Yield and Drop terminators (chained) @@ -330,10 +325,10 @@ pub(super) fn expand_async_drops<'tcx>( let context_ref_place = Place::from(body.local_decls.push(LocalDecl::new(context_mut_ref, source_info.span))); let arg = Rvalue::Use(Operand::Move(Place::from(CTX_ARG))); - body[bb].statements.push(Statement { + body[bb].statements.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new((context_ref_place, arg))), - }); + StatementKind::Assign(Box::new((context_ref_place, arg))), + )); let yield_block = insert_term_block(body, TerminatorKind::Unreachable); // `kind` replaced later to yield let (pin_bb, fut_pin_place) = build_pin_fut(tcx, body, fut_place.clone(), UnwindAction::Continue); @@ -551,11 +546,8 @@ pub(super) fn insert_clean_drop<'tcx>( }; // Create a block to destroy an unresumed coroutines. This can only destroy upvars. - body.basic_blocks_mut().push(BasicBlockData { - statements: Vec::new(), - terminator: Some(Terminator { source_info, kind: term }), - is_cleanup: false, - }) + body.basic_blocks_mut() + .push(BasicBlockData::new(Some(Terminator { source_info, kind: term }), false)) } pub(super) fn create_coroutine_drop_shim<'tcx>( @@ -734,11 +726,7 @@ pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>( body.local_decls[RETURN_PLACE] = LocalDecl::with_source_info(poll_enum, source_info); // call coroutine_drop() - let call_bb = body.basic_blocks_mut().push(BasicBlockData { - statements: Vec::new(), - terminator: None, - is_cleanup: false, - }); + let call_bb = body.basic_blocks_mut().push(BasicBlockData::new(None, false)); // return Poll::Ready() let ret_bb = insert_poll_ready_block(tcx, &mut body); diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 702c62eddc7fb..f253d1662cac8 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -259,7 +259,7 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb debug!(" injecting statement {counter_kind:?} for {bb:?}"); let data = &mut mir_body[bb]; let source_info = data.terminator().source_info; - let statement = Statement { source_info, kind: StatementKind::Coverage(counter_kind) }; + let statement = Statement::new(source_info, StatementKind::Coverage(counter_kind)); data.statements.insert(0, statement); } diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 3c0053c610d14..b0fc5e90f07bd 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -68,14 +68,13 @@ impl<'tcx> MockBlocks<'tcx> { BytePos(1) }; let next_hi = next_lo + BytePos(1); - self.blocks.push(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + self.blocks.push(BasicBlockData::new( + Some(Terminator { source_info: SourceInfo::outermost(Span::with_root_ctxt(next_lo, next_hi)), kind, }), - is_cleanup: false, - }) + false, + )) } fn link(&mut self, from_block: BasicBlock, to_block: BasicBlock) { diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index d0b313e149aca..fb17cca30f4a5 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -55,8 +55,8 @@ fn has_back_edge( } fn insert_counter(basic_block_data: &mut BasicBlockData<'_>) { - basic_block_data.statements.push(Statement { - source_info: basic_block_data.terminator().source_info, - kind: StatementKind::ConstEvalCounter, - }); + basic_block_data.statements.push(Statement::new( + basic_block_data.terminator().source_info, + StatementKind::ConstEvalCounter, + )); } diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index c9bc52c6c7ebf..de96b1f255a6e 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -222,15 +222,14 @@ where let span = self.source_info.span; let pin_obj_bb = bb.unwrap_or_else(|| { - self.elaborator.patch().new_block(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + self.elaborator.patch().new_block(BasicBlockData::new( + Some(Terminator { // Temporary terminator, will be replaced by patch source_info: self.source_info, kind: TerminatorKind::Return, }), - is_cleanup: false, - }) + false, + )) }); let (fut_ty, drop_fn_def_id, trait_args) = if call_destructor_only { @@ -366,10 +365,8 @@ where call_statements.push(self.assign(obj_ptr_place, addr)); obj_ptr_place }; - call_statements.push(Statement { - source_info: self.source_info, - kind: StatementKind::StorageLive(fut.local), - }); + call_statements + .push(Statement::new(self.source_info, StatementKind::StorageLive(fut.local))); let call_drop_bb = self.new_block_with_statements( unwind, @@ -732,17 +729,17 @@ where let do_drop_bb = self.drop_subpath(interior, interior_path, succ, unwind, dropline); - let setup_bbd = BasicBlockData { - statements: vec![self.assign( + let setup_bbd = BasicBlockData::new_stmts( + vec![self.assign( Place::from(ptr_local), Rvalue::Cast(CastKind::Transmute, Operand::Copy(nonnull_place), ptr_ty), )], - terminator: Some(Terminator { + Some(Terminator { kind: TerminatorKind::Goto { target: do_drop_bb }, source_info: self.source_info, }), - is_cleanup: unwind.is_cleanup(), - }; + unwind.is_cleanup(), + ); self.elaborator.patch().new_block(setup_bbd) } @@ -753,14 +750,13 @@ where args: GenericArgsRef<'tcx>, ) -> BasicBlock { if adt.variants().is_empty() { - return self.elaborator.patch().new_block(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + return self.elaborator.patch().new_block(BasicBlockData::new( + Some(Terminator { source_info: self.source_info, kind: TerminatorKind::Unreachable, }), - is_cleanup: self.unwind.is_cleanup(), - }); + self.unwind.is_cleanup(), + )); } let skip_contents = adt.is_union() || adt.is_manually_drop(); @@ -927,9 +923,9 @@ where let discr_ty = adt.repr().discr_type().to_ty(self.tcx()); let discr = Place::from(self.new_temp(discr_ty)); let discr_rv = Rvalue::Discriminant(self.place); - let switch_block = BasicBlockData { - statements: vec![self.assign(discr, discr_rv)], - terminator: Some(Terminator { + let switch_block = BasicBlockData::new_stmts( + vec![self.assign(discr, discr_rv)], + Some(Terminator { source_info: self.source_info, kind: TerminatorKind::SwitchInt { discr: Operand::Move(discr), @@ -939,8 +935,8 @@ where ), }, }), - is_cleanup: unwind.is_cleanup(), - }; + unwind.is_cleanup(), + ); let switch_block = self.elaborator.patch().new_block(switch_block); self.drop_flag_test_block(switch_block, succ, unwind) } @@ -956,8 +952,8 @@ where let ref_place = self.new_temp(ref_ty); let unit_temp = Place::from(self.new_temp(tcx.types.unit)); - let result = BasicBlockData { - statements: vec![self.assign( + let result = BasicBlockData::new_stmts( + vec![self.assign( Place::from(ref_place), Rvalue::Ref( tcx.lifetimes.re_erased, @@ -965,7 +961,7 @@ where self.place, ), )], - terminator: Some(Terminator { + Some(Terminator { kind: TerminatorKind::Call { func: Operand::function_handle( tcx, @@ -983,8 +979,8 @@ where }, source_info: self.source_info, }), - is_cleanup: unwind.is_cleanup(), - }; + unwind.is_cleanup(), + ); let destructor_block = self.elaborator.patch().new_block(result); @@ -1047,8 +1043,8 @@ where let can_go = Place::from(self.new_temp(tcx.types.bool)); let one = self.constant_usize(1); - let drop_block = BasicBlockData { - statements: vec![ + let drop_block = BasicBlockData::new_stmts( + vec![ self.assign( ptr, Rvalue::RawPtr(RawPtrKind::Mut, tcx.mk_place_index(self.place, cur)), @@ -1058,26 +1054,26 @@ where Rvalue::BinaryOp(BinOp::Add, Box::new((move_(cur.into()), one))), ), ], - is_cleanup: unwind.is_cleanup(), - terminator: Some(Terminator { + Some(Terminator { source_info: self.source_info, // this gets overwritten by drop elaboration. kind: TerminatorKind::Unreachable, }), - }; + unwind.is_cleanup(), + ); let drop_block = self.elaborator.patch().new_block(drop_block); - let loop_block = BasicBlockData { - statements: vec![self.assign( + let loop_block = BasicBlockData::new_stmts( + vec![self.assign( can_go, Rvalue::BinaryOp(BinOp::Eq, Box::new((copy(Place::from(cur)), copy(len.into())))), )], - is_cleanup: unwind.is_cleanup(), - terminator: Some(Terminator { + Some(Terminator { source_info: self.source_info, kind: TerminatorKind::if_(move_(can_go), succ, drop_block), }), - }; + unwind.is_cleanup(), + ); let loop_block = self.elaborator.patch().new_block(loop_block); let place = tcx.mk_place_deref(ptr); @@ -1187,8 +1183,8 @@ where let slice_ptr_ty = Ty::new_mut_ptr(tcx, slice_ty); let slice_ptr = self.new_temp(slice_ptr_ty); - let mut delegate_block = BasicBlockData { - statements: vec![ + let mut delegate_block = BasicBlockData::new_stmts( + vec![ self.assign(Place::from(array_ptr), Rvalue::RawPtr(RawPtrKind::Mut, self.place)), self.assign( Place::from(slice_ptr), @@ -1202,9 +1198,9 @@ where ), ), ], - is_cleanup: self.unwind.is_cleanup(), - terminator: None, - }; + None, + self.unwind.is_cleanup(), + ); let array_place = mem::replace( &mut self.place, @@ -1246,8 +1242,8 @@ where }; let zero = self.constant_usize(0); - let block = BasicBlockData { - statements: vec![ + let block = BasicBlockData::new_stmts( + vec![ self.assign( len.into(), Rvalue::UnaryOp( @@ -1257,12 +1253,12 @@ where ), self.assign(cur.into(), Rvalue::Use(zero)), ], - is_cleanup: unwind.is_cleanup(), - terminator: Some(Terminator { + Some(Terminator { source_info: self.source_info, kind: TerminatorKind::Goto { target: loop_block }, }), - }; + unwind.is_cleanup(), + ); let drop_block = self.elaborator.patch().new_block(block); // FIXME(#34708): handle partially-dropped array/slice elements. @@ -1308,14 +1304,13 @@ where self.source_info.span, "open drop for unsafe binder shouldn't be encountered", ); - self.elaborator.patch().new_block(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + self.elaborator.patch().new_block(BasicBlockData::new( + Some(Terminator { source_info: self.source_info, kind: TerminatorKind::Unreachable, }), - is_cleanup: self.unwind.is_cleanup(), - }) + self.unwind.is_cleanup(), + )) } _ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty), @@ -1434,11 +1429,10 @@ where } fn new_block(&mut self, unwind: Unwind, k: TerminatorKind<'tcx>) -> BasicBlock { - self.elaborator.patch().new_block(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { source_info: self.source_info, kind: k }), - is_cleanup: unwind.is_cleanup(), - }) + self.elaborator.patch().new_block(BasicBlockData::new( + Some(Terminator { source_info: self.source_info, kind: k }), + unwind.is_cleanup(), + )) } fn new_block_with_statements( @@ -1447,11 +1441,11 @@ where statements: Vec>, k: TerminatorKind<'tcx>, ) -> BasicBlock { - self.elaborator.patch().new_block(BasicBlockData { + self.elaborator.patch().new_block(BasicBlockData::new_stmts( statements, - terminator: Some(Terminator { source_info: self.source_info, kind: k }), - is_cleanup: unwind.is_cleanup(), - }) + Some(Terminator { source_info: self.source_info, kind: k }), + unwind.is_cleanup(), + )) } fn new_temp(&mut self, ty: Ty<'tcx>) -> Local { @@ -1467,9 +1461,6 @@ where } fn assign(&self, lhs: Place<'tcx>, rhs: Rvalue<'tcx>) -> Statement<'tcx> { - Statement { - source_info: self.source_info, - kind: StatementKind::Assign(Box::new((lhs, rhs))), - } + Statement::new(self.source_info, StatementKind::Assign(Box::new((lhs, rhs)))) } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index c27087fea11f7..7852bb7ae2f4e 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -900,10 +900,10 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( ); let dest_ty = dest.ty(caller_body, tcx); let temp = Place::from(new_call_temp(caller_body, callsite, dest_ty, return_block)); - caller_body[callsite.block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::Assign(Box::new((temp, dest))), - }); + caller_body[callsite.block].statements.push(Statement::new( + callsite.source_info, + StatementKind::Assign(Box::new((temp, dest))), + )); tcx.mk_place_deref(temp) } else { destination @@ -947,10 +947,9 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( for local in callee_body.vars_and_temps_iter() { if integrator.always_live_locals.contains(local) { let new_local = integrator.map_local(local); - caller_body[callsite.block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::StorageLive(new_local), - }); + caller_body[callsite.block] + .statements + .push(Statement::new(callsite.source_info, StatementKind::StorageLive(new_local))); } } if let Some(block) = return_block { @@ -958,22 +957,22 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( // the slice once. let mut n = 0; if remap_destination { - caller_body[block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::Assign(Box::new(( + caller_body[block].statements.push(Statement::new( + callsite.source_info, + StatementKind::Assign(Box::new(( dest, Rvalue::Use(Operand::Move(destination_local.into())), ))), - }); + )); n += 1; } for local in callee_body.vars_and_temps_iter().rev() { if integrator.always_live_locals.contains(local) { let new_local = integrator.map_local(local); - caller_body[block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::StorageDead(new_local), - }); + caller_body[block].statements.push(Statement::new( + callsite.source_info, + StatementKind::StorageDead(new_local), + )); n += 1; } } @@ -1126,10 +1125,10 @@ fn create_temp_if_necessary<'tcx, I: Inliner<'tcx>>( trace!("creating temp for argument {:?}", arg); let arg_ty = arg.ty(caller_body, inliner.tcx()); let local = new_call_temp(caller_body, callsite, arg_ty, return_block); - caller_body[callsite.block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::Assign(Box::new((Place::from(local), Rvalue::Use(arg)))), - }); + caller_body[callsite.block].statements.push(Statement::new( + callsite.source_info, + StatementKind::Assign(Box::new((Place::from(local), Rvalue::Use(arg)))), + )); local } @@ -1142,19 +1141,14 @@ fn new_call_temp<'tcx>( ) -> Local { let local = caller_body.local_decls.push(LocalDecl::new(ty, callsite.source_info.span)); - caller_body[callsite.block].statements.push(Statement { - source_info: callsite.source_info, - kind: StatementKind::StorageLive(local), - }); + caller_body[callsite.block] + .statements + .push(Statement::new(callsite.source_info, StatementKind::StorageLive(local))); if let Some(block) = return_block { - caller_body[block].statements.insert( - 0, - Statement { - source_info: callsite.source_info, - kind: StatementKind::StorageDead(local), - }, - ); + caller_body[block] + .statements + .insert(0, Statement::new(callsite.source_info, StatementKind::StorageDead(local))); } local diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 5f0c55ddc092d..dbcaed2095383 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -240,15 +240,15 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { let Some(arg_place) = arg.node.place() else { return }; - statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::Use(Operand::Copy( arg_place.project_deeper(&[ProjectionElem::Deref], self.tcx), )), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target: *destination_block }; } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index c4415294264ad..08f25276cecc1 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -259,13 +259,13 @@ fn remap_mir_for_const_eval_select<'tcx>( // (const generic stuff) so we just create a temporary and deconstruct // that. let local = body.local_decls.push(LocalDecl::new(ty, fn_span)); - bb.statements.push(Statement { - source_info: SourceInfo::outermost(fn_span), - kind: StatementKind::Assign(Box::new(( + bb.statements.push(Statement::new( + SourceInfo::outermost(fn_span), + StatementKind::Assign(Box::new(( local.into(), Rvalue::Use(tupled_args.node.clone()), ))), - }); + )); (Operand::Move, local.into()) } Operand::Move(place) => (Operand::Move, place), diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index fa29ab985b7be..8dadce0d448d3 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -25,31 +25,31 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { } sym::ub_checks => { let target = target.unwrap(); - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::NullaryOp(NullOp::UbChecks, tcx.types.bool), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::contract_checks => { let target = target.unwrap(); - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::NullaryOp(NullOp::ContractChecks, tcx.types.bool), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::forget => { let target = target.unwrap(); - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::Use(Operand::Constant(Box::new(ConstOperand { span: terminator.source_info.span, @@ -57,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { const_: Const::zero_sized(tcx.types.unit), }))), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::copy_nonoverlapping => { @@ -65,9 +65,9 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { let Ok([src, dst, count]) = take_array(args) else { bug!("Wrong arguments for copy_non_overlapping intrinsic"); }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Intrinsic(Box::new( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Intrinsic(Box::new( NonDivergingIntrinsic::CopyNonOverlapping( rustc_middle::mir::CopyNonOverlapping { src: src.node, @@ -76,7 +76,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { }, ), )), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::assume => { @@ -84,12 +84,12 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { let Ok([arg]) = take_array(args) else { bug!("Wrong arguments for assume intrinsic"); }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Intrinsic(Box::new( - NonDivergingIntrinsic::Assume(arg.node), - )), - }); + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume( + arg.node, + ))), + )); terminator.kind = TerminatorKind::Goto { target }; } sym::wrapping_add @@ -121,13 +121,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { sym::unchecked_shr => BinOp::ShrUnchecked, _ => bug!("unexpected intrinsic"), }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { @@ -141,13 +141,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { sym::mul_with_overflow => BinOp::MulWithOverflow, _ => bug!("unexpected intrinsic"), }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::size_of | sym::align_of => { @@ -158,13 +158,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { sym::align_of => NullOp::AlignOf, _ => bug!("unexpected intrinsic"), }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::NullaryOp(null_op, tp_ty), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::read_via_copy => { @@ -183,13 +183,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { }; // Add new statement at the end of the block that does the read, and patch // up the terminator. - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::Use(Operand::Copy(derefed_place)), ))), - }); + )); terminator.kind = match *target { None => { // No target means this read something uninhabited, @@ -217,13 +217,10 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { "Only passing a local is supported" ); }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( - derefed_place, - Rvalue::Use(val.node), - ))), - }); + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new((derefed_place, Rvalue::Use(val.node)))), + )); terminator.kind = TerminatorKind::Goto { target }; } sym::discriminant_value => { @@ -236,13 +233,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { }; let arg = arg.node.place().unwrap(); let arg = tcx.mk_place_deref(arg); - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::Discriminant(arg), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::offset => { @@ -253,13 +250,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { "Wrong number of arguments for offset intrinsic", ); }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr.node, delta.node))), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::slice_get_unchecked => { @@ -302,10 +299,10 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { _ => bug!("Unknown return type {ret_ty:?}"), }; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new((*destination, rvalue))), - }); + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new((*destination, rvalue))), + )); terminator.kind = TerminatorKind::Goto { target }; } sym::transmute | sym::transmute_unchecked => { @@ -320,13 +317,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { // Always emit the cast, even if we transmute to an uninhabited type, // because that lets CTFE and codegen generate better error messages // when such a transmute actually ends up reachable. - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty), ))), - }); + )); if let Some(target) = *target { terminator.kind = TerminatorKind::Goto { target }; } else { @@ -351,13 +348,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { ); }; let fields = [data.node, meta.node]; - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::Aggregate(Box::new(kind), fields.into()), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } sym::ptr_metadata => { @@ -368,13 +365,13 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { ); }; let target = target.unwrap(); - block.statements.push(Statement { - source_info: terminator.source_info, - kind: StatementKind::Assign(Box::new(( + block.statements.push(Statement::new( + terminator.source_info, + StatementKind::Assign(Box::new(( *destination, Rvalue::UnaryOp(UnOp::PtrMetadata, ptr.node), ))), - }); + )); terminator.kind = TerminatorKind::Goto { target }; } _ => {} diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index aca80e36e339d..79a9017de3ee1 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -56,8 +56,7 @@ fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>, slice_len_fn_ite // make new RValue for Len let r_value = Rvalue::UnaryOp(UnOp::PtrMetadata, arg.node.clone()); let len_statement_kind = StatementKind::Assign(Box::new((*destination, r_value))); - let add_statement = - Statement { kind: len_statement_kind, source_info: terminator.source_info }; + let add_statement = Statement::new(terminator.source_info, len_statement_kind); // modify terminator into simple Goto let new_terminator_kind = TerminatorKind::Goto { target: *bb }; diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs index a872eae15f185..c781d1a5324b7 100644 --- a/compiler/rustc_mir_transform/src/patch.rs +++ b/compiler/rustc_mir_transform/src/patch.rs @@ -78,14 +78,13 @@ impl<'tcx> MirPatch<'tcx> { return bb; } - let bb = self.new_block(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + let bb = self.new_block(BasicBlockData::new( + Some(Terminator { source_info: SourceInfo::outermost(self.body_span), kind: TerminatorKind::UnwindResume, }), - is_cleanup: true, - }); + true, + )); self.resume_block = Some(bb); bb } @@ -95,14 +94,13 @@ impl<'tcx> MirPatch<'tcx> { return bb; } - let bb = self.new_block(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + let bb = self.new_block(BasicBlockData::new( + Some(Terminator { source_info: SourceInfo::outermost(self.body_span), kind: TerminatorKind::Unreachable, }), - is_cleanup: true, - }); + true, + )); self.unreachable_cleanup_block = Some(bb); bb } @@ -112,14 +110,13 @@ impl<'tcx> MirPatch<'tcx> { return bb; } - let bb = self.new_block(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + let bb = self.new_block(BasicBlockData::new( + Some(Terminator { source_info: SourceInfo::outermost(self.body_span), kind: TerminatorKind::Unreachable, }), - is_cleanup: false, - }); + false, + )); self.unreachable_no_cleanup_block = Some(bb); bb } @@ -131,14 +128,13 @@ impl<'tcx> MirPatch<'tcx> { return cached_bb; } - let bb = self.new_block(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + let bb = self.new_block(BasicBlockData::new( + Some(Terminator { source_info: SourceInfo::outermost(self.body_span), kind: TerminatorKind::UnwindTerminate(reason), }), - is_cleanup: true, - }); + true, + )); self.terminate_block = Some((bb, reason)); bb } @@ -280,7 +276,7 @@ impl<'tcx> MirPatch<'tcx> { let source_info = Self::source_info_for_index(&body[loc.block], loc); body[loc.block] .statements - .insert(loc.statement_index, Statement { source_info, kind: stmt }); + .insert(loc.statement_index, Statement::new(source_info, stmt)); delta += 1; } } diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 47d4383097008..4e8f30e077b0a 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -731,23 +731,22 @@ struct Promoter<'a, 'tcx> { impl<'a, 'tcx> Promoter<'a, 'tcx> { fn new_block(&mut self) -> BasicBlock { let span = self.promoted.span; - self.promoted.basic_blocks_mut().push(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + self.promoted.basic_blocks_mut().push(BasicBlockData::new( + Some(Terminator { source_info: SourceInfo::outermost(span), kind: TerminatorKind::Return, }), - is_cleanup: false, - }) + false, + )) } fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) { let last = self.promoted.basic_blocks.last_index().unwrap(); let data = &mut self.promoted[last]; - data.statements.push(Statement { - source_info: SourceInfo::outermost(span), - kind: StatementKind::Assign(Box::new((Place::from(dest), rvalue))), - }); + data.statements.push(Statement::new( + SourceInfo::outermost(span), + StatementKind::Assign(Box::new((Place::from(dest), rvalue))), + )); } fn is_temp_kind(&self, local: Local) -> bool { @@ -914,13 +913,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { assert_eq!(self.temps.push(TempState::Unpromotable), promoted_ref); let promoted_operand = promoted_operand(ref_ty, span); - let promoted_ref_statement = Statement { - source_info: statement.source_info, - kind: StatementKind::Assign(Box::new(( + let promoted_ref_statement = Statement::new( + statement.source_info, + StatementKind::Assign(Box::new(( Place::from(promoted_ref), Rvalue::Use(Operand::Constant(Box::new(promoted_operand))), ))), - }; + ); self.extra_statements.push((loc, promoted_ref_statement)); ( diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 6d45bbc6e16e2..4083038cbb642 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -323,9 +323,7 @@ fn dropee_emit_retag<'tcx>( StatementKind::Retag(RetagKind::FnEntry, Box::new(dropee_ptr)), ]; for s in new_statements { - body.basic_blocks_mut()[START_BLOCK] - .statements - .push(Statement { source_info, kind: s }); + body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, s)); } } dropee_ptr @@ -350,11 +348,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) let return_block = BasicBlock::new(1); let mut blocks = IndexVec::with_capacity(2); let block = |blocks: &mut IndexVec<_, _>, kind| { - blocks.push(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { source_info, kind }), - is_cleanup: false, - }) + blocks.push(BasicBlockData::new(Some(Terminator { source_info, kind }), false)) }; block(&mut blocks, TerminatorKind::Goto { target: return_block }); block(&mut blocks, TerminatorKind::Return); @@ -515,17 +509,17 @@ fn build_thread_local_shim<'tcx>( let span = tcx.def_span(def_id); let source_info = SourceInfo::outermost(span); - let blocks = IndexVec::from_raw(vec![BasicBlockData { - statements: vec![Statement { + let blocks = IndexVec::from_raw(vec![BasicBlockData::new_stmts( + vec![Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( Place::return_place(), Rvalue::ThreadLocalRef(def_id), ))), - }], - terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), - is_cleanup: false, - }]); + )], + Some(Terminator { source_info, kind: TerminatorKind::Return }), + false, + )]); new_body( MirSource::from_instance(instance), @@ -609,11 +603,11 @@ impl<'tcx> CloneShimBuilder<'tcx> { is_cleanup: bool, ) -> BasicBlock { let source_info = self.source_info(); - self.blocks.push(BasicBlockData { + self.blocks.push(BasicBlockData::new_stmts( statements, - terminator: Some(Terminator { source_info, kind }), + Some(Terminator { source_info, kind }), is_cleanup, - }) + )) } /// Gives the index of an upcoming BasicBlock, with an offset. @@ -625,7 +619,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { } fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> { - Statement { source_info: self.source_info(), kind } + Statement::new(self.source_info(), kind) } fn copy_shim(&mut self) { @@ -901,13 +895,13 @@ fn build_call_shim<'tcx>( .immutable(), ); let borrow_kind = BorrowKind::Mut { kind: MutBorrowKind::Default }; - statements.push(Statement { + statements.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( Place::from(ref_rcvr), Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()), ))), - }); + )); Operand::Move(Place::from(ref_rcvr)) } }); @@ -956,11 +950,11 @@ fn build_call_shim<'tcx>( let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 }; let mut blocks = IndexVec::with_capacity(n_blocks); let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| { - blocks.push(BasicBlockData { + blocks.push(BasicBlockData::new_stmts( statements, - terminator: Some(Terminator { source_info, kind }), + Some(Terminator { source_info, kind }), is_cleanup, - }) + )) }; // BB #0 @@ -1071,8 +1065,9 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { let kind = AggregateKind::Adt(adt_def.did(), variant_index, args, None, None); let variant = adt_def.variant(variant_index); - let statement = Statement { - kind: StatementKind::Assign(Box::new(( + let statement = Statement::new( + source_info, + StatementKind::Assign(Box::new(( Place::return_place(), Rvalue::Aggregate( Box::new(kind), @@ -1081,14 +1076,13 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { .collect(), ), ))), - source_info, - }; + ); - let start_block = BasicBlockData { - statements: vec![statement], - terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), - is_cleanup: false, - }; + let start_block = BasicBlockData::new_stmts( + vec![statement], + Some(Terminator { source_info, kind: TerminatorKind::Return }), + false, + ); let source = MirSource::item(ctor_id); let mut body = new_body( @@ -1130,16 +1124,16 @@ fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'t Operand::Move(Place::from(Local::new(1))), Ty::new_imm_ptr(tcx, tcx.types.unit), ); - let stmt = Statement { + let stmt = Statement::new( source_info, - kind: StatementKind::Assign(Box::new((Place::return_place(), rvalue))), - }; + StatementKind::Assign(Box::new((Place::return_place(), rvalue))), + ); let statements = vec![stmt]; - let start_block = BasicBlockData { + let start_block = BasicBlockData::new_stmts( statements, - terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), - is_cleanup: false, - }; + Some(Terminator { source_info, kind: TerminatorKind::Return }), + false, + ); let source = MirSource::from_instance(ty::InstanceKind::FnPtrAddrShim(def_id, self_ty)); new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span) } @@ -1230,16 +1224,16 @@ fn build_construct_coroutine_by_move_shim<'tcx>( Box::new(AggregateKind::Coroutine(coroutine_def_id, coroutine_args)), IndexVec::from_raw(fields), ); - let stmt = Statement { + let stmt = Statement::new( source_info, - kind: StatementKind::Assign(Box::new((Place::return_place(), rvalue))), - }; + StatementKind::Assign(Box::new((Place::return_place(), rvalue))), + ); let statements = vec![stmt]; - let start_block = BasicBlockData { + let start_block = BasicBlockData::new_stmts( statements, - terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), - is_cleanup: false, - }; + Some(Terminator { source_info, kind: TerminatorKind::Return }), + false, + ); let source = MirSource::from_instance(ty::InstanceKind::ConstructCoroutineInClosureShim { coroutine_closure_def_id, diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index fd7b7362cd9da..18d09473c191e 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -88,11 +88,7 @@ pub(super) fn build_async_drop_shim<'tcx>( let return_block = BasicBlock::new(1); let mut blocks = IndexVec::with_capacity(2); let block = |blocks: &mut IndexVec<_, _>, kind| { - blocks.push(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { source_info, kind }), - is_cleanup: false, - }) + blocks.push(BasicBlockData::new(Some(Terminator { source_info, kind }), false)) }; block( &mut blocks, @@ -133,7 +129,7 @@ pub(super) fn build_async_drop_shim<'tcx>( dropee_ptr, Rvalue::Use(Operand::Move(coroutine_layout_dropee)), ))); - body.basic_blocks_mut()[START_BLOCK].statements.push(Statement { source_info, kind: st_kind }); + body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, st_kind)); dropee_ptr = dropee_emit_retag(tcx, &mut body, dropee_ptr, span); let dropline = body.basic_blocks.last_index(); @@ -240,13 +236,13 @@ fn build_adrop_for_coroutine_shim<'tcx>( .project_deeper(&[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)], tcx); body.basic_blocks_mut()[START_BLOCK].statements.insert( idx, - Statement { + Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( Place::from(proxy_ref_local), Rvalue::CopyForDeref(proxy_ref_place), ))), - }, + ), ); idx += 1; let mut cor_ptr_local = proxy_ref_local; @@ -261,13 +257,13 @@ fn build_adrop_for_coroutine_shim<'tcx>( // _cor_ptr = _proxy.0.0 (... .0) body.basic_blocks_mut()[START_BLOCK].statements.insert( idx, - Statement { + Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( Place::from(cor_ptr_local), Rvalue::CopyForDeref(impl_ptr_place), ))), - }, + ), ); idx += 1; } @@ -281,10 +277,10 @@ fn build_adrop_for_coroutine_shim<'tcx>( ); body.basic_blocks_mut()[START_BLOCK].statements.insert( idx, - Statement { + Statement::new( source_info, - kind: StatementKind::Assign(Box::new((Place::from(cor_ref_local), reborrow))), - }, + StatementKind::Assign(Box::new((Place::from(cor_ref_local), reborrow))), + ), ); } body @@ -334,13 +330,13 @@ fn build_adrop_for_adrop_shim<'tcx>( let mut statements = Vec::new(); - statements.push(Statement { + statements.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( Place::from(proxy_ref_local), Rvalue::CopyForDeref(proxy_ref_place), ))), - }); + )); let mut cor_ptr_local = proxy_ref_local; proxy_ty.find_async_drop_impl_coroutine(tcx, |ty| { @@ -350,13 +346,13 @@ fn build_adrop_for_adrop_shim<'tcx>( .project_deeper(&[PlaceElem::Deref, PlaceElem::Field(FieldIdx::ZERO, ty_ptr)], tcx); cor_ptr_local = locals.push(LocalDecl::new(ty_ptr, span)); // _cor_ptr = _proxy.0.0 (... .0) - statements.push(Statement { + statements.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new(( + StatementKind::Assign(Box::new(( Place::from(cor_ptr_local), Rvalue::CopyForDeref(impl_ptr_place), ))), - }); + )); } }); @@ -367,10 +363,10 @@ fn build_adrop_for_adrop_shim<'tcx>( tcx.mk_place_deref(Place::from(cor_ptr_local)), ); let cor_ref_place = Place::from(locals.push(LocalDecl::new(cor_ref, span))); - statements.push(Statement { + statements.push(Statement::new( source_info, - kind: StatementKind::Assign(Box::new((cor_ref_place, reborrow))), - }); + StatementKind::Assign(Box::new((cor_ref_place, reborrow))), + )); // cor_pin_ty = `Pin<&mut cor_ref>` let cor_pin_ty = Ty::new_adt(tcx, pin_adt_ref, tcx.mk_args(&[cor_ref.into()])); @@ -378,9 +374,9 @@ fn build_adrop_for_adrop_shim<'tcx>( let pin_fn = tcx.require_lang_item(LangItem::PinNewUnchecked, span); // call Pin::new_unchecked(&mut impl_cor) - blocks.push(BasicBlockData { + blocks.push(BasicBlockData::new_stmts( statements, - terminator: Some(Terminator { + Some(Terminator { source_info, kind: TerminatorKind::Call { func: Operand::function_handle(tcx, pin_fn, [cor_ref.into()], span), @@ -392,15 +388,14 @@ fn build_adrop_for_adrop_shim<'tcx>( fn_span: span, }, }), - is_cleanup: false, - }); + false, + )); // When dropping async drop coroutine, we continue its execution: // we call impl::poll (impl_layout, ctx) let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, span); let resume_ctx = Place::from(Local::new(2)); - blocks.push(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { + blocks.push(BasicBlockData::new( + Some(Terminator { source_info, kind: TerminatorKind::Call { func: Operand::function_handle(tcx, poll_fn, [impl_ty.into()], span), @@ -416,13 +411,12 @@ fn build_adrop_for_adrop_shim<'tcx>( fn_span: span, }, }), - is_cleanup: false, - }); - blocks.push(BasicBlockData { - statements: vec![], - terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }), - is_cleanup: false, - }); + false, + )); + blocks.push(BasicBlockData::new( + Some(Terminator { source_info, kind: TerminatorKind::Return }), + false, + )); let source = MirSource::from_instance(instance); let mut body = new_body(source, blocks, locals, sig.inputs().len(), span); diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index bd00823073139..c60eb566521c5 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -115,10 +115,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { for bb_idx in new_targets.all_targets() { storage_deads_to_insert.push(( *bb_idx, - Statement { - source_info: terminator.source_info, - kind: StatementKind::StorageDead(opt.to_switch_on.local), - }, + Statement::new( + terminator.source_info, + StatementKind::StorageDead(opt.to_switch_on.local), + ), )); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index a300558c0c9ce..c281ef216c788 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -383,10 +383,10 @@ where let mut candidates = vec![]; - if let TypingMode::Coherence = self.typing_mode() { - if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) { - return vec![candidate]; - } + if let TypingMode::Coherence = self.typing_mode() + && let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) + { + return vec![candidate]; } self.assemble_alias_bound_candidates(goal, &mut candidates); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 5b6f978527285..73bb1508de97a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -997,12 +997,12 @@ where } fn try_fold_ty(&mut self, ty: I::Ty) -> Result { - if let ty::Alias(ty::Projection, alias_ty) = ty.kind() { - if let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { - return Ok(term.expect_ty()); - } + if let ty::Alias(ty::Projection, alias_ty) = ty.kind() + && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? + { + Ok(term.expect_ty()) + } else { + ty.try_super_fold_with(self) } - - ty.try_super_fold_with(self) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 0547eb77f8d83..42264f58bcd19 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -42,20 +42,18 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - if let Some(host_clause) = assumption.as_host_effect_clause() { - if host_clause.def_id() == goal.predicate.def_id() - && host_clause.constness().satisfies(goal.predicate.constness) - { - if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.trait_ref.args, - host_clause.skip_binder().trait_ref.args, - ) { - return Ok(()); - } - } + if let Some(host_clause) = assumption.as_host_effect_clause() + && host_clause.def_id() == goal.predicate.def_id() + && host_clause.constness().satisfies(goal.predicate.constness) + && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.trait_ref.args, + host_clause.skip_binder().trait_ref.args, + ) + { + Ok(()) + } else { + Err(NoSolution) } - - Err(NoSolution) } fn match_assumption( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index dd9ccadf6cf64..b42587618b57b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -429,22 +429,21 @@ where // If we have run this goal before, and it was stalled, check that any of the goal's // args have changed. Otherwise, we don't need to re-run the goal because it'll remain // stalled, since it'll canonicalize the same way and evaluation is pure. - if let Some(stalled_on) = stalled_on { - if !stalled_on.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value)) - && !self - .delegate - .opaque_types_storage_num_entries() - .needs_reevaluation(stalled_on.num_opaques) - { - return Ok(( - NestedNormalizationGoals::empty(), - GoalEvaluation { - certainty: Certainty::Maybe(stalled_on.stalled_cause), - has_changed: HasChanged::No, - stalled_on: Some(stalled_on), - }, - )); - } + if let Some(stalled_on) = stalled_on + && !stalled_on.stalled_vars.iter().any(|value| self.delegate.is_changed_arg(*value)) + && !self + .delegate + .opaque_types_storage_num_entries() + .needs_reevaluation(stalled_on.num_opaques) + { + return Ok(( + NestedNormalizationGoals::empty(), + GoalEvaluation { + certainty: Certainty::Maybe(stalled_on.stalled_cause), + has_changed: HasChanged::No, + stalled_on: Some(stalled_on), + }, + )); } let (orig_values, canonical_goal) = self.canonicalize_goal(goal); @@ -833,14 +832,11 @@ where match t.kind() { ty::Infer(ty::TyVar(vid)) => { - if let ty::TermKind::Ty(term) = self.term.kind() { - if let ty::Infer(ty::TyVar(term_vid)) = term.kind() { - if self.delegate.root_ty_var(vid) - == self.delegate.root_ty_var(term_vid) - { - return ControlFlow::Break(()); - } - } + if let ty::TermKind::Ty(term) = self.term.kind() + && let ty::Infer(ty::TyVar(term_vid)) = term.kind() + && self.delegate.root_ty_var(vid) == self.delegate.root_ty_var(term_vid) + { + return ControlFlow::Break(()); } self.check_nameable(self.delegate.universe_of_ty(vid).unwrap())?; @@ -860,15 +856,12 @@ where fn visit_const(&mut self, c: I::Const) -> Self::Result { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - if let ty::TermKind::Const(term) = self.term.kind() { - if let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind() - { - if self.delegate.root_const_var(vid) - == self.delegate.root_const_var(term_vid) - { - return ControlFlow::Break(()); - } - } + if let ty::TermKind::Const(term) = self.term.kind() + && let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind() + && self.delegate.root_const_var(vid) + == self.delegate.root_const_var(term_vid) + { + return ControlFlow::Break(()); } self.check_nameable(self.delegate.universe_of_ct(vid).unwrap()) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index d51c87fe68e60..edb354b4a8454 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -112,18 +112,17 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - if let Some(projection_pred) = assumption.as_projection_clause() { - if projection_pred.item_def_id() == goal.predicate.def_id() { - if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.alias.args, - projection_pred.skip_binder().projection_term.args, - ) { - return Ok(()); - } - } + if let Some(projection_pred) = assumption.as_projection_clause() + && projection_pred.item_def_id() == goal.predicate.def_id() + && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.alias.args, + projection_pred.skip_binder().projection_term.args, + ) + { + Ok(()) + } else { + Err(NoSolution) } - - Err(NoSolution) } fn match_assumption( diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 8aaa8e9ca87ea..6c9fb63b579ad 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -127,33 +127,32 @@ where goal: Goal, assumption: I::Clause, ) -> Result<(), NoSolution> { - if let Some(trait_clause) = assumption.as_trait_clause() { - if trait_clause.polarity() != goal.predicate.polarity { - return Err(NoSolution); - } - - if trait_clause.def_id() == goal.predicate.def_id() { - if DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( - goal.predicate.trait_ref.args, - trait_clause.skip_binder().trait_ref.args, - ) { - return Ok(()); - } - } - + fn trait_def_id_matches( + cx: I, + clause_def_id: I::DefId, + goal_def_id: I::DefId, + ) -> bool { + clause_def_id == goal_def_id // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so - // check for a `Sized` subtrait when looking for `MetaSized`. `PointeeSized` bounds - // are syntactic sugar for a lack of bounds so don't need this. - if ecx.cx().is_lang_item(goal.predicate.def_id(), TraitSolverLangItem::MetaSized) - && ecx.cx().is_lang_item(trait_clause.def_id(), TraitSolverLangItem::Sized) - { - let meta_sized_clause = - trait_predicate_with_def_id(ecx.cx(), trait_clause, goal.predicate.def_id()); - return Self::fast_reject_assumption(ecx, goal, meta_sized_clause); - } + // check for a `MetaSized` supertrait being matched against a `Sized` assumption. + // + // `PointeeSized` bounds are syntactic sugar for a lack of bounds so don't need this. + || (cx.is_lang_item(clause_def_id, TraitSolverLangItem::Sized) + && cx.is_lang_item(goal_def_id, TraitSolverLangItem::MetaSized)) } - Err(NoSolution) + if let Some(trait_clause) = assumption.as_trait_clause() + && trait_clause.polarity() == goal.predicate.polarity + && trait_def_id_matches(ecx.cx(), trait_clause.def_id(), goal.predicate.def_id()) + && DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify( + goal.predicate.trait_ref.args, + trait_clause.skip_binder().trait_ref.args, + ) + { + return Ok(()); + } else { + Err(NoSolution) + } } fn match_assumption( diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ae486a58062bf..34c76bd3f27f3 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -177,6 +177,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => { self.check_align(span, target, *align, *repr_span) } + Attribute::Parsed(AttributeKind::LinkSection { span: attr_span, .. }) => { + self.check_link_section(hir_id, *attr_span, span, target) + } Attribute::Parsed(AttributeKind::Naked(attr_span)) => { self.check_naked(hir_id, *attr_span, span, target) } @@ -286,7 +289,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target), [sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target), [sym::link, ..] => self.check_link(hir_id, attr, span, target), - [sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target), [sym::macro_use, ..] | [sym::macro_escape, ..] => { self.check_macro_use(hir_id, attr, target) } @@ -1831,7 +1833,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[link_section]` is applied to a function or static. - fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { + fn check_link_section(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { match target { Target::Static | Target::Fn | Target::Method(..) => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an @@ -1839,7 +1841,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "link_section"); + self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "link_section"); } _ => { // FIXME: #[link_section] was previously allowed on non-functions/statics and some @@ -1847,7 +1849,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, - attr.span(), + attr_span, errors::LinkSection { span }, ); } diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 177bad96595e0..7ffcf7b5d9654 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -320,10 +320,10 @@ pub fn supertrait_def_ids( let trait_def_id = stack.pop()?; for (predicate, _) in cx.explicit_super_predicates_of(trait_def_id).iter_identity() { - if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() { - if set.insert(data.def_id()) { - stack.push(data.def_id()); - } + if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() + && set.insert(data.def_id()) + { + stack.push(data.def_id()); } } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index e42639c68075a..79f6bc5dabb40 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -284,12 +284,12 @@ where } // If they have no bound vars, relate normally. - if let Some(a_inner) = a.no_bound_vars() { - if let Some(b_inner) = b.no_bound_vars() { - self.relate(a_inner, b_inner)?; - return Ok(a); - } - }; + if let Some(a_inner) = a.no_bound_vars() + && let Some(b_inner) = b.no_bound_vars() + { + self.relate(a_inner, b_inner)?; + return Ok(a); + } match self.ambient_variance { // Checks whether `for<..> sub <: for<..> sup` holds. diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs index 1b99cc820f1ab..eb56c1af408bb 100644 --- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs +++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs @@ -80,31 +80,29 @@ impl GlobalCache { mut candidate_is_applicable: impl FnMut(&NestedGoals) -> bool, ) -> Option> { let entry = self.map.get(&input)?; - if let Some(Success { required_depth, ref nested_goals, ref result }) = entry.success { - if available_depth.cache_entry_is_applicable(required_depth) - && candidate_is_applicable(nested_goals) - { - return Some(CacheData { - result: cx.get_tracked(&result), - required_depth, - encountered_overflow: false, - nested_goals, - }); - } + if let Some(Success { required_depth, ref nested_goals, ref result }) = entry.success + && available_depth.cache_entry_is_applicable(required_depth) + && candidate_is_applicable(nested_goals) + { + return Some(CacheData { + result: cx.get_tracked(&result), + required_depth, + encountered_overflow: false, + nested_goals, + }); } let additional_depth = available_depth.0; if let Some(WithOverflow { nested_goals, result }) = entry.with_overflow.get(&additional_depth) + && candidate_is_applicable(nested_goals) { - if candidate_is_applicable(nested_goals) { - return Some(CacheData { - result: cx.get_tracked(result), - required_depth: additional_depth, - encountered_overflow: true, - nested_goals, - }); - } + return Some(CacheData { + result: cx.get_tracked(result), + required_depth: additional_depth, + encountered_overflow: true, + nested_goals, + }); } None diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 0ac887f99dc89..98a3b784233f1 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -316,6 +316,11 @@ mod prim_bool {} #[unstable(feature = "never_type", issue = "35121")] mod prim_never {} +// Required to make auto trait impls render. +// See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls +#[doc(hidden)] +impl ! {} + #[rustc_doc_primitive = "char"] #[allow(rustdoc::invalid_rust_codeblocks)] /// A character type. diff --git a/library/std/src/sys/fs/windows/remove_dir_all.rs b/library/std/src/sys/fs/windows/remove_dir_all.rs index 06734f9e3097b..c8b1a07676855 100644 --- a/library/std/src/sys/fs/windows/remove_dir_all.rs +++ b/library/std/src/sys/fs/windows/remove_dir_all.rs @@ -33,7 +33,7 @@ use core::sync::atomic::{Atomic, AtomicU32, Ordering}; use super::{AsRawHandle, DirBuff, File, FromRawHandle}; use crate::sys::c; -use crate::sys::pal::api::WinError; +use crate::sys::pal::api::{UnicodeStrRef, WinError, unicode_str}; use crate::thread; // The maximum number of times to spin when waiting for deletes to complete. @@ -74,7 +74,7 @@ unsafe fn nt_open_file( /// `options` will be OR'd with `FILE_OPEN_REPARSE_POINT`. fn open_link_no_reparse( parent: &File, - path: &[u16], + path: UnicodeStrRef<'_>, access: u32, options: u32, ) -> Result, WinError> { @@ -90,9 +90,8 @@ fn open_link_no_reparse( static ATTRIBUTES: Atomic = AtomicU32::new(c::OBJ_DONT_REPARSE); let result = unsafe { - let mut path_str = c::UNICODE_STRING::from_ref(path); let mut object = c::OBJECT_ATTRIBUTES { - ObjectName: &mut path_str, + ObjectName: path.as_ptr(), RootDirectory: parent.as_raw_handle(), Attributes: ATTRIBUTES.load(Ordering::Relaxed), ..c::OBJECT_ATTRIBUTES::with_length() @@ -129,7 +128,7 @@ fn open_link_no_reparse( } } -fn open_dir(parent: &File, name: &[u16]) -> Result, WinError> { +fn open_dir(parent: &File, name: UnicodeStrRef<'_>) -> Result, WinError> { // Open the directory for synchronous directory listing. open_link_no_reparse( parent, @@ -140,7 +139,7 @@ fn open_dir(parent: &File, name: &[u16]) -> Result, WinError> { ) } -fn delete(parent: &File, name: &[u16]) -> Result<(), WinError> { +fn delete(parent: &File, name: UnicodeStrRef<'_>) -> Result<(), WinError> { // Note that the `delete` function consumes the opened file to ensure it's // dropped immediately. See module comments for why this is important. match open_link_no_reparse(parent, name, c::DELETE, 0) { @@ -179,8 +178,9 @@ pub fn remove_dir_all_iterative(dir: File) -> Result<(), WinError> { 'outer: while let Some(dir) = dirlist.pop() { let more_data = dir.fill_dir_buff(&mut buffer, restart)?; for (name, is_directory) in buffer.iter() { + let name = unicode_str!(&name); if is_directory { - let Some(subdir) = open_dir(&dir, &name)? else { continue }; + let Some(subdir) = open_dir(&dir, name)? else { continue }; dirlist.push(dir); dirlist.push(subdir); continue 'outer; @@ -188,7 +188,7 @@ pub fn remove_dir_all_iterative(dir: File) -> Result<(), WinError> { // Attempt to delete, retrying on sharing violation errors as these // can often be very temporary. E.g. if something takes just a // bit longer than expected to release a file handle. - retry(|| delete(&dir, &name), WinError::SHARING_VIOLATION)?; + retry(|| delete(&dir, name), WinError::SHARING_VIOLATION)?; } } if more_data { @@ -197,7 +197,8 @@ pub fn remove_dir_all_iterative(dir: File) -> Result<(), WinError> { } else { // Attempt to delete, retrying on not empty errors because we may // need to wait some time for files to be removed from the filesystem. - retry(|| delete(&dir, &[]), WinError::DIR_NOT_EMPTY)?; + let name = unicode_str!(""); + retry(|| delete(&dir, name), WinError::DIR_NOT_EMPTY)?; restart = true; } } diff --git a/library/std/src/sys/pal/windows/api.rs b/library/std/src/sys/pal/windows/api.rs index 773455c572f70..25a6c2d7d8eda 100644 --- a/library/std/src/sys/pal/windows/api.rs +++ b/library/std/src/sys/pal/windows/api.rs @@ -30,6 +30,7 @@ //! should go in sys/pal/windows/mod.rs rather than here. See `IoResult` as an example. use core::ffi::c_void; +use core::marker::PhantomData; use super::c; @@ -291,3 +292,75 @@ impl WinError { pub const TIMEOUT: Self = Self::new(c::ERROR_TIMEOUT); // tidy-alphabetical-end } + +/// A wrapper around a UNICODE_STRING that is equivalent to `&[u16]`. +/// +/// It is preferable to use the `unicode_str!` macro as that contains mitigations for #143078. +/// +/// If the MaximumLength field of the underlying UNICODE_STRING is greater than +/// the Length field then you can test if the string is null terminated by inspecting +/// the u16 directly after the string. You cannot otherwise depend on nul termination. +#[derive(Copy, Clone)] +pub struct UnicodeStrRef<'a> { + s: c::UNICODE_STRING, + lifetime: PhantomData<&'a [u16]>, +} + +static EMPTY_STRING_NULL_TERMINATED: &[u16] = &[0]; + +impl UnicodeStrRef<'_> { + const fn new(slice: &[u16], is_null_terminated: bool) -> Self { + let (len, max_len, ptr) = if slice.is_empty() { + (0, 2, EMPTY_STRING_NULL_TERMINATED.as_ptr().cast_mut()) + } else { + let len = slice.len() - (is_null_terminated as usize); + (len * 2, size_of_val(slice), slice.as_ptr().cast_mut()) + }; + Self { + s: c::UNICODE_STRING { Length: len as _, MaximumLength: max_len as _, Buffer: ptr }, + lifetime: PhantomData, + } + } + + pub const fn from_slice_with_nul(slice: &[u16]) -> Self { + if !slice.is_empty() { + debug_assert!(slice[slice.len() - 1] == 0); + } + Self::new(slice, true) + } + + pub const fn from_slice(slice: &[u16]) -> Self { + Self::new(slice, false) + } + + /// Returns a pointer to the underlying UNICODE_STRING + pub const fn as_ptr(&self) -> *const c::UNICODE_STRING { + &self.s + } +} + +/// Create a UnicodeStringRef from a literal str or a u16 array. +/// +/// To mitigate #143078, when using a literal str the created UNICODE_STRING +/// will be nul terminated. The MaximumLength field of the UNICODE_STRING will +/// be set greater than the Length field to indicate that a nul may be present. +/// +/// If using a u16 array, the array is used exactly as provided and you cannot +/// count on the string being nul terminated. +/// This should generally be used for strings that come from the OS. +/// +/// **NOTE:** we lack a UNICODE_STRING builder type as we don't currently have +/// a use for it. If needing to dynamically build a UNICODE_STRING, the builder +/// should try to ensure there's a nul one past the end of the string. +pub macro unicode_str { + ($str:literal) => {const { + crate::sys::pal::windows::api::UnicodeStrRef::from_slice_with_nul( + crate::sys::pal::windows::api::wide_str!($str), + ) + }}, + ($array:expr) => { + crate::sys::pal::windows::api::UnicodeStrRef::from_slice( + $array, + ) + } +} diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 53dec105d0c85..eee169d410a9c 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -37,13 +37,6 @@ pub fn nt_success(status: NTSTATUS) -> bool { status >= 0 } -impl UNICODE_STRING { - pub fn from_ref(slice: &[u16]) -> Self { - let len = size_of_val(slice); - Self { Length: len as _, MaximumLength: len as _, Buffer: slice.as_ptr() as _ } - } -} - impl OBJECT_ATTRIBUTES { pub fn with_length() -> Self { Self { diff --git a/library/std/src/sys/pal/windows/pipe.rs b/library/std/src/sys/pal/windows/pipe.rs index bc5d05c45052a..b5ccf037a4f22 100644 --- a/library/std/src/sys/pal/windows/pipe.rs +++ b/library/std/src/sys/pal/windows/pipe.rs @@ -1,9 +1,8 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::ops::Neg; use crate::os::windows::prelude::*; -use crate::sys::api::utf16; -use crate::sys::c; use crate::sys::handle::Handle; +use crate::sys::{api, c}; use crate::sys_common::{FromInner, IntoInner}; use crate::{mem, ptr}; @@ -73,8 +72,8 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res // Open a handle to the pipe filesystem (`\??\PIPE\`). // This will be used when creating a new annon pipe. let pipe_fs = { - let path = c::UNICODE_STRING::from_ref(utf16!(r"\??\PIPE\")); - object_attributes.ObjectName = &path; + let path = api::unicode_str!(r"\??\PIPE\"); + object_attributes.ObjectName = path.as_ptr(); let mut pipe_fs = ptr::null_mut(); let status = c::NtOpenFile( &mut pipe_fs, @@ -93,8 +92,12 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res // From now on we're using handles instead of paths to create and open pipes. // So set the `ObjectName` to a zero length string. + // As a (perhaps overzealous) mitigation for #143078, we use the null pointer + // for empty.Buffer instead of unicode_str!(""). + // There's no difference to the OS itself but it's possible that third party + // DLLs which hook in to processes could be relying on the exact form of this string. let empty = c::UNICODE_STRING::default(); - object_attributes.ObjectName = ∅ + object_attributes.ObjectName = &raw const empty; // Create our side of the pipe for async access. let ours = { diff --git a/library/stdarch/crates/intrinsic-test/README.md b/library/stdarch/crates/intrinsic-test/README.md index 260d59fca80f7..bea95f91e9e1c 100644 --- a/library/stdarch/crates/intrinsic-test/README.md +++ b/library/stdarch/crates/intrinsic-test/README.md @@ -7,7 +7,7 @@ USAGE: intrinsic-test [FLAGS] [OPTIONS] FLAGS: - --a32 Run tests for A32 instrinsics instead of A64 + --a32 Run tests for A32 intrinsics instead of A64 --generate-only Regenerate test programs, but don't build or run them -h, --help Prints help information -V, --version Prints version information diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 09dc476d68eea..f7e62e1eccf67 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -499,7 +499,7 @@ This directive takes comma-separated issue numbers as arguments, or `"unknown"`: - `//@ known-bug: rust-lang/chalk#123456` (allows arbitrary text before the `#`, which is useful when the issue is on another repo) - `//@ known-bug: unknown` - (when there is no known issue yet; preferrably open one if it does not already exist) + (when there is no known issue yet; preferably open one if it does not already exist) Do not include [error annotations](#error-annotations) in a test with `known-bug`. The test should still include other normal directives and diff --git a/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md b/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md index a6fb25a55be2b..10464e500ec2a 100644 --- a/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md +++ b/src/doc/unstable-book/src/language-features/type-alias-impl-trait.md @@ -64,7 +64,7 @@ struct HaveAlias { In this example, the concrete type referred to by `Alias` is guaranteed to be the same wherever `Alias` occurs. -> Orginally this feature included type aliases as an associated type of a trait. In [#110237] this was split off to [`impl_trait_in_assoc_type`]. +> Originally this feature included type aliases as an associated type of a trait. In [#110237] this was split off to [`impl_trait_in_assoc_type`]. ### `type_alias_impl_trait` in argument position. diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 3cac55493f00a..600c564d71418 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -753,9 +753,12 @@ impl Item { .other_attrs .iter() .filter_map(|attr| { + if let hir::Attribute::Parsed(AttributeKind::LinkSection { name, .. }) = attr { + Some(format!("#[link_section = \"{name}\"]")) + } // NoMangle is special cased, as it appears in HTML output, and we want to show it in source form, not HIR printing. // It is also used by cargo-semver-checks. - if let hir::Attribute::Parsed(AttributeKind::NoMangle(..)) = attr { + else if let hir::Attribute::Parsed(AttributeKind::NoMangle(..)) = attr { Some("#[no_mangle]".to_string()) } else if let hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) = attr { diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index ec77a162cdbde..ed1851a19ae0d 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -191,7 +191,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [f] = check_intrinsic_arg_count(args)?; let f = this.read_scalar(f)?.to_f32()?; - let res = fixed_float_value(intrinsic_name, &[f]).unwrap_or_else(||{ + let res = fixed_float_value(this, intrinsic_name, &[f]).unwrap_or_else(|| { // Using host floats (but it's fine, these operations do not have // guaranteed precision). let host = f.to_host(); @@ -235,7 +235,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let [f] = check_intrinsic_arg_count(args)?; let f = this.read_scalar(f)?.to_f64()?; - let res = fixed_float_value(intrinsic_name, &[f]).unwrap_or_else(||{ + let res = fixed_float_value(this, intrinsic_name, &[f]).unwrap_or_else(|| { // Using host floats (but it's fine, these operations do not have // guaranteed precision). let host = f.to_host(); @@ -312,7 +312,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let f1 = this.read_scalar(f1)?.to_f32()?; let f2 = this.read_scalar(f2)?.to_f32()?; - let res = fixed_float_value(intrinsic_name, &[f1, f2]).unwrap_or_else(|| { + let res = fixed_float_value(this, intrinsic_name, &[f1, f2]).unwrap_or_else(|| { // Using host floats (but it's fine, this operation does not have guaranteed precision). let res = f1.to_host().powf(f2.to_host()).to_soft(); @@ -330,7 +330,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let f1 = this.read_scalar(f1)?.to_f64()?; let f2 = this.read_scalar(f2)?.to_f64()?; - let res = fixed_float_value(intrinsic_name, &[f1, f2]).unwrap_or_else(|| { + let res = fixed_float_value(this, intrinsic_name, &[f1, f2]).unwrap_or_else(|| { // Using host floats (but it's fine, this operation does not have guaranteed precision). let res = f1.to_host().powf(f2.to_host()).to_soft(); @@ -349,7 +349,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let f = this.read_scalar(f)?.to_f32()?; let i = this.read_scalar(i)?.to_i32()?; - let res = fixed_powi_float_value(f, i).unwrap_or_else(|| { + let res = fixed_powi_float_value(this, f, i).unwrap_or_else(|| { // Using host floats (but it's fine, this operation does not have guaranteed precision). let res = f.to_host().powi(i).to_soft(); @@ -367,7 +367,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let f = this.read_scalar(f)?.to_f64()?; let i = this.read_scalar(i)?.to_i32()?; - let res = fixed_powi_float_value(f, i).unwrap_or_else(|| { + let res = fixed_powi_float_value(this, f, i).unwrap_or_else(|| { // Using host floats (but it's fine, this operation does not have guaranteed precision). let res = f.to_host().powi(i).to_soft(); @@ -496,52 +496,88 @@ fn apply_random_float_error_to_imm<'tcx>( /// - logf32, logf64, log2f32, log2f64, log10f32, log10f64 /// - powf32, powf64 /// +/// # Return +/// /// Returns `Some(output)` if the `intrinsic` results in a defined fixed `output` specified in the C standard /// (specifically, C23 annex F.10) when given `args` as arguments. Outputs that are unaffected by a relative error /// (such as INF and zero) are not handled here, they are assumed to be handled by the underlying /// implementation. Returns `None` if no specific value is guaranteed. +/// +/// # Note +/// +/// For `powf*` operations of the form: +/// +/// - `(SNaN)^(±0)` +/// - `1^(SNaN)` +/// +/// The result is implementation-defined: +/// - musl returns for both `1.0` +/// - glibc returns for both `NaN` +/// +/// This discrepancy exists because SNaN handling is not consistently defined across platforms, +/// and the C standard leaves behavior for SNaNs unspecified. +/// +/// Miri chooses to adhere to both implementations and returns either one of them non-deterministically. fn fixed_float_value( + ecx: &mut MiriInterpCx<'_>, intrinsic_name: &str, args: &[IeeeFloat], ) -> Option> { let one = IeeeFloat::::one(); - match (intrinsic_name, args) { + Some(match (intrinsic_name, args) { // cos(+- 0) = 1 - ("cosf32" | "cosf64", [input]) if input.is_zero() => Some(one), + ("cosf32" | "cosf64", [input]) if input.is_zero() => one, // e^0 = 1 - ("expf32" | "expf64" | "exp2f32" | "exp2f64", [input]) if input.is_zero() => Some(one), - - // 1^y = 1 for any y, even a NaN. - ("powf32" | "powf64", [base, _]) if *base == one => Some(one), + ("expf32" | "expf64" | "exp2f32" | "exp2f64", [input]) if input.is_zero() => one, // (-1)^(±INF) = 1 - ("powf32" | "powf64", [base, exp]) if *base == -one && exp.is_infinite() => Some(one), + ("powf32" | "powf64", [base, exp]) if *base == -one && exp.is_infinite() => one, + + // 1^y = 1 for any y, even a NaN + ("powf32" | "powf64", [base, exp]) if *base == one => { + let rng = ecx.machine.rng.get_mut(); + // SNaN exponents get special treatment: they might return 1, or a NaN. + let return_nan = exp.is_signaling() && ecx.machine.float_nondet && rng.random(); + // Handle both the musl and glibc cases non-deterministically. + if return_nan { ecx.generate_nan(args) } else { one } + } - // FIXME(#4286): The C ecosystem is inconsistent with handling sNaN's, some return 1 others propogate - // the NaN. We should return either 1 or the NaN non-deterministically here. - // But for now, just handle them all the same. // x^(±0) = 1 for any x, even a NaN - ("powf32" | "powf64", [_, exp]) if exp.is_zero() => Some(one), + ("powf32" | "powf64", [base, exp]) if exp.is_zero() => { + let rng = ecx.machine.rng.get_mut(); + // SNaN bases get special treatment: they might return 1, or a NaN. + let return_nan = base.is_signaling() && ecx.machine.float_nondet && rng.random(); + // Handle both the musl and glibc cases non-deterministically. + if return_nan { ecx.generate_nan(args) } else { one } + } - // There are a lot of cases for fixed outputs according to the C Standard, but these are mainly INF or zero - // which are not affected by the applied error. - _ => None, - } + // There are a lot of cases for fixed outputs according to the C Standard, but these are + // mainly INF or zero which are not affected by the applied error. + _ => return None, + }) } -/// Returns `Some(output)` if `powi` (called `pown` in C) results in a fixed value specified in the C standard -/// (specifically, C23 annex F.10.4.6) when doing `base^exp`. Otherwise, returns `None`. -fn fixed_powi_float_value(base: IeeeFloat, exp: i32) -> Option> { - match (base.category(), exp) { - // x^0 = 1, if x is not a Signaling NaN - // FIXME(#4286): The C ecosystem is inconsistent with handling sNaN's, some return 1 others propogate - // the NaN. We should return either 1 or the NaN non-deterministically here. - // But for now, just handle them all the same. - (_, 0) => Some(IeeeFloat::::one()), - - _ => None, - } +/// Returns `Some(output)` if `powi` (called `pown` in C) results in a fixed value specified in the +/// C standard (specifically, C23 annex F.10.4.6) when doing `base^exp`. Otherwise, returns `None`. +fn fixed_powi_float_value( + ecx: &mut MiriInterpCx<'_>, + base: IeeeFloat, + exp: i32, +) -> Option> { + Some(match exp { + 0 => { + let one = IeeeFloat::::one(); + let rng = ecx.machine.rng.get_mut(); + let return_nan = ecx.machine.float_nondet && rng.random() && base.is_signaling(); + // For SNaN treatment, we are consistent with `powf`above. + // (We wouldn't have two, unlike powf all implementations seem to agree for powi, + // but for now we are maximally conservative.) + if return_nan { ecx.generate_nan(&[base]) } else { one } + } + + _ => return None, + }) } /// Given an floating-point operation and a floating-point value, clamps the result to the output diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs index 383579198bbe5..f21c6089a7b5b 100644 --- a/src/tools/miri/tests/pass/float.rs +++ b/src/tools/miri/tests/pass/float.rs @@ -1066,17 +1066,6 @@ pub fn libm() { assert_eq!((-1f32).powf(f32::NEG_INFINITY), 1.0); assert_eq!((-1f64).powf(f64::NEG_INFINITY), 1.0); - // For pow (powf in rust) the C standard says: - // x^0 = 1 for all x even a sNaN - // FIXME(#4286): this does not match the behavior of all implementations. - assert_eq!(SNAN_F32.powf(0.0), 1.0); - assert_eq!(SNAN_F64.powf(0.0), 1.0); - - // For pown (powi in rust) the C standard says: - // x^0 = 1 for all x even a sNaN - // FIXME(#4286): this does not match the behavior of all implementations. - assert_eq!(SNAN_F32.powi(0), 1.0); - assert_eq!(SNAN_F64.powi(0), 1.0); assert_eq!(0f32.powi(10), 0.0); assert_eq!(0f64.powi(100), 0.0); @@ -1500,4 +1489,18 @@ fn test_non_determinism() { test_operations_f32(12., 5.); test_operations_f64(19., 11.); test_operations_f128(25., 18.); + + + // SNaN^0 = (1 | NaN) + ensure_nondet(|| f32::powf(SNAN_F32, 0.0).is_nan()); + ensure_nondet(|| f64::powf(SNAN_F64, 0.0).is_nan()); + + // 1^SNaN = (1 | NaN) + ensure_nondet(|| f32::powf(1.0, SNAN_F32).is_nan()); + ensure_nondet(|| f64::powf(1.0, SNAN_F64).is_nan()); + + // same as powf (keep it consistent): + // x^SNaN = (1 | NaN) + ensure_nondet(|| f32::powi(SNAN_F32, 0).is_nan()); + ensure_nondet(|| f64::powi(SNAN_F64, 0).is_nan()); } diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index cadbbd58af591..3ffdb6868ac0a 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -260,6 +260,7 @@ fn test_f32() { // Intrinsics let nan = F32::nan(Neg, Quiet, 0).as_f32(); + let snan = F32::nan(Neg, Signaling, 1).as_f32(); check_all_outcomes( HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), || F32::from(f32::min(nan, nan)), @@ -313,6 +314,18 @@ fn test_f32() { HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), || F32::from(nan.ln_gamma().0), ); + check_all_outcomes( + HashSet::from_iter([ + F32::from(1.0), + F32::nan(Pos, Quiet, 0), + F32::nan(Neg, Quiet, 0), + F32::nan(Pos, Quiet, 1), + F32::nan(Neg, Quiet, 1), + F32::nan(Pos, Signaling, 1), + F32::nan(Neg, Signaling, 1), + ]), + || F32::from(snan.powf(0.0)), + ); } fn test_f64() { @@ -376,6 +389,7 @@ fn test_f64() { // Intrinsics let nan = F64::nan(Neg, Quiet, 0).as_f64(); + let snan = F64::nan(Neg, Signaling, 1).as_f64(); check_all_outcomes( HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), || F64::from(f64::min(nan, nan)), @@ -433,6 +447,18 @@ fn test_f64() { HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), || F64::from(nan.ln_gamma().0), ); + check_all_outcomes( + HashSet::from_iter([ + F64::from(1.0), + F64::nan(Pos, Quiet, 0), + F64::nan(Neg, Quiet, 0), + F64::nan(Pos, Quiet, 1), + F64::nan(Neg, Quiet, 1), + F64::nan(Pos, Signaling, 1), + F64::nan(Neg, Signaling, 1), + ]), + || F64::from(snan.powf(0.0)), + ); } fn test_casts() { diff --git a/src/tools/rust-installer/README.md b/src/tools/rust-installer/README.md index 99d8e5ca4cf1c..505ffe4093fcd 100644 --- a/src/tools/rust-installer/README.md +++ b/src/tools/rust-installer/README.md @@ -51,7 +51,7 @@ To combine installers. * Make install.sh not have to be customized, pull it's data from a config file. -* Be more resiliant to installation failures, particularly if the disk +* Be more resilient to installation failures, particularly if the disk is full. * Pre-install and post-uninstall scripts. * Allow components to depend on or contradict other components. diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 7e27e0258c2f5..4f9af6d53dd3b 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1368,7 +1368,6 @@ ui/infinite/issue-41731-infinite-macro-println.rs ui/intrinsics/issue-28575.rs ui/intrinsics/issue-84297-reifying-copy.rs ui/invalid/issue-114435-layout-type-err.rs -ui/issue-11881.rs ui/issue-15924.rs ui/issue-16822.rs ui/issues-71798.rs diff --git a/tests/crashes/132882.rs b/tests/crashes/132882.rs deleted file mode 100644 index 6b5e4dba803b0..0000000000000 --- a/tests/crashes/132882.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #132882 - -use std::ops::Add; - -pub trait Numoid -where - for &'a Self: Add, -{ -} - -pub fn compute(a: N) -> N { - &a + a -} diff --git a/tests/run-make/short-ice/rmake.rs b/tests/run-make/short-ice/rmake.rs index 483def62fc79b..dbe0f692aefb0 100644 --- a/tests/run-make/short-ice/rmake.rs +++ b/tests/run-make/short-ice/rmake.rs @@ -5,9 +5,12 @@ // See https://github.com/rust-lang/rust/issues/107910 //@ needs-target-std -//@ ignore-i686-pc-windows-msvc -// Reason: the assert_eq! on line 37 fails, almost seems like it missing debug info? -// Haven't been able to reproduce locally, but it happens on CI. +//@ ignore-windows-msvc +// +// - FIXME(#143198): On `i686-pc-windows-msvc`: the assert_eq! on line 37 fails, almost seems like +// it missing debug info? Haven't been able to reproduce locally, but it happens on CI. +// - FIXME(#143198): On `x86_64-pc-windows-msvc`: full backtrace sometimes do not contain matching +// count of short backtrace markers (e.g. 5x end marker, but 3x start marker). use run_make_support::rustc; diff --git a/tests/rustdoc-json/attrs/link_section_2021.rs b/tests/rustdoc-json/attrs/link_section_2021.rs new file mode 100644 index 0000000000000..a1312f4210b48 --- /dev/null +++ b/tests/rustdoc-json/attrs/link_section_2021.rs @@ -0,0 +1,6 @@ +//@ edition: 2021 +#![no_std] + +//@ is "$.index[?(@.name=='example')].attrs" '["#[link_section = \".text\"]"]' +#[link_section = ".text"] +pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/link_section_2024.rs b/tests/rustdoc-json/attrs/link_section_2024.rs new file mode 100644 index 0000000000000..edb028451a8e0 --- /dev/null +++ b/tests/rustdoc-json/attrs/link_section_2024.rs @@ -0,0 +1,9 @@ +//@ edition: 2024 +#![no_std] + +// Since the 2024 edition the link_section attribute must use the unsafe qualification. +// However, the unsafe qualification is not shown by rustdoc. + +//@ is "$.index[?(@.name=='example')].attrs" '["#[link_section = \".text\"]"]' +#[unsafe(link_section = ".text")] +pub extern "C" fn example() {} diff --git a/tests/ui/attributes/inner-attrs-impl-cfg.rs b/tests/ui/attributes/inner-attrs-impl-cfg.rs new file mode 100644 index 0000000000000..e7a5cfa9e2f53 --- /dev/null +++ b/tests/ui/attributes/inner-attrs-impl-cfg.rs @@ -0,0 +1,36 @@ +//! Test inner attributes (#![...]) behavior in impl blocks with cfg conditions. +//! +//! This test verifies that: +//! - Inner attributes can conditionally exclude entire impl blocks +//! - Regular attributes within impl blocks work independently +//! - Attribute parsing doesn't consume too eagerly + +//@ run-pass + +struct Foo; + +impl Foo { + #![cfg(false)] + + fn method(&self) -> bool { + false + } +} + +impl Foo { + #![cfg(not(FALSE))] + + // Check that we don't eat attributes too eagerly. + #[cfg(false)] + fn method(&self) -> bool { + false + } + + fn method(&self) -> bool { + true + } +} + +pub fn main() { + assert!(Foo.method()); +} diff --git a/tests/ui/codegen/maximal-hir-to-mir-coverage-flag.rs b/tests/ui/codegen/maximal-hir-to-mir-coverage-flag.rs new file mode 100644 index 0000000000000..64c31beba28c9 --- /dev/null +++ b/tests/ui/codegen/maximal-hir-to-mir-coverage-flag.rs @@ -0,0 +1,12 @@ +//! Test that -Z maximal-hir-to-mir-coverage flag is accepted. +//! +//! Original PR: https://github.com/rust-lang/rust/pull/105286 + +//@ compile-flags: -Zmaximal-hir-to-mir-coverage +//@ run-pass + +fn main() { + let x = 1; + let y = x + 1; + println!("{y}"); +} diff --git a/tests/ui/codegen/mono-respects-abi-alignment.rs b/tests/ui/codegen/mono-respects-abi-alignment.rs new file mode 100644 index 0000000000000..045d82b761fdc --- /dev/null +++ b/tests/ui/codegen/mono-respects-abi-alignment.rs @@ -0,0 +1,37 @@ +//! Test that monomorphization correctly distinguishes types with different ABI alignment. +//! +//! On x86_64-linux-gnu and similar platforms, structs get 8-byte "preferred" +//! alignment, but their "ABI" alignment (what actually matters for data layout) +//! is the largest alignment of any field. If monomorphization incorrectly uses +//! "preferred" alignment instead of "ABI" alignment, it might unify types `A` +//! and `B` even though `S` and `S` have field `t` at different offsets, +//! leading to incorrect method dispatch for `unwrap()`. + +//@ run-pass + +#[derive(Copy, Clone)] +struct S { + #[allow(dead_code)] + i: u8, + t: T, +} + +impl S { + fn unwrap(self) -> T { + self.t + } +} + +#[derive(Copy, Clone, PartialEq, Debug)] +struct A((u32, u32)); // Different ABI alignment than B + +#[derive(Copy, Clone, PartialEq, Debug)] +struct B(u64); // Different ABI alignment than A + +pub fn main() { + static CA: S = S { i: 0, t: A((13, 104)) }; + static CB: S = S { i: 0, t: B(31337) }; + + assert_eq!(CA.unwrap(), A((13, 104))); + assert_eq!(CB.unwrap(), B(31337)); +} diff --git a/tests/ui/codegen/msvc-opt-level-z-no-corruption.rs b/tests/ui/codegen/msvc-opt-level-z-no-corruption.rs new file mode 100644 index 0000000000000..ba97acec82228 --- /dev/null +++ b/tests/ui/codegen/msvc-opt-level-z-no-corruption.rs @@ -0,0 +1,37 @@ +//! Test that opt-level=z produces correct code on Windows MSVC targets. +//! +//! A previously outdated version of LLVM caused compilation failures and +//! generated invalid code on Windows specifically with optimization level `z`. +//! The bug manifested as corrupted base pointers due to incorrect register +//! usage in the generated assembly (e.g., `popl %esi` corrupting local variables). +//! After updating to a more recent LLVM version, this test ensures that +//! compilation and execution both succeed with opt-level=z. +//! +//! Regression test for . + +//@ ignore-cross-compile +// Reason: the compiled binary is executed +//@ only-windows +// Reason: the observed bug only occurred on Windows MSVC targets +//@ run-pass +//@ compile-flags: -C opt-level=z + +#![feature(test)] +extern crate test; + +fn foo(x: i32, y: i32) -> i64 { + (x + y) as i64 +} + +#[inline(never)] +fn bar() { + let _f = Box::new(0); + // This call used to trigger an LLVM bug in opt-level=z where the base + // pointer gets corrupted due to incorrect register allocation + let y: fn(i32, i32) -> i64 = test::black_box(foo); + test::black_box(y(1, 2)); +} + +fn main() { + bar(); +} diff --git a/tests/ui/compiletest-self-test/ui-test-missing-annotations-detection.rs b/tests/ui/compiletest-self-test/ui-test-missing-annotations-detection.rs new file mode 100644 index 0000000000000..3a110bdad3523 --- /dev/null +++ b/tests/ui/compiletest-self-test/ui-test-missing-annotations-detection.rs @@ -0,0 +1,9 @@ +//! Regression test checks UI tests without error annotations are detected as failing. +//! +//! This tests that when we forget to use any `//~ ERROR` comments whatsoever, +//! the test doesn't succeed +//! Originally created in https://github.com/rust-lang/rust/pull/56244 + +//@ should-fail + +fn main() {} diff --git a/tests/ui/derives/derive-Debug-enum-variants.rs b/tests/ui/derives/derive-Debug-enum-variants.rs new file mode 100644 index 0000000000000..26f527f766411 --- /dev/null +++ b/tests/ui/derives/derive-Debug-enum-variants.rs @@ -0,0 +1,30 @@ +//! Test that `#[derive(Debug)]` for enums correctly formats variant names. + +//@ run-pass + +#[derive(Debug)] +enum Foo { + A(usize), + C, +} + +#[derive(Debug)] +enum Bar { + D, +} + +pub fn main() { + // Test variant with data + let foo_a = Foo::A(22); + assert_eq!("A(22)".to_string(), format!("{:?}", foo_a)); + + if let Foo::A(value) = foo_a { + println!("Value: {}", value); // This needs to remove #[allow(dead_code)] + } + + // Test unit variant + assert_eq!("C".to_string(), format!("{:?}", Foo::C)); + + // Test unit variant from different enum + assert_eq!("D".to_string(), format!("{:?}", Bar::D)); +} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 1243ed5d8f486..02b9e2f06eed5 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -387,14 +387,6 @@ LL | #![link()] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 - | -LL | #![link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - warning: attribute should be applied to a function definition --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 | @@ -411,6 +403,14 @@ LL | #![link_name = "1900"] | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +warning: attribute should be applied to a function or static + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 + | +LL | #![link_section = "1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + warning: `#[must_use]` has no effect when applied to a module --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1 | diff --git a/tests/ui/logging-only-prints-once.rs b/tests/ui/fmt/debug-single-call.rs similarity index 73% rename from tests/ui/logging-only-prints-once.rs rename to tests/ui/fmt/debug-single-call.rs index bb8c29694b52a..b59a766c71a5a 100644 --- a/tests/ui/logging-only-prints-once.rs +++ b/tests/ui/fmt/debug-single-call.rs @@ -1,9 +1,12 @@ +//! Test that Debug::fmt is called exactly once during formatting. +//! +//! This is a regression test for PR https://github.com/rust-lang/rust/pull/10715 + //@ run-pass //@ needs-threads use std::cell::Cell; -use std::fmt; -use std::thread; +use std::{fmt, thread}; struct Foo(Cell); diff --git a/tests/ui/integral-indexing.rs b/tests/ui/indexing/indexing-integral-types.rs similarity index 54% rename from tests/ui/integral-indexing.rs rename to tests/ui/indexing/indexing-integral-types.rs index e20553af8a26f..a91696a6fd513 100644 --- a/tests/ui/integral-indexing.rs +++ b/tests/ui/indexing/indexing-integral-types.rs @@ -1,16 +1,20 @@ +//! Test that only usize can be used for indexing arrays and slices. + pub fn main() { let v: Vec = vec![0, 1, 2, 3, 4, 5]; let s: String = "abcdef".to_string(); + + // Valid indexing with usize v[3_usize]; v[3]; - v[3u8]; //~ ERROR the type `[isize]` cannot be indexed by `u8` - v[3i8]; //~ ERROR the type `[isize]` cannot be indexed by `i8` + v[3u8]; //~ ERROR the type `[isize]` cannot be indexed by `u8` + v[3i8]; //~ ERROR the type `[isize]` cannot be indexed by `i8` v[3u32]; //~ ERROR the type `[isize]` cannot be indexed by `u32` v[3i32]; //~ ERROR the type `[isize]` cannot be indexed by `i32` s.as_bytes()[3_usize]; s.as_bytes()[3]; - s.as_bytes()[3u8]; //~ ERROR the type `[u8]` cannot be indexed by `u8` - s.as_bytes()[3i8]; //~ ERROR the type `[u8]` cannot be indexed by `i8` + s.as_bytes()[3u8]; //~ ERROR the type `[u8]` cannot be indexed by `u8` + s.as_bytes()[3i8]; //~ ERROR the type `[u8]` cannot be indexed by `i8` s.as_bytes()[3u32]; //~ ERROR the type `[u8]` cannot be indexed by `u32` s.as_bytes()[3i32]; //~ ERROR the type `[u8]` cannot be indexed by `i32` } diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/indexing/indexing-integral-types.stderr similarity index 91% rename from tests/ui/integral-indexing.stderr rename to tests/ui/indexing/indexing-integral-types.stderr index 26253e078cb40..b63991ec2c4af 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/indexing/indexing-integral-types.stderr @@ -1,5 +1,5 @@ error[E0277]: the type `[isize]` cannot be indexed by `u8` - --> $DIR/integral-indexing.rs:6:7 + --> $DIR/indexing-integral-types.rs:10:7 | LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` @@ -11,7 +11,7 @@ LL | v[3u8]; = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i8` - --> $DIR/integral-indexing.rs:7:7 + --> $DIR/indexing-integral-types.rs:11:7 | LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` @@ -23,7 +23,7 @@ LL | v[3i8]; = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `u32` - --> $DIR/integral-indexing.rs:8:7 + --> $DIR/indexing-integral-types.rs:12:7 | LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` @@ -35,7 +35,7 @@ LL | v[3u32]; = note: required for `Vec` to implement `Index` error[E0277]: the type `[isize]` cannot be indexed by `i32` - --> $DIR/integral-indexing.rs:9:7 + --> $DIR/indexing-integral-types.rs:13:7 | LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` @@ -47,7 +47,7 @@ LL | v[3i32]; = note: required for `Vec` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u8` - --> $DIR/integral-indexing.rs:12:18 + --> $DIR/indexing-integral-types.rs:16:18 | LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` @@ -59,7 +59,7 @@ LL | s.as_bytes()[3u8]; = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i8` - --> $DIR/integral-indexing.rs:13:18 + --> $DIR/indexing-integral-types.rs:17:18 | LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` @@ -71,7 +71,7 @@ LL | s.as_bytes()[3i8]; = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `u32` - --> $DIR/integral-indexing.rs:14:18 + --> $DIR/indexing-integral-types.rs:18:18 | LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` @@ -83,7 +83,7 @@ LL | s.as_bytes()[3u32]; = note: required for `[u8]` to implement `Index` error[E0277]: the type `[u8]` cannot be indexed by `i32` - --> $DIR/integral-indexing.rs:15:18 + --> $DIR/indexing-integral-types.rs:19:18 | LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` diff --git a/tests/ui/inner-attrs-on-impl.rs b/tests/ui/inner-attrs-on-impl.rs deleted file mode 100644 index 1dce1cdd261af..0000000000000 --- a/tests/ui/inner-attrs-on-impl.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ run-pass - -struct Foo; - -impl Foo { - #![cfg(false)] - - fn method(&self) -> bool { false } -} - -impl Foo { - #![cfg(not(FALSE))] - - // check that we don't eat attributes too eagerly. - #[cfg(false)] - fn method(&self) -> bool { false } - - fn method(&self) -> bool { true } -} - - -pub fn main() { - assert!(Foo.method()); -} diff --git a/tests/ui/inner-module.rs b/tests/ui/inner-module.rs deleted file mode 100644 index 111f2cab857f2..0000000000000 --- a/tests/ui/inner-module.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass - -mod inner { - pub mod inner2 { - pub fn hello() { println!("hello, modular world"); } - } - pub fn hello() { inner2::hello(); } -} - -pub fn main() { inner::hello(); inner::inner2::hello(); } diff --git a/tests/ui/inner-static-type-parameter.rs b/tests/ui/inner-static-type-parameter.rs deleted file mode 100644 index a1994e7529cb7..0000000000000 --- a/tests/ui/inner-static-type-parameter.rs +++ /dev/null @@ -1,11 +0,0 @@ -// see #9186 - -enum Bar { What } //~ ERROR parameter `T` is never used - -fn foo() { - static a: Bar = Bar::What; -//~^ ERROR can't use generic parameters from outer item -} - -fn main() { -} diff --git a/tests/ui/auxiliary/msvc-data-only-lib.rs b/tests/ui/linkage-attr/auxiliary/msvc-static-data-import-lib.rs similarity index 100% rename from tests/ui/auxiliary/msvc-data-only-lib.rs rename to tests/ui/linkage-attr/auxiliary/msvc-static-data-import-lib.rs diff --git a/tests/ui/link-section.rs b/tests/ui/linkage-attr/link-section-placement.rs similarity index 93% rename from tests/ui/link-section.rs rename to tests/ui/linkage-attr/link-section-placement.rs index a8de8c2e1e77d..6a143bfedb451 100644 --- a/tests/ui/link-section.rs +++ b/tests/ui/linkage-attr/link-section-placement.rs @@ -1,8 +1,9 @@ +//! Test placement of functions and statics in custom link sections + //@ run-pass // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint #![allow(static_mut_refs)] - #![allow(non_upper_case_globals)] #[cfg(not(target_vendor = "apple"))] #[link_section = ".moretext"] diff --git a/tests/ui/linkage-attr/msvc-static-data-import.rs b/tests/ui/linkage-attr/msvc-static-data-import.rs new file mode 100644 index 0000000000000..e53eb404ef6ee --- /dev/null +++ b/tests/ui/linkage-attr/msvc-static-data-import.rs @@ -0,0 +1,18 @@ +//! Test that static data from external crates can be imported on MSVC targets. +//! +//! On Windows MSVC targets, static data from external rlibs must be imported +//! through `__imp_` stubs to ensure proper linking. Without this, +//! the linker would fail with "unresolved external symbol" errors when trying +//! to reference static data from another crate. +//! +//! Regression test for . +//! Fixed in . + +//@ run-pass +//@ aux-build:msvc-static-data-import-lib.rs + +extern crate msvc_static_data_import_lib; + +fn main() { + println!("The answer is {}!", msvc_static_data_import_lib::FOO); +} diff --git a/tests/ui/missing_debug_impls.rs b/tests/ui/lint/missing-debug-implementations-lint.rs similarity index 76% rename from tests/ui/missing_debug_impls.rs rename to tests/ui/lint/missing-debug-implementations-lint.rs index 3abc0706887b7..8a93f052f9c82 100644 --- a/tests/ui/missing_debug_impls.rs +++ b/tests/ui/lint/missing-debug-implementations-lint.rs @@ -1,3 +1,7 @@ +//! Test the `missing_debug_implementations` lint that warns about public types without Debug. +//! +//! See https://github.com/rust-lang/rust/issues/20855 + //@ compile-flags: --crate-type lib #![deny(missing_debug_implementations)] #![allow(unused)] @@ -10,7 +14,6 @@ pub enum A {} //~ ERROR type does not implement `Debug` pub enum B {} pub enum C {} - impl fmt::Debug for C { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { Ok(()) @@ -23,15 +26,14 @@ pub struct Foo; //~ ERROR type does not implement `Debug` pub struct Bar; pub struct Baz; - impl fmt::Debug for Baz { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { Ok(()) } } +// Private types should not trigger the lint struct PrivateStruct; - enum PrivateEnum {} #[derive(Debug)] diff --git a/tests/ui/missing_debug_impls.stderr b/tests/ui/lint/missing-debug-implementations-lint.stderr similarity index 74% rename from tests/ui/missing_debug_impls.stderr rename to tests/ui/lint/missing-debug-implementations-lint.stderr index 0538f207b4443..288ab981034e9 100644 --- a/tests/ui/missing_debug_impls.stderr +++ b/tests/ui/lint/missing-debug-implementations-lint.stderr @@ -1,17 +1,17 @@ error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation - --> $DIR/missing_debug_impls.rs:7:1 + --> $DIR/missing-debug-implementations-lint.rs:11:1 | LL | pub enum A {} | ^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/missing_debug_impls.rs:2:9 + --> $DIR/missing-debug-implementations-lint.rs:6:9 | LL | #![deny(missing_debug_implementations)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: type does not implement `Debug`; consider adding `#[derive(Debug)]` or a manual implementation - --> $DIR/missing_debug_impls.rs:20:1 + --> $DIR/missing-debug-implementations-lint.rs:23:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs index 407af40654e8b..bf94a42f6e0cf 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.rs +++ b/tests/ui/lint/unused/unused-attr-duplicate.rs @@ -102,4 +102,10 @@ pub fn no_mangle_test() {} #[used] //~ ERROR unused attribute static FOO: u32 = 0; +#[link_section = ".text"] +//~^ ERROR unused attribute +//~| WARN this was previously accepted +#[link_section = ".bss"] +pub extern "C" fn example() {} + fn main() {} diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index e8452465efc27..feae8528cf7ae 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -289,5 +289,18 @@ note: attribute also specified here LL | #[used] | ^^^^^^^ -error: aborting due to 23 previous errors +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:105:1 + | +LL | #[link_section = ".text"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:108:1 + | +LL | #[link_section = ".bss"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: aborting due to 24 previous errors diff --git a/tests/ui/log-err-phi.rs b/tests/ui/log-err-phi.rs deleted file mode 100644 index 1bb97758782b0..0000000000000 --- a/tests/ui/log-err-phi.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass - -pub fn main() { - if false { - println!("{}", "foobar"); - } -} diff --git a/tests/ui/log-knows-the-names-of-variants.rs b/tests/ui/log-knows-the-names-of-variants.rs deleted file mode 100644 index cb82cb4878a11..0000000000000 --- a/tests/ui/log-knows-the-names-of-variants.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ run-pass - -#![allow(non_camel_case_types)] -#![allow(dead_code)] -#[derive(Debug)] -enum foo { - a(usize), - b(String), - c, -} - -#[derive(Debug)] -enum bar { - d, e, f -} - -pub fn main() { - assert_eq!("a(22)".to_string(), format!("{:?}", foo::a(22))); - assert_eq!("c".to_string(), format!("{:?}", foo::c)); - assert_eq!("d".to_string(), format!("{:?}", bar::d)); -} diff --git a/tests/ui/loud_ui.rs b/tests/ui/loud_ui.rs deleted file mode 100644 index 2a73e49e17206..0000000000000 --- a/tests/ui/loud_ui.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ should-fail - -// this test ensures that when we forget to use -// any `//~ ERROR` comments whatsoever, that the test doesn't succeed - -fn main() {} diff --git a/tests/ui/maximal_mir_to_hir_coverage.rs b/tests/ui/maximal_mir_to_hir_coverage.rs deleted file mode 100644 index e57c83d007e07..0000000000000 --- a/tests/ui/maximal_mir_to_hir_coverage.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ compile-flags: -Zmaximal-hir-to-mir-coverage -//@ run-pass - -// Just making sure this flag is accepted and doesn't crash the compiler - -fn main() { - let x = 1; - let y = x + 1; - println!("{y}"); -} diff --git a/tests/ui/maybe-bounds.rs b/tests/ui/maybe-bounds.rs deleted file mode 100644 index 02ed45c656f1c..0000000000000 --- a/tests/ui/maybe-bounds.rs +++ /dev/null @@ -1,9 +0,0 @@ -trait Tr: ?Sized {} -//~^ ERROR `?Trait` is not permitted in supertraits - -type A1 = dyn Tr + (?Sized); -//~^ ERROR `?Trait` is not permitted in trait object types -type A2 = dyn for<'a> Tr + (?Sized); -//~^ ERROR `?Trait` is not permitted in trait object types - -fn main() {} diff --git a/tests/ui/method-output-diff-issue-127263.rs b/tests/ui/method-output-diff-issue-127263.rs deleted file mode 100644 index 85a903e245360..0000000000000 --- a/tests/ui/method-output-diff-issue-127263.rs +++ /dev/null @@ -1,8 +0,0 @@ -fn bar() {} -fn foo(x: i32) -> u32 { - 0 -} -fn main() { - let b: fn() -> u32 = bar; //~ ERROR mismatched types [E0308] - let f: fn(i32) = foo; //~ ERROR mismatched types [E0308] -} diff --git a/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.rs b/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.rs new file mode 100644 index 0000000000000..e28ca3e55b5ed --- /dev/null +++ b/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.rs @@ -0,0 +1,16 @@ +//! This test checks that when there's a type mismatch between a function item and +//! a function pointer, the error message focuses on the actual type difference +//! (return types, argument types) rather than the confusing "pointer vs item" distinction. +//! +//! See https://github.com/rust-lang/rust/issues/127263 + +fn bar() {} + +fn foo(x: i32) -> u32 { + 0 +} + +fn main() { + let b: fn() -> u32 = bar; //~ ERROR mismatched types [E0308] + let f: fn(i32) = foo; //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/method-output-diff-issue-127263.stderr b/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.stderr similarity index 87% rename from tests/ui/method-output-diff-issue-127263.stderr rename to tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.stderr index 35b86114f16d0..8d63f2ea2d3c0 100644 --- a/tests/ui/method-output-diff-issue-127263.stderr +++ b/tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/method-output-diff-issue-127263.rs:6:26 + --> $DIR/fn-pointer-mismatch-diagnostics.rs:14:26 | LL | let b: fn() -> u32 = bar; | ----------- ^^^ expected fn pointer, found fn item @@ -10,7 +10,7 @@ LL | let b: fn() -> u32 = bar; found fn item `fn() -> () {bar}` error[E0308]: mismatched types - --> $DIR/method-output-diff-issue-127263.rs:7:22 + --> $DIR/fn-pointer-mismatch-diagnostics.rs:15:22 | LL | let f: fn(i32) = foo; | ------- ^^^ expected fn pointer, found fn item diff --git a/tests/ui/integral-variable-unification-error.rs b/tests/ui/mismatched_types/int-float-type-mismatch.rs similarity index 65% rename from tests/ui/integral-variable-unification-error.rs rename to tests/ui/mismatched_types/int-float-type-mismatch.rs index 8d1621321e8e6..b45d02730d986 100644 --- a/tests/ui/integral-variable-unification-error.rs +++ b/tests/ui/mismatched_types/int-float-type-mismatch.rs @@ -1,3 +1,6 @@ +//! Check that a type mismatch error is reported when trying +//! to unify a {float} value assignment to an {integer} variable. + fn main() { let mut x //~ NOTE expected due to the type of this binding = diff --git a/tests/ui/integral-variable-unification-error.stderr b/tests/ui/mismatched_types/int-float-type-mismatch.stderr similarity index 87% rename from tests/ui/integral-variable-unification-error.stderr rename to tests/ui/mismatched_types/int-float-type-mismatch.stderr index 1caa6042fd206..43b8609a49d7c 100644 --- a/tests/ui/integral-variable-unification-error.stderr +++ b/tests/ui/mismatched_types/int-float-type-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/integral-variable-unification-error.rs:5:9 + --> $DIR/int-float-type-mismatch.rs:8:9 | LL | let mut x | ----- expected due to the type of this binding diff --git a/tests/ui/mod-subitem-as-enum-variant.rs b/tests/ui/mod-subitem-as-enum-variant.rs deleted file mode 100644 index 959024c46f4ff..0000000000000 --- a/tests/ui/mod-subitem-as-enum-variant.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod Mod { - pub struct FakeVariant(pub T); -} - -fn main() { - Mod::FakeVariant::(0); - Mod::::FakeVariant(0); - //~^ ERROR type arguments are not allowed on module `Mod` [E0109] -} diff --git a/tests/ui/modules/nested-modules-basic.rs b/tests/ui/modules/nested-modules-basic.rs new file mode 100644 index 0000000000000..12eccec280863 --- /dev/null +++ b/tests/ui/modules/nested-modules-basic.rs @@ -0,0 +1,19 @@ +//! Basic test for nested module functionality and path resolution + +//@ run-pass + +mod inner { + pub mod inner2 { + pub fn hello() { + println!("hello, modular world"); + } + } + pub fn hello() { + inner2::hello(); + } +} + +pub fn main() { + inner::hello(); + inner::inner2::hello(); +} diff --git a/tests/ui/monomorphize-abi-alignment.rs b/tests/ui/monomorphize-abi-alignment.rs deleted file mode 100644 index 62df1aca357d7..0000000000000 --- a/tests/ui/monomorphize-abi-alignment.rs +++ /dev/null @@ -1,35 +0,0 @@ -//@ run-pass - -#![allow(non_upper_case_globals)] -#![allow(dead_code)] -/*! - * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment, - * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment - * of any field. (Also, `u64` has 8-byte ABI alignment; this is not always true). - * - * On such platforms, if monomorphize uses the "preferred" alignment, then it will unify - * `A` and `B`, even though `S` and `S` have the field `t` at different offsets, - * and apply the wrong instance of the method `unwrap`. - */ - -#[derive(Copy, Clone)] -struct S { i:u8, t:T } - -impl S { - fn unwrap(self) -> T { - self.t - } -} - -#[derive(Copy, Clone, PartialEq, Debug)] -struct A((u32, u32)); - -#[derive(Copy, Clone, PartialEq, Debug)] -struct B(u64); - -pub fn main() { - static Ca: S = S { i: 0, t: A((13, 104)) }; - static Cb: S = S { i: 0, t: B(31337) }; - assert_eq!(Ca.unwrap(), A((13, 104))); - assert_eq!(Cb.unwrap(), B(31337)); -} diff --git a/tests/ui/msvc-data-only.rs b/tests/ui/msvc-data-only.rs deleted file mode 100644 index 15d799085fecc..0000000000000 --- a/tests/ui/msvc-data-only.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-pass -//@ aux-build:msvc-data-only-lib.rs - -extern crate msvc_data_only_lib; - -fn main() { - println!("The answer is {} !", msvc_data_only_lib::FOO); -} diff --git a/tests/ui/msvc-opt-minsize.rs b/tests/ui/msvc-opt-minsize.rs deleted file mode 100644 index c1be168a05dde..0000000000000 --- a/tests/ui/msvc-opt-minsize.rs +++ /dev/null @@ -1,31 +0,0 @@ -// A previously outdated version of LLVM caused compilation failures on Windows -// specifically with optimization level `z`. After the update to a more recent LLVM -// version, this test checks that compilation and execution both succeed. -// See https://github.com/rust-lang/rust/issues/45034 - -//@ ignore-cross-compile -// Reason: the compiled binary is executed -//@ only-windows -// Reason: the observed bug only occurs on Windows -//@ run-pass -//@ compile-flags: -C opt-level=z - -#![feature(test)] -extern crate test; - -fn foo(x: i32, y: i32) -> i64 { - (x + y) as i64 -} - -#[inline(never)] -fn bar() { - let _f = Box::new(0); - // This call used to trigger an LLVM bug in opt-level z where the base - // pointer gets corrupted, see issue #45034 - let y: fn(i32, i32) -> i64 = test::black_box(foo); - test::black_box(y(1, 2)); -} - -fn main() { - bar(); -} diff --git a/tests/ui/multibyte.rs b/tests/ui/multibyte.rs deleted file mode 100644 index d585a791fb9c1..0000000000000 --- a/tests/ui/multibyte.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -// - -// Test that multibyte characters don't crash the compiler -pub fn main() { - println!("마이너스 사인이 없으면"); -} diff --git a/tests/ui/multiline-comment.rs b/tests/ui/multiline-comment.rs deleted file mode 100644 index 9817488203221..0000000000000 --- a/tests/ui/multiline-comment.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ run-pass - -/* - * This is a multi-line oldcomment. - */ -pub fn main() { } diff --git a/tests/ui/parser/multiline-comments-basic.rs b/tests/ui/parser/multiline-comments-basic.rs new file mode 100644 index 0000000000000..1aa2a531f5cc2 --- /dev/null +++ b/tests/ui/parser/multiline-comments-basic.rs @@ -0,0 +1,10 @@ +//! Test that basic multiline comments are parsed correctly. +//! +//! Feature implementation test for . + +//@ run-pass + +/* + * This is a multi-line comment. + */ +pub fn main() {} diff --git a/tests/ui/parser/unicode-multibyte-chars-no-ice.rs b/tests/ui/parser/unicode-multibyte-chars-no-ice.rs new file mode 100644 index 0000000000000..b1bb0c66ae2bb --- /dev/null +++ b/tests/ui/parser/unicode-multibyte-chars-no-ice.rs @@ -0,0 +1,9 @@ +//! Test that multibyte Unicode characters don't crash the compiler. +//! +//! Regression test for . + +//@ run-pass + +pub fn main() { + println!("마이너스 사인이 없으면"); +} diff --git a/tests/ui/max-min-classes.rs b/tests/ui/resolve/struct-function-same-name.rs similarity index 84% rename from tests/ui/max-min-classes.rs rename to tests/ui/resolve/struct-function-same-name.rs index 338a3156a9a93..bb2837d7ca6f9 100644 --- a/tests/ui/max-min-classes.rs +++ b/tests/ui/resolve/struct-function-same-name.rs @@ -1,3 +1,5 @@ +//! Test that a struct and function can have the same name +//! //@ run-pass #![allow(non_snake_case)] @@ -23,7 +25,7 @@ impl Product for Foo { } fn Foo(x: isize, y: isize) -> Foo { - Foo { x: x, y: y } + Foo { x, y } } pub fn main() { diff --git a/tests/ui/lexical-scoping.rs b/tests/ui/resolve/type-param-local-var-shadowing.rs similarity index 51% rename from tests/ui/lexical-scoping.rs rename to tests/ui/resolve/type-param-local-var-shadowing.rs index f858369f7ce7e..e08379e2acff9 100644 --- a/tests/ui/lexical-scoping.rs +++ b/tests/ui/resolve/type-param-local-var-shadowing.rs @@ -1,8 +1,13 @@ +//! Test that items in subscopes correctly shadow type parameters and local variables +//! +//! Regression test for https://github.com/rust-lang/rust/issues/23880 + //@ run-pass -// Tests that items in subscopes can shadow type parameters and local variables (see issue #23880). #![allow(unused)] -struct Foo { x: Box } +struct Foo { + x: Box, +} impl Foo { fn foo(&self) { type Bar = i32; diff --git a/tests/ui/statics/static-generic-param-soundness.rs b/tests/ui/statics/static-generic-param-soundness.rs new file mode 100644 index 0000000000000..aabcca514d317 --- /dev/null +++ b/tests/ui/statics/static-generic-param-soundness.rs @@ -0,0 +1,20 @@ +//! Originally, inner statics in generic functions were generated only once, causing the same +//! static to be shared across all generic instantiations. This created a soundness hole where +//! different types could be coerced through thread-local storage in safe code. +//! +//! This test checks that generic parameters from outer scopes cannot be used in inner statics, +//! preventing this soundness issue. +//! +//! See https://github.com/rust-lang/rust/issues/9186 + +enum Bar { + //~^ ERROR parameter `T` is never used + What, +} + +fn foo() { + static a: Bar = Bar::What; + //~^ ERROR can't use generic parameters from outer item +} + +fn main() {} diff --git a/tests/ui/inner-static-type-parameter.stderr b/tests/ui/statics/static-generic-param-soundness.stderr similarity index 86% rename from tests/ui/inner-static-type-parameter.stderr rename to tests/ui/statics/static-generic-param-soundness.stderr index 88d33b44c5931..47554c7fcb0f0 100644 --- a/tests/ui/inner-static-type-parameter.stderr +++ b/tests/ui/statics/static-generic-param-soundness.stderr @@ -1,5 +1,5 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/inner-static-type-parameter.rs:6:19 + --> $DIR/static-generic-param-soundness.rs:16:19 | LL | fn foo() { | - type parameter from outer item @@ -9,9 +9,9 @@ LL | static a: Bar = Bar::What; = note: a `static` is a separate item from the item that contains it error[E0392]: type parameter `T` is never used - --> $DIR/inner-static-type-parameter.rs:3:10 + --> $DIR/static-generic-param-soundness.rs:10:10 | -LL | enum Bar { What } +LL | enum Bar { | ^ unused type parameter | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.rs b/tests/ui/traits/dispatch-from-dyn-invalid-impls.rs similarity index 52% rename from tests/ui/invalid_dispatch_from_dyn_impls.rs rename to tests/ui/traits/dispatch-from-dyn-invalid-impls.rs index b1d4b261babee..f5f66ca69cfc1 100644 --- a/tests/ui/invalid_dispatch_from_dyn_impls.rs +++ b/tests/ui/traits/dispatch-from-dyn-invalid-impls.rs @@ -1,20 +1,30 @@ +//! Test various invalid implementations of DispatchFromDyn trait. +//! +//! DispatchFromDyn is a special trait used by the compiler for dyn-compatible dynamic dispatch. +//! This checks that the compiler correctly rejects invalid implementations: +//! - Structs with extra non-coercible fields +//! - Structs with multiple pointer fields +//! - Structs with no coercible fields +//! - Structs with repr(C) or other incompatible representations +//! - Structs with over-aligned fields + #![feature(unsize, dispatch_from_dyn)] -use std::{ - ops::DispatchFromDyn, - marker::{Unsize, PhantomData}, -}; +use std::marker::{PhantomData, Unsize}; +use std::ops::DispatchFromDyn; +// Extra field prevents DispatchFromDyn struct WrapperWithExtraField(T, i32); impl DispatchFromDyn> for WrapperWithExtraField //~^ ERROR [E0378] where - T: DispatchFromDyn, -{} - + T: DispatchFromDyn +{ +} -struct MultiplePointers{ +// Multiple pointer fields create ambiguous coercion +struct MultiplePointers { ptr1: *const T, ptr2: *const T, } @@ -22,10 +32,11 @@ struct MultiplePointers{ impl DispatchFromDyn> for MultiplePointers //~^ ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced where - T: Unsize, -{} - + T: Unsize +{ +} +// No coercible fields (only PhantomData) struct NothingToCoerce { data: PhantomData, } @@ -33,23 +44,28 @@ struct NothingToCoerce { impl DispatchFromDyn> for NothingToCoerce {} //~^ ERROR implementing `DispatchFromDyn` requires a field to be coerced +// repr(C) is incompatible with DispatchFromDyn #[repr(C)] struct HasReprC(Box); impl DispatchFromDyn> for HasReprC //~^ ERROR [E0378] where - T: Unsize, -{} + T: Unsize +{ +} +// Over-aligned fields are incompatible #[repr(align(64))] struct OverAlignedZst; + struct OverAligned(Box, OverAlignedZst); impl DispatchFromDyn> for OverAligned //~^ ERROR [E0378] - where - T: Unsize, -{} +where + T: Unsize +{ +} fn main() {} diff --git a/tests/ui/invalid_dispatch_from_dyn_impls.stderr b/tests/ui/traits/dispatch-from-dyn-invalid-impls.stderr similarity index 77% rename from tests/ui/invalid_dispatch_from_dyn_impls.stderr rename to tests/ui/traits/dispatch-from-dyn-invalid-impls.stderr index 93ec6bbe0896f..676da0ce81fb1 100644 --- a/tests/ui/invalid_dispatch_from_dyn_impls.stderr +++ b/tests/ui/traits/dispatch-from-dyn-invalid-impls.stderr @@ -1,25 +1,25 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else - --> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:19:1 | LL | / impl DispatchFromDyn> for WrapperWithExtraField LL | | LL | | where -LL | | T: DispatchFromDyn, - | |__________________________^ +LL | | T: DispatchFromDyn + | |_________________________^ | = note: extra field `1` of type `i32` is not allowed error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced - --> $DIR/invalid_dispatch_from_dyn_impls.rs:22:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:32:1 | LL | / impl DispatchFromDyn> for MultiplePointers LL | | LL | | where -LL | | T: Unsize, - | |_________________^ +LL | | T: Unsize + | |________________^ | note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced - --> $DIR/invalid_dispatch_from_dyn_impls.rs:18:5 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:28:5 | LL | ptr1: *const T, | ^^^^^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | ptr2: *const T, | ^^^^^^^^^^^^^^ error[E0374]: implementing `DispatchFromDyn` requires a field to be coerced - --> $DIR/invalid_dispatch_from_dyn_impls.rs:33:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:44:1 | LL | impl DispatchFromDyn> for NothingToCoerce {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,22 +35,22 @@ LL | impl DispatchFromDyn> for NothingT = note: expected a single field to be coerced, none found error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` - --> $DIR/invalid_dispatch_from_dyn_impls.rs:39:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:51:1 | LL | / impl DispatchFromDyn> for HasReprC LL | | LL | | where -LL | | T: Unsize, - | |_________________^ +LL | | T: Unsize + | |________________^ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else - --> $DIR/invalid_dispatch_from_dyn_impls.rs:49:1 + --> $DIR/dispatch-from-dyn-invalid-impls.rs:64:1 | LL | / impl DispatchFromDyn> for OverAligned LL | | -LL | | where -LL | | T: Unsize, - | |_____________________^ +LL | | where +LL | | T: Unsize + | |________________^ | = note: extra field `1` of type `OverAlignedZst` is not allowed diff --git a/tests/ui/issue-11881.rs b/tests/ui/traits/encoder-trait-bounds-regression.rs similarity index 76% rename from tests/ui/issue-11881.rs rename to tests/ui/traits/encoder-trait-bounds-regression.rs index 1abe079720337..292b921cdf761 100644 --- a/tests/ui/issue-11881.rs +++ b/tests/ui/traits/encoder-trait-bounds-regression.rs @@ -1,14 +1,23 @@ +//! Regression test for issue #11881 +//! +//! Originally, the compiler would ICE when trying to parameterize on certain encoder types +//! due to issues with higher-ranked trait bounds and lifetime inference. This test checks +//! that various encoder patterns work correctly: +//! - Generic encoders with associated error types +//! - Higher-ranked trait bounds (for<'r> Encodable>) +//! - Multiple encoder implementations for the same type +//! - Polymorphic encoding functions + //@ run-pass #![allow(unused_must_use)] #![allow(dead_code)] #![allow(unused_imports)] -use std::fmt; -use std::io::prelude::*; use std::io::Cursor; -use std::slice; +use std::io::prelude::*; use std::marker::PhantomData; +use std::{fmt, slice}; trait Encoder { type Error; @@ -45,7 +54,6 @@ impl Encoder for OpaqueEncoder { type Error = (); } - struct Foo { baz: bool, } @@ -69,7 +77,6 @@ impl Encodable for Bar { enum WireProtocol { JSON, Opaque, - // ... } fn encode_json Encodable>>(val: &T, wr: &mut Cursor>) { diff --git a/tests/ui/traits/eval-caching-error-region.rs b/tests/ui/traits/eval-caching-error-region.rs new file mode 100644 index 0000000000000..831b5ab80c1ef --- /dev/null +++ b/tests/ui/traits/eval-caching-error-region.rs @@ -0,0 +1,23 @@ +// Regression test for #132882. + +use std::ops::Add; + +pub trait Numoid: Sized +where + &'missing Self: Add, + //~^ ERROR use of undeclared lifetime name `'missing` +{ +} + +// Proving `N: Numoid`'s well-formedness causes us to have to prove `&'missing N: Add`. +// Since `'missing` is a region error, that will lead to us consider the predicate to hold, +// since it references errors. Since the freshener turns error regions into fresh regions, +// this means that subsequent lookups of `&'?0 N: Add` will also hit this cache entry +// even if candidate assembly can't assemble anything for `&'?0 N: Add` anyways. This +// led to an ICE. +pub fn compute(a: N) { + let _ = &a + a; + //~^ ERROR cannot add `N` to `&N` +} + +fn main() {} diff --git a/tests/ui/traits/eval-caching-error-region.stderr b/tests/ui/traits/eval-caching-error-region.stderr new file mode 100644 index 0000000000000..6365d242d2e6b --- /dev/null +++ b/tests/ui/traits/eval-caching-error-region.stderr @@ -0,0 +1,33 @@ +error[E0261]: use of undeclared lifetime name `'missing` + --> $DIR/eval-caching-error-region.rs:7:6 + | +LL | &'missing Self: Add, + | ^^^^^^^^ undeclared lifetime + | + = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html +help: consider making the bound lifetime-generic with a new `'missing` lifetime + | +LL | for<'missing> &'missing Self: Add, + | +++++++++++++ +help: consider introducing lifetime `'missing` here + | +LL | pub trait Numoid<'missing>: Sized + | ++++++++++ + +error[E0369]: cannot add `N` to `&N` + --> $DIR/eval-caching-error-region.rs:19:16 + | +LL | let _ = &a + a; + | -- ^ - N + | | + | &N + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub fn compute(a: N) where &N: Add { + | ++++++++++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0261, E0369. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs new file mode 100644 index 0000000000000..04963c98765e9 --- /dev/null +++ b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs @@ -0,0 +1,18 @@ +//! Test that ?Trait bounds are forbidden in supertraits and trait object types. +//! +//! While `?Sized` and other maybe bounds are allowed in type parameter bounds and where clauses, +//! they are explicitly forbidden in certain syntactic positions: +//! - As supertraits in trait definitions +//! - In trait object type expressions +//! +//! See https://github.com/rust-lang/rust/issues/20503 + +trait Tr: ?Sized {} +//~^ ERROR `?Trait` is not permitted in supertraits + +type A1 = dyn Tr + (?Sized); +//~^ ERROR `?Trait` is not permitted in trait object types +type A2 = dyn for<'a> Tr + (?Sized); +//~^ ERROR `?Trait` is not permitted in trait object types + +fn main() {} diff --git a/tests/ui/maybe-bounds.stderr b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr similarity index 85% rename from tests/ui/maybe-bounds.stderr rename to tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr index 230d11fd0ae66..bd0baa580bdf5 100644 --- a/tests/ui/maybe-bounds.stderr +++ b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr @@ -1,5 +1,5 @@ error[E0658]: `?Trait` is not permitted in supertraits - --> $DIR/maybe-bounds.rs:1:11 + --> $DIR/maybe-trait-bounds-forbidden-locations.rs:10:11 | LL | trait Tr: ?Sized {} | ^^^^^^ @@ -9,7 +9,7 @@ LL | trait Tr: ?Sized {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bounds.rs:4:20 + --> $DIR/maybe-trait-bounds-forbidden-locations.rs:13:20 | LL | type A1 = dyn Tr + (?Sized); | ^^^^^^^^ @@ -18,7 +18,7 @@ LL | type A1 = dyn Tr + (?Sized); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bounds.rs:6:28 + --> $DIR/maybe-trait-bounds-forbidden-locations.rs:15:28 | LL | type A2 = dyn for<'a> Tr + (?Sized); | ^^^^^^^^ diff --git a/tests/ui/type-alias-enum-variants/module-type-args-error.rs b/tests/ui/type-alias-enum-variants/module-type-args-error.rs new file mode 100644 index 0000000000000..9f7dae4f4f514 --- /dev/null +++ b/tests/ui/type-alias-enum-variants/module-type-args-error.rs @@ -0,0 +1,16 @@ +//! Test that type arguments are properly rejected on modules. +//! +//! Related PR: https://github.com/rust-lang/rust/pull/56225 (RFC 2338 implementation) + +mod Mod { + pub struct FakeVariant(pub T); +} + +fn main() { + // This should work fine - normal generic struct constructor + Mod::FakeVariant::(0); + + // This should error - type arguments not allowed on modules + Mod::::FakeVariant(0); + //~^ ERROR type arguments are not allowed on module `Mod` [E0109] +} diff --git a/tests/ui/mod-subitem-as-enum-variant.stderr b/tests/ui/type-alias-enum-variants/module-type-args-error.stderr similarity index 86% rename from tests/ui/mod-subitem-as-enum-variant.stderr rename to tests/ui/type-alias-enum-variants/module-type-args-error.stderr index 92d972eba42bf..4c59d19eaa783 100644 --- a/tests/ui/mod-subitem-as-enum-variant.stderr +++ b/tests/ui/type-alias-enum-variants/module-type-args-error.stderr @@ -1,5 +1,5 @@ error[E0109]: type arguments are not allowed on module `Mod` - --> $DIR/mod-subitem-as-enum-variant.rs:7:11 + --> $DIR/module-type-args-error.rs:14:11 | LL | Mod::::FakeVariant(0); | --- ^^^ type argument not allowed