| author | bors <bors@rust-lang.org> 2025-06-16 18:20:05 UTC |
| committer | bors <bors@rust-lang.org> 2025-06-16 18:20:05 UTC |
| log | 45acf54eea118ed27927282b5e0bfdcd80b7987c |
| tree | e876174d258caa3d3ab3233f3e6a0697b9601157 |
| parent | 3bc767e1a215c4bf8f099b32e84edb85780591b1 |
| parent | b1ba2cdf41da538fa2195ff439cc6b82723b9474 |
Rollup of 8 pull requests
Successful merges:
- rust-lang/rust#139340 (Fix RISC-V C function ABI when passing/returning structs containing floats)
- rust-lang/rust#142341 (Don't suggest converting `///` to `//` when expecting `,`)
- rust-lang/rust#142414 (ignore `run-make` tests that need `std` on targets without `std`)
- rust-lang/rust#142498 (Port `#[rustc_as_ptr]` to the new attribute system)
- rust-lang/rust#142554 (Fix `PathSource` lifetimes.)
- rust-lang/rust#142562 (Update the `backtrace` submodule)
- rust-lang/rust#142565 (Test naked asm for wasm32-unknown-unknown)
- rust-lang/rust#142573 (`fn candidate_is_applicable` to method)
r? `@ghost`
`@rustbot` modify labels: rollup135 files changed, 913 insertions(+), 239 deletions(-)
compiler/rustc_attr_data_structures/src/attributes.rs+3| ... | ... | @@ -188,6 +188,9 @@ pub enum AttributeKind { |
| 188 | 188 | /// Represents `#[allow_internal_unstable]`. |
| 189 | 189 | AllowInternalUnstable(ThinVec<(Symbol, Span)>), |
| 190 | 190 | |
| 191 | /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). | |
| 192 | AsPtr(Span), | |
| 193 | ||
| 191 | 194 | /// Represents `#[rustc_default_body_unstable]`. |
| 192 | 195 | BodyStability { |
| 193 | 196 | stability: DefaultBodyStability, |
compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | use rustc_attr_data_structures::AttributeKind; | |
| 2 | use rustc_span::{Symbol, sym}; | |
| 3 | ||
| 4 | use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; | |
| 5 | use crate::context::{AcceptContext, Stage}; | |
| 6 | use crate::parser::ArgParser; | |
| 7 | ||
| 8 | pub(crate) struct AsPtrParser; | |
| 9 | ||
| 10 | impl<S: Stage> SingleAttributeParser<S> for AsPtrParser { | |
| 11 | const PATH: &[Symbol] = &[sym::rustc_as_ptr]; | |
| 12 | ||
| 13 | const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst; | |
| 14 | ||
| 15 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; | |
| 16 | ||
| 17 | fn convert(cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> { | |
| 18 | // FIXME: check that there's no args (this is currently checked elsewhere) | |
| 19 | Some(AttributeKind::AsPtr(cx.attr_span)) | |
| 20 | } | |
| 21 | } |
compiler/rustc_attr_parsing/src/attributes/mod.rs+1| ... | ... | @@ -29,6 +29,7 @@ pub(crate) mod allow_unstable; |
| 29 | 29 | pub(crate) mod cfg; |
| 30 | 30 | pub(crate) mod confusables; |
| 31 | 31 | pub(crate) mod deprecation; |
| 32 | pub(crate) mod lint_helpers; | |
| 32 | 33 | pub(crate) mod repr; |
| 33 | 34 | pub(crate) mod stability; |
| 34 | 35 | pub(crate) mod transparency; |
compiler/rustc_attr_parsing/src/context.rs+2| ... | ... | @@ -18,6 +18,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; |
| 18 | 18 | use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; |
| 19 | 19 | use crate::attributes::confusables::ConfusablesParser; |
| 20 | 20 | use crate::attributes::deprecation::DeprecationParser; |
| 21 | use crate::attributes::lint_helpers::AsPtrParser; | |
| 21 | 22 | use crate::attributes::repr::ReprParser; |
| 22 | 23 | use crate::attributes::stability::{ |
| 23 | 24 | BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, |
| ... | ... | @@ -102,6 +103,7 @@ attribute_parsers!( |
| 102 | 103 | // tidy-alphabetical-end |
| 103 | 104 | |
| 104 | 105 | // tidy-alphabetical-start |
| 106 | Single<AsPtrParser>, | |
| 105 | 107 | Single<ConstStabilityIndirectParser>, |
| 106 | 108 | Single<DeprecationParser>, |
| 107 | 109 | Single<TransparencyParser>, |
compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs+42-24| ... | ... | @@ -40,7 +40,18 @@ fn apply_attrs_to_abi_param(param: AbiParam, arg_attrs: ArgAttributes) -> AbiPar |
| 40 | 40 | } |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> { | |
| 43 | fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[(Size, AbiParam); 2]> { | |
| 44 | if let Some(offset_from_start) = cast.rest_offset { | |
| 45 | assert!(cast.prefix[1..].iter().all(|p| p.is_none())); | |
| 46 | assert_eq!(cast.rest.unit.size, cast.rest.total); | |
| 47 | let first = cast.prefix[0].unwrap(); | |
| 48 | let second = cast.rest.unit; | |
| 49 | return smallvec![ | |
| 50 | (Size::ZERO, reg_to_abi_param(first)), | |
| 51 | (offset_from_start, reg_to_abi_param(second)) | |
| 52 | ]; | |
| 53 | } | |
| 54 | ||
| 44 | 55 | let (rest_count, rem_bytes) = if cast.rest.unit.size.bytes() == 0 { |
| 45 | 56 | (0, 0) |
| 46 | 57 | } else { |
| ... | ... | @@ -55,25 +66,32 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> { |
| 55 | 66 | // different types in Cranelift IR. Instead a single array of primitive types is used. |
| 56 | 67 | |
| 57 | 68 | // Create list of fields in the main structure |
| 58 | let mut args = cast | |
| 69 | let args = cast | |
| 59 | 70 | .prefix |
| 60 | 71 | .iter() |
| 61 | 72 | .flatten() |
| 62 | 73 | .map(|&reg| reg_to_abi_param(reg)) |
| 63 | .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))) | |
| 64 | .collect::<SmallVec<_>>(); | |
| 74 | .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))); | |
| 75 | ||
| 76 | let mut res = SmallVec::new(); | |
| 77 | let mut offset = Size::ZERO; | |
| 78 | ||
| 79 | for arg in args { | |
| 80 | res.push((offset, arg)); | |
| 81 | offset += Size::from_bytes(arg.value_type.bytes()); | |
| 82 | } | |
| 65 | 83 | |
| 66 | 84 | // Append final integer |
| 67 | 85 | if rem_bytes != 0 { |
| 68 | 86 | // Only integers can be really split further. |
| 69 | 87 | assert_eq!(cast.rest.unit.kind, RegKind::Integer); |
| 70 | args.push(reg_to_abi_param(Reg { | |
| 71 | kind: RegKind::Integer, | |
| 72 | size: Size::from_bytes(rem_bytes), | |
| 73 | })); | |
| 88 | res.push(( | |
| 89 | offset, | |
| 90 | reg_to_abi_param(Reg { kind: RegKind::Integer, size: Size::from_bytes(rem_bytes) }), | |
| 91 | )); | |
| 74 | 92 | } |
| 75 | 93 | |
| 76 | args | |
| 94 | res | |
| 77 | 95 | } |
| 78 | 96 | |
| 79 | 97 | impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { |
| ... | ... | @@ -104,7 +122,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { |
| 104 | 122 | }, |
| 105 | 123 | PassMode::Cast { ref cast, pad_i32 } => { |
| 106 | 124 | assert!(!pad_i32, "padding support not yet implemented"); |
| 107 | cast_target_to_abi_params(cast) | |
| 125 | cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect() | |
| 108 | 126 | } |
| 109 | 127 | PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { |
| 110 | 128 | if on_stack { |
| ... | ... | @@ -160,9 +178,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { |
| 160 | 178 | } |
| 161 | 179 | _ => unreachable!("{:?}", self.layout.backend_repr), |
| 162 | 180 | }, |
| 163 | PassMode::Cast { ref cast, .. } => { | |
| 164 | (None, cast_target_to_abi_params(cast).into_iter().collect()) | |
| 165 | } | |
| 181 | PassMode::Cast { ref cast, .. } => ( | |
| 182 | None, | |
| 183 | cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect(), | |
| 184 | ), | |
| 166 | 185 | PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { |
| 167 | 186 | assert!(!on_stack); |
| 168 | 187 | ( |
| ... | ... | @@ -187,12 +206,14 @@ pub(super) fn to_casted_value<'tcx>( |
| 187 | 206 | ) -> SmallVec<[Value; 2]> { |
| 188 | 207 | let (ptr, meta) = arg.force_stack(fx); |
| 189 | 208 | assert!(meta.is_none()); |
| 190 | let mut offset = 0; | |
| 191 | 209 | cast_target_to_abi_params(cast) |
| 192 | 210 | .into_iter() |
| 193 | .map(|param| { | |
| 194 | let val = ptr.offset_i64(fx, offset).load(fx, param.value_type, MemFlags::new()); | |
| 195 | offset += i64::from(param.value_type.bytes()); | |
| 211 | .map(|(offset, param)| { | |
| 212 | let val = ptr.offset_i64(fx, offset.bytes() as i64).load( | |
| 213 | fx, | |
| 214 | param.value_type, | |
| 215 | MemFlags::new(), | |
| 216 | ); | |
| 196 | 217 | val |
| 197 | 218 | }) |
| 198 | 219 | .collect() |
| ... | ... | @@ -205,7 +226,7 @@ pub(super) fn from_casted_value<'tcx>( |
| 205 | 226 | cast: &CastTarget, |
| 206 | 227 | ) -> CValue<'tcx> { |
| 207 | 228 | let abi_params = cast_target_to_abi_params(cast); |
| 208 | let abi_param_size: u32 = abi_params.iter().map(|param| param.value_type.bytes()).sum(); | |
| 229 | let abi_param_size: u32 = abi_params.iter().map(|(_, param)| param.value_type.bytes()).sum(); | |
| 209 | 230 | let layout_size = u32::try_from(layout.size.bytes()).unwrap(); |
| 210 | 231 | let ptr = fx.create_stack_slot( |
| 211 | 232 | // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`. |
| ... | ... | @@ -214,16 +235,13 @@ pub(super) fn from_casted_value<'tcx>( |
| 214 | 235 | std::cmp::max(abi_param_size, layout_size), |
| 215 | 236 | u32::try_from(layout.align.abi.bytes()).unwrap(), |
| 216 | 237 | ); |
| 217 | let mut offset = 0; | |
| 218 | 238 | let mut block_params_iter = block_params.iter().copied(); |
| 219 | for param in abi_params { | |
| 220 | let val = ptr.offset_i64(fx, offset).store( | |
| 239 | for (offset, _) in abi_params { | |
| 240 | ptr.offset_i64(fx, offset.bytes() as i64).store( | |
| 221 | 241 | fx, |
| 222 | 242 | block_params_iter.next().unwrap(), |
| 223 | 243 | MemFlags::new(), |
| 224 | ); | |
| 225 | offset += i64::from(param.value_type.bytes()); | |
| 226 | val | |
| 244 | ) | |
| 227 | 245 | } |
| 228 | 246 | assert_eq!(block_params_iter.next(), None, "Leftover block param"); |
| 229 | 247 | CValue::by_ref(ptr, layout) |
compiler/rustc_codegen_gcc/src/intrinsic/mod.rs+1-1| ... | ... | @@ -626,7 +626,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { |
| 626 | 626 | bx.lifetime_start(llscratch, scratch_size); |
| 627 | 627 | |
| 628 | 628 | // ... where we first store the value... |
| 629 | bx.store(val, llscratch, scratch_align); | |
| 629 | rustc_codegen_ssa::mir::store_cast(bx, cast, val, llscratch, scratch_align); | |
| 630 | 630 | |
| 631 | 631 | // ... and then memcpy it to the intended destination. |
| 632 | 632 | bx.memcpy( |
compiler/rustc_codegen_llvm/src/abi.rs+1-1| ... | ... | @@ -229,7 +229,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { |
| 229 | 229 | let llscratch = bx.alloca(scratch_size, scratch_align); |
| 230 | 230 | bx.lifetime_start(llscratch, scratch_size); |
| 231 | 231 | // ...store the value... |
| 232 | bx.store(val, llscratch, scratch_align); | |
| 232 | rustc_codegen_ssa::mir::store_cast(bx, cast, val, llscratch, scratch_align); | |
| 233 | 233 | // ... and then memcpy it to the intended destination. |
| 234 | 234 | bx.memcpy( |
| 235 | 235 | dst.val.llval, |
compiler/rustc_codegen_ssa/src/mir/block.rs+48-6| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | use std::cmp; |
| 2 | 2 | |
| 3 | use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, Size, WrappingRange}; | |
| 3 | use rustc_abi::{Align, BackendRepr, ExternAbi, HasDataLayout, Reg, Size, WrappingRange}; | |
| 4 | 4 | use rustc_ast as ast; |
| 5 | 5 | use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; |
| 6 | 6 | use rustc_data_structures::packed::Pu128; |
| ... | ... | @@ -13,7 +13,7 @@ use rustc_middle::{bug, span_bug}; |
| 13 | 13 | use rustc_session::config::OptLevel; |
| 14 | 14 | use rustc_span::Span; |
| 15 | 15 | use rustc_span::source_map::Spanned; |
| 16 | use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; | |
| 16 | use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi, PassMode}; | |
| 17 | 17 | use tracing::{debug, info}; |
| 18 | 18 | |
| 19 | 19 | use super::operand::OperandRef; |
| ... | ... | @@ -558,8 +558,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { |
| 558 | 558 | } |
| 559 | 559 | ZeroSized => bug!("ZST return value shouldn't be in PassMode::Cast"), |
| 560 | 560 | }; |
| 561 | let ty = bx.cast_backend_type(cast_ty); | |
| 562 | bx.load(ty, llslot, self.fn_abi.ret.layout.align.abi) | |
| 561 | load_cast(bx, cast_ty, llslot, self.fn_abi.ret.layout.align.abi) | |
| 563 | 562 | } |
| 564 | 563 | }; |
| 565 | 564 | bx.ret(llval); |
| ... | ... | @@ -1618,8 +1617,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { |
| 1618 | 1617 | MemFlags::empty(), |
| 1619 | 1618 | ); |
| 1620 | 1619 | // ...and then load it with the ABI type. |
| 1621 | let cast_ty = bx.cast_backend_type(cast); | |
| 1622 | llval = bx.load(cast_ty, llscratch, scratch_align); | |
| 1620 | llval = load_cast(bx, cast, llscratch, scratch_align); | |
| 1623 | 1621 | bx.lifetime_end(llscratch, scratch_size); |
| 1624 | 1622 | } else { |
| 1625 | 1623 | // We can't use `PlaceRef::load` here because the argument |
| ... | ... | @@ -1969,3 +1967,47 @@ enum ReturnDest<'tcx, V> { |
| 1969 | 1967 | /// Store a direct return value to an operand local place. |
| 1970 | 1968 | DirectOperand(mir::Local), |
| 1971 | 1969 | } |
| 1970 | ||
| 1971 | fn load_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( | |
| 1972 | bx: &mut Bx, | |
| 1973 | cast: &CastTarget, | |
| 1974 | ptr: Bx::Value, | |
| 1975 | align: Align, | |
| 1976 | ) -> Bx::Value { | |
| 1977 | let cast_ty = bx.cast_backend_type(cast); | |
| 1978 | if let Some(offset_from_start) = cast.rest_offset { | |
| 1979 | assert!(cast.prefix[1..].iter().all(|p| p.is_none())); | |
| 1980 | assert_eq!(cast.rest.unit.size, cast.rest.total); | |
| 1981 | let first_ty = bx.reg_backend_type(&cast.prefix[0].unwrap()); | |
| 1982 | let second_ty = bx.reg_backend_type(&cast.rest.unit); | |
| 1983 | let first = bx.load(first_ty, ptr, align); | |
| 1984 | let second_ptr = bx.inbounds_ptradd(ptr, bx.const_usize(offset_from_start.bytes())); | |
| 1985 | let second = bx.load(second_ty, second_ptr, align.restrict_for_offset(offset_from_start)); | |
| 1986 | let res = bx.cx().const_poison(cast_ty); | |
| 1987 | let res = bx.insert_value(res, first, 0); | |
| 1988 | bx.insert_value(res, second, 1) | |
| 1989 | } else { | |
| 1990 | bx.load(cast_ty, ptr, align) | |
| 1991 | } | |
| 1992 | } | |
| 1993 | ||
| 1994 | pub fn store_cast<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( | |
| 1995 | bx: &mut Bx, | |
| 1996 | cast: &CastTarget, | |
| 1997 | value: Bx::Value, | |
| 1998 | ptr: Bx::Value, | |
| 1999 | align: Align, | |
| 2000 | ) { | |
| 2001 | if let Some(offset_from_start) = cast.rest_offset { | |
| 2002 | assert!(cast.prefix[1..].iter().all(|p| p.is_none())); | |
| 2003 | assert_eq!(cast.rest.unit.size, cast.rest.total); | |
| 2004 | assert!(cast.prefix[0].is_some()); | |
| 2005 | let first = bx.extract_value(value, 0); | |
| 2006 | let second = bx.extract_value(value, 1); | |
| 2007 | bx.store(first, ptr, align); | |
| 2008 | let second_ptr = bx.inbounds_ptradd(ptr, bx.const_usize(offset_from_start.bytes())); | |
| 2009 | bx.store(second, second_ptr, align.restrict_for_offset(offset_from_start)); | |
| 2010 | } else { | |
| 2011 | bx.store(value, ptr, align); | |
| 2012 | }; | |
| 2013 | } |
compiler/rustc_codegen_ssa/src/mir/mod.rs+2-1| ... | ... | @@ -26,6 +26,7 @@ pub mod place; |
| 26 | 26 | mod rvalue; |
| 27 | 27 | mod statement; |
| 28 | 28 | |
| 29 | pub use self::block::store_cast; | |
| 29 | 30 | use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo}; |
| 30 | 31 | use self::operand::{OperandRef, OperandValue}; |
| 31 | 32 | use self::place::PlaceRef; |
| ... | ... | @@ -259,7 +260,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( |
| 259 | 260 | } |
| 260 | 261 | PassMode::Cast { ref cast, .. } => { |
| 261 | 262 | debug!("alloc: {:?} (return place) -> place", local); |
| 262 | let size = cast.size(&start_bx); | |
| 263 | let size = cast.size(&start_bx).max(layout.size); | |
| 263 | 264 | return LocalRef::Place(PlaceRef::alloca_size(&mut start_bx, size, layout)); |
| 264 | 265 | } |
| 265 | 266 | _ => {} |
compiler/rustc_lint/src/dangling.rs+2-1| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | use rustc_ast::visit::{visit_opt, walk_list}; |
| 2 | use rustc_attr_data_structures::{AttributeKind, find_attr}; | |
| 2 | 3 | use rustc_hir::def_id::LocalDefId; |
| 3 | 4 | use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; |
| 4 | 5 | use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem}; |
| ... | ... | @@ -133,7 +134,7 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { |
| 133 | 134 | && let ty = cx.typeck_results().expr_ty(receiver) |
| 134 | 135 | && owns_allocation(cx.tcx, ty) |
| 135 | 136 | && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) |
| 136 | && cx.tcx.has_attr(fn_id, sym::rustc_as_ptr) | |
| 137 | && find_attr!(cx.tcx.get_all_attrs(fn_id), AttributeKind::AsPtr(_)) | |
| 137 | 138 | { |
| 138 | 139 | // FIXME: use `emit_node_lint` when `#[primary_span]` is added. |
| 139 | 140 | cx.tcx.emit_node_span_lint( |
compiler/rustc_parse/src/parser/diagnostics.rs+28-17| ... | ... | @@ -686,23 +686,34 @@ impl<'a> Parser<'a> { |
| 686 | 686 | } |
| 687 | 687 | |
| 688 | 688 | if let token::DocComment(kind, style, _) = self.token.kind { |
| 689 | // We have something like `expr //!val` where the user likely meant `expr // !val` | |
| 690 | let pos = self.token.span.lo() + BytePos(2); | |
| 691 | let span = self.token.span.with_lo(pos).with_hi(pos); | |
| 692 | err.span_suggestion_verbose( | |
| 693 | span, | |
| 694 | format!( | |
| 695 | "add a space before {} to write a regular comment", | |
| 696 | match (kind, style) { | |
| 697 | (token::CommentKind::Line, ast::AttrStyle::Inner) => "`!`", | |
| 698 | (token::CommentKind::Block, ast::AttrStyle::Inner) => "`!`", | |
| 699 | (token::CommentKind::Line, ast::AttrStyle::Outer) => "the last `/`", | |
| 700 | (token::CommentKind::Block, ast::AttrStyle::Outer) => "the last `*`", | |
| 701 | }, | |
| 702 | ), | |
| 703 | " ".to_string(), | |
| 704 | Applicability::MachineApplicable, | |
| 705 | ); | |
| 689 | // This is to avoid suggesting converting a doc comment to a regular comment | |
| 690 | // when missing a comma before the doc comment in lists (#142311): | |
| 691 | // | |
| 692 | // ``` | |
| 693 | // enum Foo{ | |
| 694 | // A /// xxxxxxx | |
| 695 | // B, | |
| 696 | // } | |
| 697 | // ``` | |
| 698 | if !expected.contains(&TokenType::Comma) { | |
| 699 | // We have something like `expr //!val` where the user likely meant `expr // !val` | |
| 700 | let pos = self.token.span.lo() + BytePos(2); | |
| 701 | let span = self.token.span.with_lo(pos).with_hi(pos); | |
| 702 | err.span_suggestion_verbose( | |
| 703 | span, | |
| 704 | format!( | |
| 705 | "add a space before {} to write a regular comment", | |
| 706 | match (kind, style) { | |
| 707 | (token::CommentKind::Line, ast::AttrStyle::Inner) => "`!`", | |
| 708 | (token::CommentKind::Block, ast::AttrStyle::Inner) => "`!`", | |
| 709 | (token::CommentKind::Line, ast::AttrStyle::Outer) => "the last `/`", | |
| 710 | (token::CommentKind::Block, ast::AttrStyle::Outer) => "the last `*`", | |
| 711 | }, | |
| 712 | ), | |
| 713 | " ".to_string(), | |
| 714 | Applicability::MaybeIncorrect, | |
| 715 | ); | |
| 716 | } | |
| 706 | 717 | } |
| 707 | 718 | |
| 708 | 719 | let sp = if self.token == token::Eof { |
compiler/rustc_passes/src/check_attr.rs+12-12| ... | ... | @@ -147,6 +147,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 147 | 147 | | AttributeKind::ConstStabilityIndirect |
| 148 | 148 | | AttributeKind::MacroTransparency(_), |
| 149 | 149 | ) => { /* do nothing */ } |
| 150 | Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => { | |
| 151 | self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target) | |
| 152 | } | |
| 150 | 153 | Attribute::Unparsed(_) => { |
| 151 | 154 | match attr.path().as_slice() { |
| 152 | 155 | [sym::diagnostic, sym::do_not_recommend, ..] => { |
| ... | ... | @@ -188,26 +191,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 188 | 191 | self.check_rustc_std_internal_symbol(attr, span, target) |
| 189 | 192 | } |
| 190 | 193 | [sym::naked, ..] => self.check_naked(hir_id, attr, span, target, attrs), |
| 191 | [sym::rustc_as_ptr, ..] => { | |
| 192 | self.check_applied_to_fn_or_method(hir_id, attr, span, target) | |
| 193 | } | |
| 194 | 194 | [sym::rustc_no_implicit_autorefs, ..] => { |
| 195 | self.check_applied_to_fn_or_method(hir_id, attr, span, target) | |
| 195 | self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) | |
| 196 | 196 | } |
| 197 | 197 | [sym::rustc_never_returns_null_ptr, ..] => { |
| 198 | self.check_applied_to_fn_or_method(hir_id, attr, span, target) | |
| 198 | self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) | |
| 199 | 199 | } |
| 200 | 200 | [sym::rustc_legacy_const_generics, ..] => { |
| 201 | 201 | self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item) |
| 202 | 202 | } |
| 203 | 203 | [sym::rustc_lint_query_instability, ..] => { |
| 204 | self.check_applied_to_fn_or_method(hir_id, attr, span, target) | |
| 204 | self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) | |
| 205 | 205 | } |
| 206 | 206 | [sym::rustc_lint_untracked_query_information, ..] => { |
| 207 | self.check_applied_to_fn_or_method(hir_id, attr, span, target) | |
| 207 | self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) | |
| 208 | 208 | } |
| 209 | 209 | [sym::rustc_lint_diagnostics, ..] => { |
| 210 | self.check_applied_to_fn_or_method(hir_id, attr, span, target) | |
| 210 | self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) | |
| 211 | 211 | } |
| 212 | 212 | [sym::rustc_lint_opt_ty, ..] => self.check_rustc_lint_opt_ty(attr, span, target), |
| 213 | 213 | [sym::rustc_lint_opt_deny_field_access, ..] => { |
| ... | ... | @@ -1825,15 +1825,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> { |
| 1825 | 1825 | fn check_applied_to_fn_or_method( |
| 1826 | 1826 | &self, |
| 1827 | 1827 | hir_id: HirId, |
| 1828 | attr: &Attribute, | |
| 1829 | span: Span, | |
| 1828 | attr_span: Span, | |
| 1829 | defn_span: Span, | |
| 1830 | 1830 | target: Target, |
| 1831 | 1831 | ) { |
| 1832 | 1832 | let is_function = matches!(target, Target::Fn | Target::Method(..)); |
| 1833 | 1833 | if !is_function { |
| 1834 | 1834 | self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { |
| 1835 | attr_span: attr.span(), | |
| 1836 | defn_span: span, | |
| 1835 | attr_span, | |
| 1836 | defn_span, | |
| 1837 | 1837 | on_crate: hir_id == CRATE_HIR_ID, |
| 1838 | 1838 | }); |
| 1839 | 1839 | } |
compiler/rustc_resolve/src/late.rs+12-12| ... | ... | @@ -415,24 +415,24 @@ pub(crate) enum AliasPossibility { |
| 415 | 415 | } |
| 416 | 416 | |
| 417 | 417 | #[derive(Copy, Clone, Debug)] |
| 418 | pub(crate) enum PathSource<'a, 'c> { | |
| 418 | pub(crate) enum PathSource<'a, 'ast, 'ra> { | |
| 419 | 419 | /// Type paths `Path`. |
| 420 | 420 | Type, |
| 421 | 421 | /// Trait paths in bounds or impls. |
| 422 | 422 | Trait(AliasPossibility), |
| 423 | 423 | /// Expression paths `path`, with optional parent context. |
| 424 | Expr(Option<&'a Expr>), | |
| 424 | Expr(Option<&'ast Expr>), | |
| 425 | 425 | /// Paths in path patterns `Path`. |
| 426 | 426 | Pat, |
| 427 | 427 | /// Paths in struct expressions and patterns `Path { .. }`. |
| 428 | 428 | Struct, |
| 429 | 429 | /// Paths in tuple struct patterns `Path(..)`. |
| 430 | TupleStruct(Span, &'a [Span]), | |
| 430 | TupleStruct(Span, &'ra [Span]), | |
| 431 | 431 | /// `m::A::B` in `<T as m::A>::B::C`. |
| 432 | 432 | /// |
| 433 | 433 | /// Second field holds the "cause" of this one, i.e. the context within |
| 434 | 434 | /// which the trait item is resolved. Used for diagnostics. |
| 435 | TraitItem(Namespace, &'c PathSource<'a, 'c>), | |
| 435 | TraitItem(Namespace, &'a PathSource<'a, 'ast, 'ra>), | |
| 436 | 436 | /// Paths in delegation item |
| 437 | 437 | Delegation, |
| 438 | 438 | /// An arg in a `use<'a, N>` precise-capturing bound. |
| ... | ... | @@ -443,7 +443,7 @@ pub(crate) enum PathSource<'a, 'c> { |
| 443 | 443 | DefineOpaques, |
| 444 | 444 | } |
| 445 | 445 | |
| 446 | impl<'a> PathSource<'a, '_> { | |
| 446 | impl PathSource<'_, '_, '_> { | |
| 447 | 447 | fn namespace(self) -> Namespace { |
| 448 | 448 | match self { |
| 449 | 449 | PathSource::Type |
| ... | ... | @@ -773,7 +773,7 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 773 | 773 | } |
| 774 | 774 | |
| 775 | 775 | /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. |
| 776 | impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { | |
| 776 | impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { | |
| 777 | 777 | fn visit_attribute(&mut self, _: &'ast Attribute) { |
| 778 | 778 | // We do not want to resolve expressions that appear in attributes, |
| 779 | 779 | // as they do not correspond to actual code. |
| ... | ... | @@ -1462,7 +1462,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r |
| 1462 | 1462 | } |
| 1463 | 1463 | } |
| 1464 | 1464 | |
| 1465 | impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { | |
| 1465 | impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { | |
| 1466 | 1466 | fn new(resolver: &'a mut Resolver<'ra, 'tcx>) -> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 1467 | 1467 | // During late resolution we only track the module component of the parent scope, |
| 1468 | 1468 | // although it may be useful to track other components as well for diagnostics. |
| ... | ... | @@ -2010,7 +2010,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 2010 | 2010 | &mut self, |
| 2011 | 2011 | partial_res: PartialRes, |
| 2012 | 2012 | path: &[Segment], |
| 2013 | source: PathSource<'_, '_>, | |
| 2013 | source: PathSource<'_, '_, '_>, | |
| 2014 | 2014 | path_span: Span, |
| 2015 | 2015 | ) { |
| 2016 | 2016 | let proj_start = path.len() - partial_res.unresolved_segments(); |
| ... | ... | @@ -4161,7 +4161,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 4161 | 4161 | id: NodeId, |
| 4162 | 4162 | qself: &Option<P<QSelf>>, |
| 4163 | 4163 | path: &Path, |
| 4164 | source: PathSource<'ast, '_>, | |
| 4164 | source: PathSource<'_, 'ast, '_>, | |
| 4165 | 4165 | ) { |
| 4166 | 4166 | self.smart_resolve_path_fragment( |
| 4167 | 4167 | qself, |
| ... | ... | @@ -4178,7 +4178,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 4178 | 4178 | &mut self, |
| 4179 | 4179 | qself: &Option<P<QSelf>>, |
| 4180 | 4180 | path: &[Segment], |
| 4181 | source: PathSource<'ast, '_>, | |
| 4181 | source: PathSource<'_, 'ast, '_>, | |
| 4182 | 4182 | finalize: Finalize, |
| 4183 | 4183 | record_partial_res: RecordPartialRes, |
| 4184 | 4184 | parent_qself: Option<&QSelf>, |
| ... | ... | @@ -4482,7 +4482,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 4482 | 4482 | span: Span, |
| 4483 | 4483 | defer_to_typeck: bool, |
| 4484 | 4484 | finalize: Finalize, |
| 4485 | source: PathSource<'ast, '_>, | |
| 4485 | source: PathSource<'_, 'ast, '_>, | |
| 4486 | 4486 | ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> { |
| 4487 | 4487 | let mut fin_res = None; |
| 4488 | 4488 | |
| ... | ... | @@ -4525,7 +4525,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |
| 4525 | 4525 | path: &[Segment], |
| 4526 | 4526 | ns: Namespace, |
| 4527 | 4527 | finalize: Finalize, |
| 4528 | source: PathSource<'ast, '_>, | |
| 4528 | source: PathSource<'_, 'ast, '_>, | |
| 4529 | 4529 | ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> { |
| 4530 | 4530 | debug!( |
| 4531 | 4531 | "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})", |
compiler/rustc_resolve/src/late/diagnostics.rs+21-21| ... | ... | @@ -170,12 +170,12 @@ impl TypoCandidate { |
| 170 | 170 | } |
| 171 | 171 | } |
| 172 | 172 | |
| 173 | impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { | |
| 173 | impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { | |
| 174 | 174 | fn make_base_error( |
| 175 | 175 | &mut self, |
| 176 | 176 | path: &[Segment], |
| 177 | 177 | span: Span, |
| 178 | source: PathSource<'_, '_>, | |
| 178 | source: PathSource<'_, '_, '_>, | |
| 179 | 179 | res: Option<Res>, |
| 180 | 180 | ) -> BaseError { |
| 181 | 181 | // Make the base error. |
| ... | ... | @@ -421,7 +421,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 421 | 421 | path: &[Segment], |
| 422 | 422 | following_seg: Option<&Segment>, |
| 423 | 423 | span: Span, |
| 424 | source: PathSource<'_, '_>, | |
| 424 | source: PathSource<'_, '_, '_>, | |
| 425 | 425 | res: Option<Res>, |
| 426 | 426 | qself: Option<&QSelf>, |
| 427 | 427 | ) -> (Diag<'tcx>, Vec<ImportSuggestion>) { |
| ... | ... | @@ -539,7 +539,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 539 | 539 | path: &[Segment], |
| 540 | 540 | following_seg: Option<&Segment>, |
| 541 | 541 | span: Span, |
| 542 | source: PathSource<'_, '_>, | |
| 542 | source: PathSource<'_, '_, '_>, | |
| 543 | 543 | res: Option<Res>, |
| 544 | 544 | qself: Option<&QSelf>, |
| 545 | 545 | ) { |
| ... | ... | @@ -650,7 +650,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 650 | 650 | fn try_lookup_name_relaxed( |
| 651 | 651 | &mut self, |
| 652 | 652 | err: &mut Diag<'_>, |
| 653 | source: PathSource<'_, '_>, | |
| 653 | source: PathSource<'_, '_, '_>, | |
| 654 | 654 | path: &[Segment], |
| 655 | 655 | following_seg: Option<&Segment>, |
| 656 | 656 | span: Span, |
| ... | ... | @@ -940,7 +940,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 940 | 940 | fn suggest_trait_and_bounds( |
| 941 | 941 | &mut self, |
| 942 | 942 | err: &mut Diag<'_>, |
| 943 | source: PathSource<'_, '_>, | |
| 943 | source: PathSource<'_, '_, '_>, | |
| 944 | 944 | res: Option<Res>, |
| 945 | 945 | span: Span, |
| 946 | 946 | base_error: &BaseError, |
| ... | ... | @@ -1017,7 +1017,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1017 | 1017 | fn suggest_typo( |
| 1018 | 1018 | &mut self, |
| 1019 | 1019 | err: &mut Diag<'_>, |
| 1020 | source: PathSource<'_, '_>, | |
| 1020 | source: PathSource<'_, '_, '_>, | |
| 1021 | 1021 | path: &[Segment], |
| 1022 | 1022 | following_seg: Option<&Segment>, |
| 1023 | 1023 | span: Span, |
| ... | ... | @@ -1063,7 +1063,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1063 | 1063 | fn suggest_shadowed( |
| 1064 | 1064 | &mut self, |
| 1065 | 1065 | err: &mut Diag<'_>, |
| 1066 | source: PathSource<'_, '_>, | |
| 1066 | source: PathSource<'_, '_, '_>, | |
| 1067 | 1067 | path: &[Segment], |
| 1068 | 1068 | following_seg: Option<&Segment>, |
| 1069 | 1069 | span: Span, |
| ... | ... | @@ -1096,7 +1096,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1096 | 1096 | fn err_code_special_cases( |
| 1097 | 1097 | &mut self, |
| 1098 | 1098 | err: &mut Diag<'_>, |
| 1099 | source: PathSource<'_, '_>, | |
| 1099 | source: PathSource<'_, '_, '_>, | |
| 1100 | 1100 | path: &[Segment], |
| 1101 | 1101 | span: Span, |
| 1102 | 1102 | ) { |
| ... | ... | @@ -1141,7 +1141,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1141 | 1141 | fn suggest_self_ty( |
| 1142 | 1142 | &mut self, |
| 1143 | 1143 | err: &mut Diag<'_>, |
| 1144 | source: PathSource<'_, '_>, | |
| 1144 | source: PathSource<'_, '_, '_>, | |
| 1145 | 1145 | path: &[Segment], |
| 1146 | 1146 | span: Span, |
| 1147 | 1147 | ) -> bool { |
| ... | ... | @@ -1164,7 +1164,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1164 | 1164 | fn suggest_self_value( |
| 1165 | 1165 | &mut self, |
| 1166 | 1166 | err: &mut Diag<'_>, |
| 1167 | source: PathSource<'_, '_>, | |
| 1167 | source: PathSource<'_, '_, '_>, | |
| 1168 | 1168 | path: &[Segment], |
| 1169 | 1169 | span: Span, |
| 1170 | 1170 | ) -> bool { |
| ... | ... | @@ -1332,7 +1332,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1332 | 1332 | fn suggest_swapping_misplaced_self_ty_and_trait( |
| 1333 | 1333 | &mut self, |
| 1334 | 1334 | err: &mut Diag<'_>, |
| 1335 | source: PathSource<'_, '_>, | |
| 1335 | source: PathSource<'_, '_, '_>, | |
| 1336 | 1336 | res: Option<Res>, |
| 1337 | 1337 | span: Span, |
| 1338 | 1338 | ) { |
| ... | ... | @@ -1361,7 +1361,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1361 | 1361 | &mut self, |
| 1362 | 1362 | err: &mut Diag<'_>, |
| 1363 | 1363 | res: Option<Res>, |
| 1364 | source: PathSource<'_, '_>, | |
| 1364 | source: PathSource<'_, '_, '_>, | |
| 1365 | 1365 | ) { |
| 1366 | 1366 | let PathSource::TupleStruct(_, _) = source else { return }; |
| 1367 | 1367 | let Some(Res::Def(DefKind::Fn, _)) = res else { return }; |
| ... | ... | @@ -1373,7 +1373,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1373 | 1373 | &mut self, |
| 1374 | 1374 | err: &mut Diag<'_>, |
| 1375 | 1375 | res: Option<Res>, |
| 1376 | source: PathSource<'_, '_>, | |
| 1376 | source: PathSource<'_, '_, '_>, | |
| 1377 | 1377 | span: Span, |
| 1378 | 1378 | ) { |
| 1379 | 1379 | let PathSource::Trait(_) = source else { return }; |
| ... | ... | @@ -1422,7 +1422,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1422 | 1422 | fn suggest_pattern_match_with_let( |
| 1423 | 1423 | &mut self, |
| 1424 | 1424 | err: &mut Diag<'_>, |
| 1425 | source: PathSource<'_, '_>, | |
| 1425 | source: PathSource<'_, '_, '_>, | |
| 1426 | 1426 | span: Span, |
| 1427 | 1427 | ) -> bool { |
| 1428 | 1428 | if let PathSource::Expr(_) = source |
| ... | ... | @@ -1448,7 +1448,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1448 | 1448 | fn get_single_associated_item( |
| 1449 | 1449 | &mut self, |
| 1450 | 1450 | path: &[Segment], |
| 1451 | source: &PathSource<'_, '_>, | |
| 1451 | source: &PathSource<'_, '_, '_>, | |
| 1452 | 1452 | filter_fn: &impl Fn(Res) -> bool, |
| 1453 | 1453 | ) -> Option<TypoSuggestion> { |
| 1454 | 1454 | if let crate::PathSource::TraitItem(_, _) = source { |
| ... | ... | @@ -1556,7 +1556,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1556 | 1556 | |
| 1557 | 1557 | /// Check if the source is call expression and the first argument is `self`. If true, |
| 1558 | 1558 | /// return the span of whole call and the span for all arguments expect the first one (`self`). |
| 1559 | fn call_has_self_arg(&self, source: PathSource<'_, '_>) -> Option<(Span, Option<Span>)> { | |
| 1559 | fn call_has_self_arg(&self, source: PathSource<'_, '_, '_>) -> Option<(Span, Option<Span>)> { | |
| 1560 | 1560 | let mut has_self_arg = None; |
| 1561 | 1561 | if let PathSource::Expr(Some(parent)) = source |
| 1562 | 1562 | && let ExprKind::Call(_, args) = &parent.kind |
| ... | ... | @@ -1614,7 +1614,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1614 | 1614 | &mut self, |
| 1615 | 1615 | err: &mut Diag<'_>, |
| 1616 | 1616 | span: Span, |
| 1617 | source: PathSource<'_, '_>, | |
| 1617 | source: PathSource<'_, '_, '_>, | |
| 1618 | 1618 | path: &[Segment], |
| 1619 | 1619 | res: Res, |
| 1620 | 1620 | path_str: &str, |
| ... | ... | @@ -1666,7 +1666,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 1666 | 1666 | } |
| 1667 | 1667 | }; |
| 1668 | 1668 | |
| 1669 | let find_span = |source: &PathSource<'_, '_>, err: &mut Diag<'_>| { | |
| 1669 | let find_span = |source: &PathSource<'_, '_, '_>, err: &mut Diag<'_>| { | |
| 1670 | 1670 | match source { |
| 1671 | 1671 | PathSource::Expr(Some(Expr { span, kind: ExprKind::Call(_, _), .. })) |
| 1672 | 1672 | | PathSource::TupleStruct(span, _) => { |
| ... | ... | @@ -2699,7 +2699,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 2699 | 2699 | fn suggest_using_enum_variant( |
| 2700 | 2700 | &mut self, |
| 2701 | 2701 | err: &mut Diag<'_>, |
| 2702 | source: PathSource<'_, '_>, | |
| 2702 | source: PathSource<'_, '_, '_>, | |
| 2703 | 2703 | def_id: DefId, |
| 2704 | 2704 | span: Span, |
| 2705 | 2705 | ) { |
| ... | ... | @@ -2877,7 +2877,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 2877 | 2877 | pub(crate) fn suggest_adding_generic_parameter( |
| 2878 | 2878 | &self, |
| 2879 | 2879 | path: &[Segment], |
| 2880 | source: PathSource<'_, '_>, | |
| 2880 | source: PathSource<'_, '_, '_>, | |
| 2881 | 2881 | ) -> Option<(Span, &'static str, String, Applicability)> { |
| 2882 | 2882 | let (ident, span) = match path { |
| 2883 | 2883 | [segment] |
compiler/rustc_target/src/callconv/mips64.rs+2-13| ... | ... | @@ -2,9 +2,7 @@ use rustc_abi::{ |
| 2 | 2 | BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface, |
| 3 | 3 | }; |
| 4 | 4 | |
| 5 | use crate::callconv::{ | |
| 6 | ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, Uniform, | |
| 7 | }; | |
| 5 | use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform}; | |
| 8 | 6 | |
| 9 | 7 | fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) { |
| 10 | 8 | // Always sign extend u32 values on 64-bit mips |
| ... | ... | @@ -140,16 +138,7 @@ where |
| 140 | 138 | |
| 141 | 139 | // Extract first 8 chunks as the prefix |
| 142 | 140 | let rest_size = size - Size::from_bytes(8) * prefix_index as u64; |
| 143 | arg.cast_to(CastTarget { | |
| 144 | prefix, | |
| 145 | rest: Uniform::new(Reg::i64(), rest_size), | |
| 146 | attrs: ArgAttributes { | |
| 147 | regular: ArgAttribute::default(), | |
| 148 | arg_ext: ArgExtension::None, | |
| 149 | pointee_size: Size::ZERO, | |
| 150 | pointee_align: None, | |
| 151 | }, | |
| 152 | }); | |
| 141 | arg.cast_to(CastTarget::prefixed(prefix, Uniform::new(Reg::i64(), rest_size))); | |
| 153 | 142 | } |
| 154 | 143 | |
| 155 | 144 | pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) |
compiler/rustc_target/src/callconv/mod.rs+57-27| ... | ... | @@ -197,6 +197,17 @@ impl ArgAttributes { |
| 197 | 197 | } |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | impl From<ArgAttribute> for ArgAttributes { | |
| 201 | fn from(value: ArgAttribute) -> Self { | |
| 202 | Self { | |
| 203 | regular: value, | |
| 204 | arg_ext: ArgExtension::None, | |
| 205 | pointee_size: Size::ZERO, | |
| 206 | pointee_align: None, | |
| 207 | } | |
| 208 | } | |
| 209 | } | |
| 210 | ||
| 200 | 211 | /// An argument passed entirely registers with the |
| 201 | 212 | /// same kind (e.g., HFA / HVA on PPC64 and AArch64). |
| 202 | 213 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] |
| ... | ... | @@ -251,6 +262,9 @@ impl Uniform { |
| 251 | 262 | #[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] |
| 252 | 263 | pub struct CastTarget { |
| 253 | 264 | pub prefix: [Option<Reg>; 8], |
| 265 | /// The offset of `rest` from the start of the value. Currently only implemented for a `Reg` | |
| 266 | /// pair created by the `offset_pair` method. | |
| 267 | pub rest_offset: Option<Size>, | |
| 254 | 268 | pub rest: Uniform, |
| 255 | 269 | pub attrs: ArgAttributes, |
| 256 | 270 | } |
| ... | ... | @@ -263,42 +277,45 @@ impl From<Reg> for CastTarget { |
| 263 | 277 | |
| 264 | 278 | impl From<Uniform> for CastTarget { |
| 265 | 279 | fn from(uniform: Uniform) -> CastTarget { |
| 266 | CastTarget { | |
| 267 | prefix: [None; 8], | |
| 268 | rest: uniform, | |
| 269 | attrs: ArgAttributes { | |
| 270 | regular: ArgAttribute::default(), | |
| 271 | arg_ext: ArgExtension::None, | |
| 272 | pointee_size: Size::ZERO, | |
| 273 | pointee_align: None, | |
| 274 | }, | |
| 275 | } | |
| 280 | Self::prefixed([None; 8], uniform) | |
| 276 | 281 | } |
| 277 | 282 | } |
| 278 | 283 | |
| 279 | 284 | impl CastTarget { |
| 280 | pub fn pair(a: Reg, b: Reg) -> CastTarget { | |
| 281 | CastTarget { | |
| 285 | pub fn prefixed(prefix: [Option<Reg>; 8], rest: Uniform) -> Self { | |
| 286 | Self { prefix, rest_offset: None, rest, attrs: ArgAttributes::new() } | |
| 287 | } | |
| 288 | ||
| 289 | pub fn offset_pair(a: Reg, offset_from_start: Size, b: Reg) -> Self { | |
| 290 | Self { | |
| 282 | 291 | prefix: [Some(a), None, None, None, None, None, None, None], |
| 283 | rest: Uniform::from(b), | |
| 284 | attrs: ArgAttributes { | |
| 285 | regular: ArgAttribute::default(), | |
| 286 | arg_ext: ArgExtension::None, | |
| 287 | pointee_size: Size::ZERO, | |
| 288 | pointee_align: None, | |
| 289 | }, | |
| 292 | rest_offset: Some(offset_from_start), | |
| 293 | rest: b.into(), | |
| 294 | attrs: ArgAttributes::new(), | |
| 290 | 295 | } |
| 291 | 296 | } |
| 292 | 297 | |
| 298 | pub fn with_attrs(mut self, attrs: ArgAttributes) -> Self { | |
| 299 | self.attrs = attrs; | |
| 300 | self | |
| 301 | } | |
| 302 | ||
| 303 | pub fn pair(a: Reg, b: Reg) -> CastTarget { | |
| 304 | Self::prefixed([Some(a), None, None, None, None, None, None, None], Uniform::from(b)) | |
| 305 | } | |
| 306 | ||
| 293 | 307 | /// When you only access the range containing valid data, you can use this unaligned size; |
| 294 | 308 | /// otherwise, use the safer `size` method. |
| 295 | 309 | pub fn unaligned_size<C: HasDataLayout>(&self, _cx: &C) -> Size { |
| 296 | 310 | // Prefix arguments are passed in specific designated registers |
| 297 | let prefix_size = self | |
| 298 | .prefix | |
| 299 | .iter() | |
| 300 | .filter_map(|x| x.map(|reg| reg.size)) | |
| 301 | .fold(Size::ZERO, |acc, size| acc + size); | |
| 311 | let prefix_size = if let Some(offset_from_start) = self.rest_offset { | |
| 312 | offset_from_start | |
| 313 | } else { | |
| 314 | self.prefix | |
| 315 | .iter() | |
| 316 | .filter_map(|x| x.map(|reg| reg.size)) | |
| 317 | .fold(Size::ZERO, |acc, size| acc + size) | |
| 318 | }; | |
| 302 | 319 | // Remaining arguments are passed in chunks of the unit size |
| 303 | 320 | let rest_size = |
| 304 | 321 | self.rest.unit.size * self.rest.total.bytes().div_ceil(self.rest.unit.size.bytes()); |
| ... | ... | @@ -322,9 +339,22 @@ impl CastTarget { |
| 322 | 339 | /// Checks if these two `CastTarget` are equal enough to be considered "the same for all |
| 323 | 340 | /// function call ABIs". |
| 324 | 341 | pub fn eq_abi(&self, other: &Self) -> bool { |
| 325 | let CastTarget { prefix: prefix_l, rest: rest_l, attrs: attrs_l } = self; | |
| 326 | let CastTarget { prefix: prefix_r, rest: rest_r, attrs: attrs_r } = other; | |
| 327 | prefix_l == prefix_r && rest_l == rest_r && attrs_l.eq_abi(attrs_r) | |
| 342 | let CastTarget { | |
| 343 | prefix: prefix_l, | |
| 344 | rest_offset: rest_offset_l, | |
| 345 | rest: rest_l, | |
| 346 | attrs: attrs_l, | |
| 347 | } = self; | |
| 348 | let CastTarget { | |
| 349 | prefix: prefix_r, | |
| 350 | rest_offset: rest_offset_r, | |
| 351 | rest: rest_r, | |
| 352 | attrs: attrs_r, | |
| 353 | } = other; | |
| 354 | prefix_l == prefix_r | |
| 355 | && rest_offset_l == rest_offset_r | |
| 356 | && rest_l == rest_r | |
| 357 | && attrs_l.eq_abi(attrs_r) | |
| 328 | 358 | } |
| 329 | 359 | } |
| 330 | 360 |
compiler/rustc_target/src/callconv/nvptx64.rs+9-16| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | use rustc_abi::{HasDataLayout, Reg, Size, TyAbiInterface}; |
| 2 | 2 | |
| 3 | use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget}; | |
| 3 | use super::CastTarget; | |
| 4 | 4 | use crate::callconv::{ArgAbi, FnAbi, Uniform}; |
| 5 | 5 | |
| 6 | 6 | fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { |
| ... | ... | @@ -34,16 +34,10 @@ fn classify_aggregate<Ty>(arg: &mut ArgAbi<'_, Ty>) { |
| 34 | 34 | }; |
| 35 | 35 | |
| 36 | 36 | if align_bytes == size.bytes() { |
| 37 | arg.cast_to(CastTarget { | |
| 38 | prefix: [Some(reg), None, None, None, None, None, None, None], | |
| 39 | rest: Uniform::new(Reg::i8(), Size::from_bytes(0)), | |
| 40 | attrs: ArgAttributes { | |
| 41 | regular: ArgAttribute::default(), | |
| 42 | arg_ext: ArgExtension::None, | |
| 43 | pointee_size: Size::ZERO, | |
| 44 | pointee_align: None, | |
| 45 | }, | |
| 46 | }); | |
| 37 | arg.cast_to(CastTarget::prefixed( | |
| 38 | [Some(reg), None, None, None, None, None, None, None], | |
| 39 | Uniform::new(Reg::i8(), Size::ZERO), | |
| 40 | )); | |
| 47 | 41 | } else { |
| 48 | 42 | arg.cast_to(Uniform::new(reg, size)); |
| 49 | 43 | } |
| ... | ... | @@ -78,11 +72,10 @@ where |
| 78 | 72 | }; |
| 79 | 73 | if arg.layout.size.bytes() / align_bytes == 1 { |
| 80 | 74 | // Make sure we pass the struct as array at the LLVM IR level and not as a single integer. |
| 81 | arg.cast_to(CastTarget { | |
| 82 | prefix: [Some(unit), None, None, None, None, None, None, None], | |
| 83 | rest: Uniform::new(unit, Size::ZERO), | |
| 84 | attrs: ArgAttributes::new(), | |
| 85 | }); | |
| 75 | arg.cast_to(CastTarget::prefixed( | |
| 76 | [Some(unit), None, None, None, None, None, None, None], | |
| 77 | Uniform::new(unit, Size::ZERO), | |
| 78 | )); | |
| 86 | 79 | } else { |
| 87 | 80 | arg.cast_to(Uniform::new(unit, arg.layout.size)); |
| 88 | 81 | } |
compiler/rustc_target/src/callconv/riscv.rs+105-32| ... | ... | @@ -14,16 +14,16 @@ use crate::spec::HasTargetSpec; |
| 14 | 14 | |
| 15 | 15 | #[derive(Copy, Clone)] |
| 16 | 16 | enum RegPassKind { |
| 17 | Float(Reg), | |
| 18 | Integer(Reg), | |
| 17 | Float { offset_from_start: Size, ty: Reg }, | |
| 18 | Integer { offset_from_start: Size, ty: Reg }, | |
| 19 | 19 | Unknown, |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | 22 | #[derive(Copy, Clone)] |
| 23 | 23 | enum FloatConv { |
| 24 | FloatPair(Reg, Reg), | |
| 24 | FloatPair { first_ty: Reg, second_ty_offset_from_start: Size, second_ty: Reg }, | |
| 25 | 25 | Float(Reg), |
| 26 | MixedPair(Reg, Reg), | |
| 26 | MixedPair { first_ty: Reg, second_ty_offset_from_start: Size, second_ty: Reg }, | |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | #[derive(Copy, Clone)] |
| ... | ... | @@ -43,6 +43,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>( |
| 43 | 43 | flen: u64, |
| 44 | 44 | field1_kind: &mut RegPassKind, |
| 45 | 45 | field2_kind: &mut RegPassKind, |
| 46 | offset_from_start: Size, | |
| 46 | 47 | ) -> Result<(), CannotUseFpConv> |
| 47 | 48 | where |
| 48 | 49 | Ty: TyAbiInterface<'a, C> + Copy, |
| ... | ... | @@ -55,16 +56,16 @@ where |
| 55 | 56 | } |
| 56 | 57 | match (*field1_kind, *field2_kind) { |
| 57 | 58 | (RegPassKind::Unknown, _) => { |
| 58 | *field1_kind = RegPassKind::Integer(Reg { | |
| 59 | kind: RegKind::Integer, | |
| 60 | size: arg_layout.size, | |
| 61 | }); | |
| 59 | *field1_kind = RegPassKind::Integer { | |
| 60 | offset_from_start, | |
| 61 | ty: Reg { kind: RegKind::Integer, size: arg_layout.size }, | |
| 62 | }; | |
| 62 | 63 | } |
| 63 | (RegPassKind::Float(_), RegPassKind::Unknown) => { | |
| 64 | *field2_kind = RegPassKind::Integer(Reg { | |
| 65 | kind: RegKind::Integer, | |
| 66 | size: arg_layout.size, | |
| 67 | }); | |
| 64 | (RegPassKind::Float { .. }, RegPassKind::Unknown) => { | |
| 65 | *field2_kind = RegPassKind::Integer { | |
| 66 | offset_from_start, | |
| 67 | ty: Reg { kind: RegKind::Integer, size: arg_layout.size }, | |
| 68 | }; | |
| 68 | 69 | } |
| 69 | 70 | _ => return Err(CannotUseFpConv), |
| 70 | 71 | } |
| ... | ... | @@ -75,12 +76,16 @@ where |
| 75 | 76 | } |
| 76 | 77 | match (*field1_kind, *field2_kind) { |
| 77 | 78 | (RegPassKind::Unknown, _) => { |
| 78 | *field1_kind = | |
| 79 | RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); | |
| 79 | *field1_kind = RegPassKind::Float { | |
| 80 | offset_from_start, | |
| 81 | ty: Reg { kind: RegKind::Float, size: arg_layout.size }, | |
| 82 | }; | |
| 80 | 83 | } |
| 81 | 84 | (_, RegPassKind::Unknown) => { |
| 82 | *field2_kind = | |
| 83 | RegPassKind::Float(Reg { kind: RegKind::Float, size: arg_layout.size }); | |
| 85 | *field2_kind = RegPassKind::Float { | |
| 86 | offset_from_start, | |
| 87 | ty: Reg { kind: RegKind::Float, size: arg_layout.size }, | |
| 88 | }; | |
| 84 | 89 | } |
| 85 | 90 | _ => return Err(CannotUseFpConv), |
| 86 | 91 | } |
| ... | ... | @@ -102,13 +107,14 @@ where |
| 102 | 107 | flen, |
| 103 | 108 | field1_kind, |
| 104 | 109 | field2_kind, |
| 110 | offset_from_start, | |
| 105 | 111 | ); |
| 106 | 112 | } |
| 107 | 113 | return Err(CannotUseFpConv); |
| 108 | 114 | } |
| 109 | 115 | } |
| 110 | 116 | FieldsShape::Array { count, .. } => { |
| 111 | for _ in 0..count { | |
| 117 | for i in 0..count { | |
| 112 | 118 | let elem_layout = arg_layout.field(cx, 0); |
| 113 | 119 | should_use_fp_conv_helper( |
| 114 | 120 | cx, |
| ... | ... | @@ -117,6 +123,7 @@ where |
| 117 | 123 | flen, |
| 118 | 124 | field1_kind, |
| 119 | 125 | field2_kind, |
| 126 | offset_from_start + elem_layout.size * i, | |
| 120 | 127 | )?; |
| 121 | 128 | } |
| 122 | 129 | } |
| ... | ... | @@ -127,7 +134,15 @@ where |
| 127 | 134 | } |
| 128 | 135 | for i in arg_layout.fields.index_by_increasing_offset() { |
| 129 | 136 | let field = arg_layout.field(cx, i); |
| 130 | should_use_fp_conv_helper(cx, &field, xlen, flen, field1_kind, field2_kind)?; | |
| 137 | should_use_fp_conv_helper( | |
| 138 | cx, | |
| 139 | &field, | |
| 140 | xlen, | |
| 141 | flen, | |
| 142 | field1_kind, | |
| 143 | field2_kind, | |
| 144 | offset_from_start + arg_layout.fields.offset(i), | |
| 145 | )?; | |
| 131 | 146 | } |
| 132 | 147 | } |
| 133 | 148 | }, |
| ... | ... | @@ -146,14 +161,52 @@ where |
| 146 | 161 | { |
| 147 | 162 | let mut field1_kind = RegPassKind::Unknown; |
| 148 | 163 | let mut field2_kind = RegPassKind::Unknown; |
| 149 | if should_use_fp_conv_helper(cx, arg, xlen, flen, &mut field1_kind, &mut field2_kind).is_err() { | |
| 164 | if should_use_fp_conv_helper( | |
| 165 | cx, | |
| 166 | arg, | |
| 167 | xlen, | |
| 168 | flen, | |
| 169 | &mut field1_kind, | |
| 170 | &mut field2_kind, | |
| 171 | Size::ZERO, | |
| 172 | ) | |
| 173 | .is_err() | |
| 174 | { | |
| 150 | 175 | return None; |
| 151 | 176 | } |
| 152 | 177 | match (field1_kind, field2_kind) { |
| 153 | (RegPassKind::Integer(l), RegPassKind::Float(r)) => Some(FloatConv::MixedPair(l, r)), | |
| 154 | (RegPassKind::Float(l), RegPassKind::Integer(r)) => Some(FloatConv::MixedPair(l, r)), | |
| 155 | (RegPassKind::Float(l), RegPassKind::Float(r)) => Some(FloatConv::FloatPair(l, r)), | |
| 156 | (RegPassKind::Float(f), RegPassKind::Unknown) => Some(FloatConv::Float(f)), | |
| 178 | ( | |
| 179 | RegPassKind::Integer { offset_from_start, .. } | |
| 180 | | RegPassKind::Float { offset_from_start, .. }, | |
| 181 | _, | |
| 182 | ) if offset_from_start != Size::ZERO => { | |
| 183 | panic!("type {:?} has a first field with non-zero offset {offset_from_start:?}", arg.ty) | |
| 184 | } | |
| 185 | ( | |
| 186 | RegPassKind::Integer { ty: first_ty, .. }, | |
| 187 | RegPassKind::Float { offset_from_start, ty: second_ty }, | |
| 188 | ) => Some(FloatConv::MixedPair { | |
| 189 | first_ty, | |
| 190 | second_ty_offset_from_start: offset_from_start, | |
| 191 | second_ty, | |
| 192 | }), | |
| 193 | ( | |
| 194 | RegPassKind::Float { ty: first_ty, .. }, | |
| 195 | RegPassKind::Integer { offset_from_start, ty: second_ty }, | |
| 196 | ) => Some(FloatConv::MixedPair { | |
| 197 | first_ty, | |
| 198 | second_ty_offset_from_start: offset_from_start, | |
| 199 | second_ty, | |
| 200 | }), | |
| 201 | ( | |
| 202 | RegPassKind::Float { ty: first_ty, .. }, | |
| 203 | RegPassKind::Float { offset_from_start, ty: second_ty }, | |
| 204 | ) => Some(FloatConv::FloatPair { | |
| 205 | first_ty, | |
| 206 | second_ty_offset_from_start: offset_from_start, | |
| 207 | second_ty, | |
| 208 | }), | |
| 209 | (RegPassKind::Float { ty, .. }, RegPassKind::Unknown) => Some(FloatConv::Float(ty)), | |
| 157 | 210 | _ => None, |
| 158 | 211 | } |
| 159 | 212 | } |
| ... | ... | @@ -171,11 +224,19 @@ where |
| 171 | 224 | FloatConv::Float(f) => { |
| 172 | 225 | arg.cast_to(f); |
| 173 | 226 | } |
| 174 | FloatConv::FloatPair(l, r) => { | |
| 175 | arg.cast_to(CastTarget::pair(l, r)); | |
| 227 | FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty } => { | |
| 228 | arg.cast_to(CastTarget::offset_pair( | |
| 229 | first_ty, | |
| 230 | second_ty_offset_from_start, | |
| 231 | second_ty, | |
| 232 | )); | |
| 176 | 233 | } |
| 177 | FloatConv::MixedPair(l, r) => { | |
| 178 | arg.cast_to(CastTarget::pair(l, r)); | |
| 234 | FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty } => { | |
| 235 | arg.cast_to(CastTarget::offset_pair( | |
| 236 | first_ty, | |
| 237 | second_ty_offset_from_start, | |
| 238 | second_ty, | |
| 239 | )); | |
| 179 | 240 | } |
| 180 | 241 | } |
| 181 | 242 | return false; |
| ... | ... | @@ -239,15 +300,27 @@ fn classify_arg<'a, Ty, C>( |
| 239 | 300 | arg.cast_to(f); |
| 240 | 301 | return; |
| 241 | 302 | } |
| 242 | Some(FloatConv::FloatPair(l, r)) if *avail_fprs >= 2 => { | |
| 303 | Some(FloatConv::FloatPair { first_ty, second_ty_offset_from_start, second_ty }) | |
| 304 | if *avail_fprs >= 2 => | |
| 305 | { | |
| 243 | 306 | *avail_fprs -= 2; |
| 244 | arg.cast_to(CastTarget::pair(l, r)); | |
| 307 | arg.cast_to(CastTarget::offset_pair( | |
| 308 | first_ty, | |
| 309 | second_ty_offset_from_start, | |
| 310 | second_ty, | |
| 311 | )); | |
| 245 | 312 | return; |
| 246 | 313 | } |
| 247 | Some(FloatConv::MixedPair(l, r)) if *avail_fprs >= 1 && *avail_gprs >= 1 => { | |
| 314 | Some(FloatConv::MixedPair { first_ty, second_ty_offset_from_start, second_ty }) | |
| 315 | if *avail_fprs >= 1 && *avail_gprs >= 1 => | |
| 316 | { | |
| 248 | 317 | *avail_gprs -= 1; |
| 249 | 318 | *avail_fprs -= 1; |
| 250 | arg.cast_to(CastTarget::pair(l, r)); | |
| 319 | arg.cast_to(CastTarget::offset_pair( | |
| 320 | first_ty, | |
| 321 | second_ty_offset_from_start, | |
| 322 | second_ty, | |
| 323 | )); | |
| 251 | 324 | return; |
| 252 | 325 | } |
| 253 | 326 | _ => (), |
compiler/rustc_target/src/callconv/sparc64.rs+5-13| ... | ... | @@ -5,9 +5,7 @@ use rustc_abi::{ |
| 5 | 5 | TyAndLayout, |
| 6 | 6 | }; |
| 7 | 7 | |
| 8 | use crate::callconv::{ | |
| 9 | ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Uniform, | |
| 10 | }; | |
| 8 | use crate::callconv::{ArgAbi, ArgAttribute, CastTarget, FnAbi, Uniform}; | |
| 11 | 9 | use crate::spec::HasTargetSpec; |
| 12 | 10 | |
| 13 | 11 | #[derive(Clone, Debug)] |
| ... | ... | @@ -197,16 +195,10 @@ where |
| 197 | 195 | rest_size = rest_size - Reg::i32().size; |
| 198 | 196 | } |
| 199 | 197 | |
| 200 | arg.cast_to(CastTarget { | |
| 201 | prefix: data.prefix, | |
| 202 | rest: Uniform::new(Reg::i64(), rest_size), | |
| 203 | attrs: ArgAttributes { | |
| 204 | regular: data.arg_attribute, | |
| 205 | arg_ext: ArgExtension::None, | |
| 206 | pointee_size: Size::ZERO, | |
| 207 | pointee_align: None, | |
| 208 | }, | |
| 209 | }); | |
| 198 | arg.cast_to( | |
| 199 | CastTarget::prefixed(data.prefix, Uniform::new(Reg::i64(), rest_size)) | |
| 200 | .with_attrs(data.arg_attribute.into()), | |
| 201 | ); | |
| 210 | 202 | return; |
| 211 | 203 | } |
| 212 | 204 | } |
compiler/rustc_type_ir/src/search_graph/mod.rs+6-17| ... | ... | @@ -842,9 +842,8 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { |
| 842 | 842 | /// evaluating this entry would not have ended up depending on either a goal |
| 843 | 843 | /// already on the stack or a provisional cache entry. |
| 844 | 844 | fn candidate_is_applicable( |
| 845 | stack: &Stack<X>, | |
| 845 | &self, | |
| 846 | 846 | step_kind_from_parent: PathKind, |
| 847 | provisional_cache: &HashMap<X::Input, Vec<ProvisionalCacheEntry<X>>>, | |
| 848 | 847 | nested_goals: &NestedGoals<X>, |
| 849 | 848 | ) -> bool { |
| 850 | 849 | // If the global cache entry didn't depend on any nested goals, it always |
| ... | ... | @@ -855,7 +854,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { |
| 855 | 854 | |
| 856 | 855 | // If a nested goal of the global cache entry is on the stack, we would |
| 857 | 856 | // definitely encounter a cycle. |
| 858 | if stack.iter().any(|e| nested_goals.contains(e.input)) { | |
| 857 | if self.stack.iter().any(|e| nested_goals.contains(e.input)) { | |
| 859 | 858 | debug!("cache entry not applicable due to stack"); |
| 860 | 859 | return false; |
| 861 | 860 | } |
| ... | ... | @@ -864,7 +863,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { |
| 864 | 863 | // would apply for any of its nested goals. |
| 865 | 864 | #[allow(rustc::potential_query_instability)] |
| 866 | 865 | for (input, path_from_global_entry) in nested_goals.iter() { |
| 867 | let Some(entries) = provisional_cache.get(&input) else { | |
| 866 | let Some(entries) = self.provisional_cache.get(&input) else { | |
| 868 | 867 | continue; |
| 869 | 868 | }; |
| 870 | 869 | |
| ... | ... | @@ -890,7 +889,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { |
| 890 | 889 | // We check if any of the paths taken while computing the global goal |
| 891 | 890 | // would end up with an applicable provisional cache entry. |
| 892 | 891 | let head = heads.highest_cycle_head(); |
| 893 | let head_to_curr = Self::cycle_path_kind(stack, step_kind_from_parent, head); | |
| 892 | let head_to_curr = Self::cycle_path_kind(&self.stack, step_kind_from_parent, head); | |
| 894 | 893 | let full_paths = path_from_global_entry.extend_with(head_to_curr); |
| 895 | 894 | if full_paths.contains(head_to_provisional.into()) { |
| 896 | 895 | debug!( |
| ... | ... | @@ -918,12 +917,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { |
| 918 | 917 | cx.with_global_cache(|cache| { |
| 919 | 918 | cache |
| 920 | 919 | .get(cx, input, available_depth, |nested_goals| { |
| 921 | Self::candidate_is_applicable( | |
| 922 | &self.stack, | |
| 923 | step_kind_from_parent, | |
| 924 | &self.provisional_cache, | |
| 925 | nested_goals, | |
| 926 | ) | |
| 920 | self.candidate_is_applicable(step_kind_from_parent, nested_goals) | |
| 927 | 921 | }) |
| 928 | 922 | .map(|c| c.result) |
| 929 | 923 | }) |
| ... | ... | @@ -942,12 +936,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { |
| 942 | 936 | cx.with_global_cache(|cache| { |
| 943 | 937 | let CacheData { result, required_depth, encountered_overflow, nested_goals } = cache |
| 944 | 938 | .get(cx, input, available_depth, |nested_goals| { |
| 945 | Self::candidate_is_applicable( | |
| 946 | &self.stack, | |
| 947 | step_kind_from_parent, | |
| 948 | &self.provisional_cache, | |
| 949 | nested_goals, | |
| 950 | ) | |
| 939 | self.candidate_is_applicable(step_kind_from_parent, nested_goals) | |
| 951 | 940 | })?; |
| 952 | 941 | |
| 953 | 942 | // We don't move cycle participants to the global cache, so the |
library/backtrace+1-1| ... | ... | @@ -1 +1 @@ |
| 1 | Subproject commit 6c882eb11984d737f62e85f36703effaf34c2453 | |
| 1 | Subproject commit b65ab935fb2e0d59dba8966ffca09c9cc5a5f57c |
tests/assembly/naked-functions/wasm32.rs+6-3| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | // FIXME: add wasm32-unknown when the wasm32-unknown-unknown ABI is fixed | |
| 2 | // see https://github.com/rust-lang/rust/issues/115666 | |
| 3 | //@ revisions: wasm64-unknown wasm32-wasip1 | |
| 1 | //@ revisions: wasm32-unknown wasm64-unknown wasm32-wasip1 | |
| 4 | 2 | //@ add-core-stubs |
| 5 | 3 | //@ assembly-output: emit-asm |
| 4 | //@ [wasm32-unknown] compile-flags: --target wasm32-unknown-unknown | |
| 6 | 5 | //@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown |
| 7 | 6 | //@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1 |
| 7 | //@ [wasm32-unknown] needs-llvm-components: webassembly | |
| 8 | 8 | //@ [wasm64-unknown] needs-llvm-components: webassembly |
| 9 | 9 | //@ [wasm32-wasip1] needs-llvm-components: webassembly |
| 10 | 10 | |
| ... | ... | @@ -97,6 +97,7 @@ extern "C" fn fn_i64_i64(num: i64) -> i64 { |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | // CHECK-LABEL: fn_i128_i128: |
| 100 | // wasm32-unknown: .functype fn_i128_i128 (i32, i64, i64) -> () | |
| 100 | 101 | // wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> () |
| 101 | 102 | // wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> () |
| 102 | 103 | #[allow(improper_ctypes_definitions)] |
| ... | ... | @@ -114,6 +115,7 @@ extern "C" fn fn_i128_i128(num: i128) -> i128 { |
| 114 | 115 | } |
| 115 | 116 | |
| 116 | 117 | // CHECK-LABEL: fn_f128_f128: |
| 118 | // wasm32-unknown: .functype fn_f128_f128 (i32, i64, i64) -> () | |
| 117 | 119 | // wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> () |
| 118 | 120 | // wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> () |
| 119 | 121 | #[no_mangle] |
| ... | ... | @@ -136,6 +138,7 @@ struct Compound { |
| 136 | 138 | } |
| 137 | 139 | |
| 138 | 140 | // CHECK-LABEL: fn_compound_compound: |
| 141 | // wasm32-unknown: .functype fn_compound_compound (i32, i32) -> () | |
| 139 | 142 | // wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> () |
| 140 | 143 | // wasm64-unknown: .functype fn_compound_compound (i64, i64) -> () |
| 141 | 144 | #[no_mangle] |
tests/assembly/riscv-float-struct-abi.rs created+177| ... | ... | @@ -0,0 +1,177 @@ |
| 1 | //@ add-core-stubs | |
| 2 | //@ assembly-output: emit-asm | |
| 3 | //@ compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu | |
| 4 | //@ needs-llvm-components: riscv | |
| 5 | ||
| 6 | #![feature(no_core, lang_items)] | |
| 7 | #![no_std] | |
| 8 | #![no_core] | |
| 9 | #![crate_type = "lib"] | |
| 10 | ||
| 11 | extern crate minicore; | |
| 12 | use minicore::*; | |
| 13 | ||
| 14 | #[repr(C, align(64))] | |
| 15 | struct Aligned(f64); | |
| 16 | ||
| 17 | #[repr(C)] | |
| 18 | struct Padded(u8, Aligned); | |
| 19 | ||
| 20 | #[repr(C, packed)] | |
| 21 | struct Packed(u8, f32); | |
| 22 | ||
| 23 | impl Copy for Aligned {} | |
| 24 | impl Copy for Padded {} | |
| 25 | impl Copy for Packed {} | |
| 26 | ||
| 27 | extern "C" { | |
| 28 | fn take_padded(x: Padded); | |
| 29 | fn get_padded() -> Padded; | |
| 30 | fn take_packed(x: Packed); | |
| 31 | fn get_packed() -> Packed; | |
| 32 | } | |
| 33 | ||
| 34 | // CHECK-LABEL: pass_padded | |
| 35 | #[unsafe(no_mangle)] | |
| 36 | extern "C" fn pass_padded(out: &mut Padded, x: Padded) { | |
| 37 | // CHECK: sb a1, 0(a0) | |
| 38 | // CHECK-NEXT: fsd fa0, 64(a0) | |
| 39 | // CHECK-NEXT: ret | |
| 40 | *out = x; | |
| 41 | } | |
| 42 | ||
| 43 | // CHECK-LABEL: ret_padded | |
| 44 | #[unsafe(no_mangle)] | |
| 45 | extern "C" fn ret_padded(x: &Padded) -> Padded { | |
| 46 | // CHECK: fld fa0, 64(a0) | |
| 47 | // CHECK-NEXT: lbu a0, 0(a0) | |
| 48 | // CHECK-NEXT: ret | |
| 49 | *x | |
| 50 | } | |
| 51 | ||
| 52 | #[unsafe(no_mangle)] | |
| 53 | extern "C" fn call_padded(x: &Padded) { | |
| 54 | // CHECK: fld fa0, 64(a0) | |
| 55 | // CHECK-NEXT: lbu a0, 0(a0) | |
| 56 | // CHECK-NEXT: tail take_padded | |
| 57 | unsafe { | |
| 58 | take_padded(*x); | |
| 59 | } | |
| 60 | } | |
| 61 | ||
| 62 | #[unsafe(no_mangle)] | |
| 63 | extern "C" fn receive_padded(out: &mut Padded) { | |
| 64 | // CHECK: addi sp, sp, -16 | |
| 65 | // CHECK-NEXT: .cfi_def_cfa_offset 16 | |
| 66 | // CHECK-NEXT: sd ra, [[#%d,RA_SPILL:]](sp) | |
| 67 | // CHECK-NEXT: sd [[TEMP:.*]], [[#%d,TEMP_SPILL:]](sp) | |
| 68 | // CHECK-NEXT: .cfi_offset ra, [[#%d,RA_SPILL - 16]] | |
| 69 | // CHECK-NEXT: .cfi_offset [[TEMP]], [[#%d,TEMP_SPILL - 16]] | |
| 70 | // CHECK-NEXT: mv [[TEMP]], a0 | |
| 71 | // CHECK-NEXT: call get_padded | |
| 72 | // CHECK-NEXT: sb a0, 0([[TEMP]]) | |
| 73 | // CHECK-NEXT: fsd fa0, 64([[TEMP]]) | |
| 74 | // CHECK-NEXT: ld ra, [[#%d,RA_SPILL]](sp) | |
| 75 | // CHECK-NEXT: ld [[TEMP]], [[#%d,TEMP_SPILL]](sp) | |
| 76 | // CHECK: addi sp, sp, 16 | |
| 77 | // CHECK: ret | |
| 78 | unsafe { | |
| 79 | *out = get_padded(); | |
| 80 | } | |
| 81 | } | |
| 82 | ||
| 83 | // CHECK-LABEL: pass_packed | |
| 84 | #[unsafe(no_mangle)] | |
| 85 | extern "C" fn pass_packed(out: &mut Packed, x: Packed) { | |
| 86 | // CHECK: addi sp, sp, -16 | |
| 87 | // CHECK-NEXT: .cfi_def_cfa_offset 16 | |
| 88 | // CHECK-NEXT: sb a1, 0(a0) | |
| 89 | // CHECK-NEXT: fsw fa0, 8(sp) | |
| 90 | // CHECK-NEXT: lw [[VALUE:.*]], 8(sp) | |
| 91 | // CHECK-DAG: srli [[BYTE4:.*]], [[VALUE]], 24 | |
| 92 | // CHECK-DAG: srli [[BYTE3:.*]], [[VALUE]], 16 | |
| 93 | // CHECK-DAG: srli [[BYTE2:.*]], [[VALUE]], 8 | |
| 94 | // CHECK-DAG: sb [[VALUE]], 1(a0) | |
| 95 | // CHECK-DAG: sb [[BYTE2]], 2(a0) | |
| 96 | // CHECK-DAG: sb [[BYTE3]], 3(a0) | |
| 97 | // CHECK-DAG: sb [[BYTE4]], 4(a0) | |
| 98 | // CHECK-NEXT: addi sp, sp, 16 | |
| 99 | // CHECK: ret | |
| 100 | *out = x; | |
| 101 | } | |
| 102 | ||
| 103 | // CHECK-LABEL: ret_packed | |
| 104 | #[unsafe(no_mangle)] | |
| 105 | extern "C" fn ret_packed(x: &Packed) -> Packed { | |
| 106 | // CHECK: addi sp, sp, -16 | |
| 107 | // CHECK-NEXT: .cfi_def_cfa_offset 16 | |
| 108 | // CHECK-NEXT: lbu [[BYTE2:.*]], 2(a0) | |
| 109 | // CHECK-NEXT: lbu [[BYTE1:.*]], 1(a0) | |
| 110 | // CHECK-NEXT: lbu [[BYTE3:.*]], 3(a0) | |
| 111 | // CHECK-NEXT: lbu [[BYTE4:.*]], 4(a0) | |
| 112 | // CHECK-NEXT: slli [[SHIFTED2:.*]], [[BYTE2]], 8 | |
| 113 | // CHECK-NEXT: or [[BYTE12:.*]], [[SHIFTED2]], [[BYTE1]] | |
| 114 | // CHECK-NEXT: slli [[SHIFTED3:.*]], [[BYTE3]], 16 | |
| 115 | // CHECK-NEXT: slli [[SHIFTED4:.*]], [[BYTE4]], 24 | |
| 116 | // CHECK-NEXT: or [[BYTE34:.*]], [[SHIFTED3]], [[SHIFTED4]] | |
| 117 | // CHECK-NEXT: or [[VALUE:.*]], [[BYTE12]], [[BYTE34]] | |
| 118 | // CHECK-NEXT: sw [[VALUE]], 8(sp) | |
| 119 | // CHECK-NEXT: flw fa0, 8(sp) | |
| 120 | // CHECK-NEXT: lbu a0, 0(a0) | |
| 121 | // CHECK-NEXT: addi sp, sp, 16 | |
| 122 | // CHECK: ret | |
| 123 | *x | |
| 124 | } | |
| 125 | ||
| 126 | #[unsafe(no_mangle)] | |
| 127 | extern "C" fn call_packed(x: &Packed) { | |
| 128 | // CHECK: addi sp, sp, -16 | |
| 129 | // CHECK-NEXT: .cfi_def_cfa_offset 16 | |
| 130 | // CHECK-NEXT: lbu [[BYTE2:.*]], 2(a0) | |
| 131 | // CHECK-NEXT: lbu [[BYTE1:.*]], 1(a0) | |
| 132 | // CHECK-NEXT: lbu [[BYTE3:.*]], 3(a0) | |
| 133 | // CHECK-NEXT: lbu [[BYTE4:.*]], 4(a0) | |
| 134 | // CHECK-NEXT: slli [[SHIFTED2:.*]], [[BYTE2]], 8 | |
| 135 | // CHECK-NEXT: or [[BYTE12:.*]], [[SHIFTED2]], [[BYTE1]] | |
| 136 | // CHECK-NEXT: slli [[SHIFTED3:.*]], [[BYTE3]], 16 | |
| 137 | // CHECK-NEXT: slli [[SHIFTED4:.*]], [[BYTE4]], 24 | |
| 138 | // CHECK-NEXT: or [[BYTE34:.*]], [[SHIFTED3]], [[SHIFTED4]] | |
| 139 | // CHECK-NEXT: or [[VALUE:.*]], [[BYTE12]], [[BYTE34]] | |
| 140 | // CHECK-NEXT: sw [[VALUE]], 8(sp) | |
| 141 | // CHECK-NEXT: flw fa0, 8(sp) | |
| 142 | // CHECK-NEXT: lbu a0, 0(a0) | |
| 143 | // CHECK-NEXT: addi sp, sp, 16 | |
| 144 | // CHECK: tail take_packed | |
| 145 | unsafe { | |
| 146 | take_packed(*x); | |
| 147 | } | |
| 148 | } | |
| 149 | ||
| 150 | #[unsafe(no_mangle)] | |
| 151 | extern "C" fn receive_packed(out: &mut Packed) { | |
| 152 | // CHECK: addi sp, sp, -32 | |
| 153 | // CHECK-NEXT: .cfi_def_cfa_offset 32 | |
| 154 | // CHECK-NEXT: sd ra, [[#%d,RA_SPILL:]](sp) | |
| 155 | // CHECK-NEXT: sd [[TEMP:.*]], [[#%d,TEMP_SPILL:]](sp) | |
| 156 | // CHECK-NEXT: .cfi_offset ra, [[#%d,RA_SPILL - 32]] | |
| 157 | // CHECK-NEXT: .cfi_offset [[TEMP]], [[#%d,TEMP_SPILL - 32]] | |
| 158 | // CHECK-NEXT: mv [[TEMP]], a0 | |
| 159 | // CHECK-NEXT: call get_packed | |
| 160 | // CHECK-NEXT: sb a0, 0([[TEMP]]) | |
| 161 | // CHECK-NEXT: fsw fa0, [[FLOAT_SPILL:.*]](sp) | |
| 162 | // CHECK-NEXT: lw [[VALUE:.*]], [[FLOAT_SPILL]](sp) | |
| 163 | // CHECK-DAG: srli [[BYTE4:.*]], [[VALUE]], 24 | |
| 164 | // CHECK-DAG: srli [[BYTE3:.*]], [[VALUE]], 16 | |
| 165 | // CHECK-DAG: srli [[BYTE2:.*]], [[VALUE]], 8 | |
| 166 | // CHECK-DAG: sb [[VALUE]], 1([[TEMP]]) | |
| 167 | // CHECK-DAG: sb [[BYTE2]], 2([[TEMP]]) | |
| 168 | // CHECK-DAG: sb [[BYTE3]], 3([[TEMP]]) | |
| 169 | // CHECK-DAG: sb [[BYTE4]], 4([[TEMP]]) | |
| 170 | // CHECK-NEXT: ld ra, [[#%d,RA_SPILL]](sp) | |
| 171 | // CHECK-NEXT: ld [[TEMP]], [[#%d,TEMP_SPILL]](sp) | |
| 172 | // CHECK: addi sp, sp, 32 | |
| 173 | // CHECK: ret | |
| 174 | unsafe { | |
| 175 | *out = get_packed(); | |
| 176 | } | |
| 177 | } |
tests/codegen/riscv-abi/cast-local-large-enough.rs created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | //@ add-core-stubs | |
| 2 | //@ compile-flags: -Copt-level=0 -Cdebuginfo=0 --target riscv64gc-unknown-linux-gnu | |
| 3 | //@ needs-llvm-components: riscv | |
| 4 | ||
| 5 | #![feature(no_core, lang_items)] | |
| 6 | #![no_std] | |
| 7 | #![no_core] | |
| 8 | #![crate_type = "lib"] | |
| 9 | ||
| 10 | extern crate minicore; | |
| 11 | use minicore::*; | |
| 12 | ||
| 13 | #[repr(C, align(64))] | |
| 14 | struct Aligned(f64); | |
| 15 | ||
| 16 | #[repr(C, align(64))] | |
| 17 | struct AlignedPair(f32, f64); | |
| 18 | ||
| 19 | impl Copy for Aligned {} | |
| 20 | impl Copy for AlignedPair {} | |
| 21 | ||
| 22 | // CHECK-LABEL: define double @read_aligned | |
| 23 | #[unsafe(no_mangle)] | |
| 24 | pub extern "C" fn read_aligned(x: &Aligned) -> Aligned { | |
| 25 | // CHECK: %[[TEMP:.*]] = alloca [64 x i8], align 64 | |
| 26 | // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 64 %[[TEMP]], ptr align 64 %[[PTR:.*]], i64 64, i1 false) | |
| 27 | // CHECK-NEXT: %[[RES:.*]] = load double, ptr %[[TEMP]], align 64 | |
| 28 | // CHECK-NEXT: ret double %[[RES]] | |
| 29 | *x | |
| 30 | } | |
| 31 | ||
| 32 | // CHECK-LABEL: define { float, double } @read_aligned_pair | |
| 33 | #[unsafe(no_mangle)] | |
| 34 | pub extern "C" fn read_aligned_pair(x: &AlignedPair) -> AlignedPair { | |
| 35 | // CHECK: %[[TEMP:.*]] = alloca [64 x i8], align 64 | |
| 36 | // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 64 %[[TEMP]], ptr align 64 %[[PTR:.*]], i64 64, i1 false) | |
| 37 | // CHECK-NEXT: %[[FIRST:.*]] = load float, ptr %[[TEMP]], align 64 | |
| 38 | // CHECK-NEXT: %[[SECOND_PTR:.*]] = getelementptr inbounds i8, ptr %[[TEMP]], i64 8 | |
| 39 | // CHECK-NEXT: %[[SECOND:.*]] = load double, ptr %[[SECOND_PTR]], align 8 | |
| 40 | // CHECK-NEXT: %[[RES1:.*]] = insertvalue { float, double } poison, float %[[FIRST]], 0 | |
| 41 | // CHECK-NEXT: %[[RES2:.*]] = insertvalue { float, double } %[[RES1]], double %[[SECOND]], 1 | |
| 42 | // CHECK-NEXT: ret { float, double } %[[RES2]] | |
| 43 | *x | |
| 44 | } |
tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | // ignore-tidy-linelength |
| 2 | 3 | |
| 3 | 4 | // Check that the `CURRENT_RUSTC_VERSION` placeholder is correctly replaced by the current |
tests/run-make/allow-warnings-cmdline-stability/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | // Test that `-Awarnings` suppresses warnings for unstable APIs. |
| 2 | 3 | |
| 3 | 4 | use run_make_support::rustc; |
tests/run-make/artifact-incr-cache-no-obj/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // emitting an object file is not necessary if user didn't ask for one |
| 2 | 4 | // |
| 3 | 5 | // This test is similar to run-make/artifact-incr-cache but it doesn't |
tests/run-make/artifact-incr-cache/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // rustc should be able to emit required files (asm, llvm-*, etc) during incremental |
| 2 | 4 | // compilation on the first pass by running the code gen as well as on subsequent runs - |
| 3 | 5 | // extracting them from the cache |
tests/run-make/bin-emit-no-symbols/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // When setting the crate type as a "bin" (in app.rs), |
| 2 | 4 | // this could cause a bug where some symbols would not be |
| 3 | 5 | // emitted in the object files. This has been fixed, and |
tests/run-make/box-struct-no-segfault/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // The crate "foo" tied to this test executes a very specific function, |
| 2 | 4 | // which involves boxing an instance of the struct Foo. However, |
| 3 | 5 | // this once caused a segmentation fault in cargo release builds due to an LLVM |
tests/run-make/checksum-freshness/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::{rfs, rustc}; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
tests/run-make/compiler-lookup-paths-2/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This test checks that extern crate declarations in Cargo without a corresponding declaration |
| 2 | 4 | // in the manifest of a dependency are NOT allowed. The last rustc call does it anyways, which |
| 3 | 5 | // should result in a compilation failure. |
tests/run-make/compiler-lookup-paths/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Since #19941, rustc can accept specifications on its library search paths. |
| 2 | 4 | // This test runs Rust programs with varied library dependencies, expecting them |
| 3 | 5 | // to succeed or fail depending on the situation. |
tests/run-make/const-trait-stable-toolchain/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Test output of const super trait errors in both stable and nightly. |
| 2 | 4 | // We don't want to provide suggestions on stable that only make sense in nightly. |
| 3 | 5 |
tests/run-make/crate-circular-deps-link/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Test that previously triggered a linker failure with root cause |
| 2 | 4 | // similar to one found in the issue #69368. |
| 3 | 5 | // |
tests/run-make/cross-lang-lto-upstream-rlibs/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // When using the flag -C linker-plugin-lto, static libraries could lose their upstream object |
| 2 | 4 | // files during compilation. This bug was fixed in #53031, and this test compiles a staticlib |
| 3 | 5 | // dependent on upstream, checking that the upstream object file still exists after no LTO and |
tests/run-make/cross-lang-lto/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This test checks that the object files we generate are actually |
| 2 | 4 | // LLVM bitcode files (as used by linker LTO plugins) when compiling with |
| 3 | 5 | // -Clinker-plugin-lto. |
tests/run-make/debugger-visualizer-dep-info/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This test checks that files referenced via #[debugger_visualizer] are |
| 2 | 4 | // included in `--emit dep-info` output. |
| 3 | 5 | // See https://github.com/rust-lang/rust/pull/111641 |
tests/run-make/dep-info/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This is a simple smoke test for rustc's `--emit dep-info` feature. It prints out |
| 2 | 4 | // information about dependencies in a Makefile-compatible format, as a `.d` file. |
| 3 | 5 | // Note that this test does not check that the `.d` file is Makefile-compatible. |
tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Non-regression test for issue #132920 where multiple versions of the same crate are present in |
| 2 | 4 | // the dependency graph, and an unexpected error in a dependent crate caused an ICE in the |
| 3 | 5 | // unsatisfied bounds diagnostics for traits present in multiple crate versions. |
tests/run-make/doctests-merge/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use std::path::Path; |
| 2 | 3 | |
| 3 | 4 | use run_make_support::{cwd, diff, rustc, rustdoc}; |
tests/run-make/doctests-runtool/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Tests behavior of rustdoc `--test-runtool`. |
| 2 | 4 | |
| 3 | 5 | use std::path::PathBuf; |
tests/run-make/dump-mono-stats/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // A flag named dump-mono-stats was added to the compiler in 2022, which |
| 2 | 4 | // collects stats on instantiation of items and their associated costs. |
| 3 | 5 | // This test checks that the output stat file exists, and that it contains |
tests/run-make/duplicate-output-flavors/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::rustc; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
tests/run-make/embed-metadata/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Tests the -Zembed-metadata compiler flag. |
| 2 | 4 | // Tracking issue: https://github.com/rust-lang/rust/issues/139165 |
| 3 | 5 |
tests/run-make/embed-source-dwarf/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | //@ ignore-windows |
| 2 | 3 | //@ ignore-apple |
| 3 | 4 |
tests/run-make/emit-named-files/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use std::path::Path; |
| 2 | 3 | |
| 3 | 4 | use run_make_support::{rfs, rustc}; |
tests/run-make/emit-path-unhashed/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Specifying how rustc outputs a file can be done in different ways, such as |
| 2 | 4 | // the output flag or the KIND=NAME syntax. However, some of these methods used |
| 3 | 5 | // to result in different hashes on output files even though they yielded the |
tests/run-make/emit-stack-sizes/rmake.rs+1| ... | ... | @@ -6,6 +6,7 @@ |
| 6 | 6 | // this diagnostics information should be located. |
| 7 | 7 | // See https://github.com/rust-lang/rust/pull/51946 |
| 8 | 8 | |
| 9 | //@ needs-target-std | |
| 9 | 10 | //@ ignore-windows |
| 10 | 11 | //@ ignore-apple |
| 11 | 12 | // Reason: this feature only works when the output object format is ELF. |
tests/run-make/emit-to-stdout/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | //! If `-o -` or `--emit KIND=-` is provided, output should be written to stdout |
| 2 | 3 | //! instead. Binary output (`obj`, `llvm-bc`, `link` and `metadata`) |
| 3 | 4 | //! being written this way will result in an error if stdout is a tty. |
tests/run-make/env-dep-info/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Inside dep-info emit files, #71858 made it so all accessed environment |
| 2 | 4 | // variables are usefully printed. This test checks that this feature works |
| 3 | 5 | // as intended by checking if the environment variables used in compilation |
tests/run-make/error-found-staticlib-instead-crate/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // When rustc is looking for a crate but is given a staticlib instead, |
| 2 | 4 | // the error message should be helpful and indicate precisely the cause |
| 3 | 5 | // of the compilation failure. |
tests/run-make/exit-code/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Test that we exit with the correct exit code for successful / unsuccessful / ICE compilations |
| 2 | 4 | |
| 3 | 5 | use run_make_support::{rustc, rustdoc}; |
tests/run-make/export/disambiguator/rmake.rs+3-8| ... | ... | @@ -1,12 +1,7 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::rustc; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
| 4 | rustc() | |
| 5 | .env("RUSTC_FORCE_RUSTC_VERSION", "1") | |
| 6 | .input("libr.rs") | |
| 7 | .run(); | |
| 8 | rustc() | |
| 9 | .env("RUSTC_FORCE_RUSTC_VERSION", "2") | |
| 10 | .input("app.rs") | |
| 11 | .run(); | |
| 5 | rustc().env("RUSTC_FORCE_RUSTC_VERSION", "1").input("libr.rs").run(); | |
| 6 | rustc().env("RUSTC_FORCE_RUSTC_VERSION", "2").input("app.rs").run(); | |
| 12 | 7 | } |
tests/run-make/export/extern-opt/rmake.rs+3-5| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | use run_make_support::{rustc, dynamic_lib_name}; | |
| 1 | //@ needs-target-std | |
| 2 | use run_make_support::{dynamic_lib_name, rustc}; | |
| 2 | 3 | |
| 3 | 4 | fn main() { |
| 4 | rustc() | |
| 5 | .env("RUSTC_FORCE_RUSTC_VERSION", "1") | |
| 6 | .input("libr.rs") | |
| 7 | .run(); | |
| 5 | rustc().env("RUSTC_FORCE_RUSTC_VERSION", "1").input("libr.rs").run(); | |
| 8 | 6 | |
| 9 | 7 | rustc() |
| 10 | 8 | .env("RUSTC_FORCE_RUSTC_VERSION", "2") |
tests/run-make/export/simple/rmake.rs+3-8| ... | ... | @@ -1,12 +1,7 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::rustc; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
| 4 | rustc() | |
| 5 | .env("RUSTC_FORCE_RUSTC_VERSION", "1") | |
| 6 | .input("libr.rs") | |
| 7 | .run(); | |
| 8 | rustc() | |
| 9 | .env("RUSTC_FORCE_RUSTC_VERSION", "2") | |
| 10 | .input("app.rs") | |
| 11 | .run(); | |
| 5 | rustc().env("RUSTC_FORCE_RUSTC_VERSION", "1").input("libr.rs").run(); | |
| 6 | rustc().env("RUSTC_FORCE_RUSTC_VERSION", "2").input("app.rs").run(); | |
| 12 | 7 | } |
tests/run-make/extern-diff-internal-name/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // In the following scenario: |
| 2 | 4 | // 1. The crate foo, is referenced multiple times |
| 3 | 5 | // 2. --extern foo=./path/to/libbar.rlib is specified to rustc |
tests/run-make/extern-flag-fun/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // The --extern flag can override the default crate search of |
| 2 | 4 | // the compiler and directly fetch a given path. There are a few rules |
| 3 | 5 | // to follow: for example, there can't be more than one rlib, the crates must |
tests/run-make/extern-flag-rename-transitive/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // In this test, baz.rs is looking for an extern crate "a" which |
| 2 | 4 | // does not exist, and can only run through the --extern rustc flag |
| 3 | 5 | // defining that the "a" crate is in fact just "foo". This test |
tests/run-make/extern-multiple-copies/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // In this test, the rust library foo1 exists in two different locations, but only one |
| 2 | 4 | // is required by the --extern flag. This test checks that the copy is ignored (as --extern |
| 3 | 5 | // demands fetching only the original instance of foo1) and that no error is emitted, resulting |
tests/run-make/extern-multiple-copies2/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Almost identical to `extern-multiple-copies`, but with a variation in the --extern calls |
| 2 | 4 | // and the addition of #[macro_use] in the rust code files, which used to break --extern |
| 3 | 5 | // until #33625. |
tests/run-make/ice-static-mir/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Trying to access mid-level internal representation (MIR) in statics |
| 2 | 4 | // used to cause an internal compiler error (ICE), now handled as a proper |
| 3 | 5 | // error since #100211. This test checks that the correct error is printed |
tests/run-make/include-all-symbols-linking/rmake.rs+1| ... | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | // See https://github.com/rust-lang/rust/pull/95604 |
| 8 | 8 | // See https://github.com/rust-lang/rust/issues/47384 |
| 9 | 9 | |
| 10 | //@ needs-target-std | |
| 10 | 11 | //@ ignore-wasm differences in object file formats causes errors in the llvm_objdump step. |
| 11 | 12 | //@ ignore-windows differences in object file formats causes errors in the llvm_objdump step. |
| 12 | 13 |
tests/run-make/include-bytes-deps/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // include_bytes! and include_str! in `main.rs` |
| 2 | 4 | // should register the included file as of #24423, |
| 3 | 5 | // and this test checks that this is still the case. |
tests/run-make/incremental-debugger-visualizer/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This test ensures that changes to files referenced via #[debugger_visualizer] |
| 2 | 4 | // (in this case, foo.py and foo.natvis) are picked up when compiling incrementally. |
| 3 | 5 | // See https://github.com/rust-lang/rust/pull/111641 |
tests/run-make/inline-always-many-cgu/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use std::ffi::OsStr; |
| 2 | 3 | |
| 3 | 4 | use run_make_support::regex::Regex; |
tests/run-make/invalid-so/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // When a fake library was given to the compiler, it would |
| 2 | 4 | // result in an obscure and unhelpful error message. This test |
| 3 | 5 | // creates a false "foo" dylib, and checks that the standard error |
tests/run-make/invalid-staticlib/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // If the static library provided is not valid (in this test, |
| 2 | 4 | // created as an empty file), |
| 3 | 5 | // rustc should print a normal error message and not throw |
tests/run-make/invalid-symlink-search-path/rmake.rs+1| ... | ... | @@ -5,6 +5,7 @@ |
| 5 | 5 | // |
| 6 | 6 | // See https://github.com/rust-lang/rust/issues/26006 |
| 7 | 7 | |
| 8 | //@ needs-target-std | |
| 8 | 9 | //@ needs-symlink |
| 9 | 10 | //Reason: symlink requires elevated permission in Windows |
| 10 | 11 |
tests/run-make/invalid-tmpdir-env-var/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // When the TMP (on Windows) or TMPDIR (on Unix) variable is set to an invalid |
| 2 | 4 | // or non-existing directory, this used to cause an internal compiler error (ICE). After the |
| 3 | 5 | // addition of proper error handling in #28430, this test checks that the expected message is |
tests/run-make/issue-107495-archive-permissions/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | #[cfg(unix)] |
| 2 | 3 | use std::os::unix::fs::PermissionsExt; |
| 3 | 4 | use std::path::Path; |
tests/run-make/issue-125484-used-dependencies/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Non-regression test for issues #125474, #125484, #125646, with the repro taken from #125484. Some |
| 2 | 4 | // queries use "used dependencies" while others use "speculatively loaded dependencies", and an |
| 3 | 5 | // indexing ICE appeared in some cases when these were unexpectedly used in the same context. |
tests/run-make/json-error-no-offset/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // The byte positions in json format error logging used to have a small, difficult |
| 2 | 4 | // to predict offset. This was changed to be the top of the file every time in #42973, |
| 3 | 5 | // and this test checks that the measurements appearing in the standard error are correct. |
tests/run-make/lib-trait-for-trait-no-ice/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Inside a library, implementing a trait for another trait |
| 2 | 4 | // with a lifetime used to cause an internal compiler error (ICE). |
| 3 | 5 | // This test checks that this bug does not make a resurgence - |
tests/run-make/link-arg/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // In 2016, the rustc flag "-C link-arg" was introduced - it can be repeatedly used |
| 2 | 4 | // to add single arguments to the linker. This test passes 2 arguments to the linker using it, |
| 3 | 5 | // then checks that the compiler's output contains the arguments passed to it. |
tests/run-make/link-args-order/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Passing linker arguments to the compiler used to be lost or reordered in a messy way |
| 2 | 4 | // as they were passed further to the linker. This was fixed in #70665, and this test |
| 3 | 5 | // checks that linker arguments remain intact and in the order they were originally passed in. |
tests/run-make/link-dedup/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // When native libraries are passed to the linker, there used to be an annoyance |
| 2 | 4 | // where multiple instances of the same library in a row would cause duplication in |
| 3 | 5 | // outputs. This has been fixed, and this test checks that it stays fixed. |
tests/run-make/linker-warning/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::{Rustc, diff, regex, rustc}; |
| 2 | 3 | |
| 3 | 4 | fn run_rustc() -> Rustc { |
tests/run-make/llvm-outputs/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | // test that directories get created when emitting llvm bitcode and IR |
| 2 | 3 | |
| 3 | 4 | use std::path::PathBuf; |
tests/run-make/lto-avoid-object-duplication/rmake.rs+1| ... | ... | @@ -8,6 +8,7 @@ |
| 8 | 8 | // This test makes sure that functions defined in the upstream crates do not |
| 9 | 9 | // appear twice in the final staticlib when listing all the symbols from it. |
| 10 | 10 | |
| 11 | //@ needs-target-std | |
| 11 | 12 | //@ ignore-windows |
| 12 | 13 | // Reason: `llvm-objdump`'s output looks different on windows than on other platforms. |
| 13 | 14 | // Only checking on Unix platforms should suffice. |
tests/run-make/manual-crate-name/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::{path, rustc}; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
tests/run-make/many-crates-but-no-match/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // An extended version of the ui/changing-crates.rs test, this test puts |
| 2 | 4 | // multiple mismatching crates into the search path of crateC (A2 and A3) |
| 3 | 5 | // and checks that the standard error contains helpful messages to indicate |
tests/run-make/metadata-dep-info/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Emitting dep-info alongside metadata would present subtle discrepancies |
| 2 | 4 | // in the output file, such as the filename transforming underscores_ into hyphens-. |
| 3 | 5 | // After the fix in #114750, this test checks that the emitted files are identical |
tests/run-make/metadata-only-crate-no-ice/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // In a dependency hierarchy, metadata-only crates could cause an Internal |
| 2 | 4 | // Compiler Error (ICE) due to a compiler bug - not correctly fetching sources for |
| 3 | 5 | // metadata-only crates. This test is a minimal reproduction of a program that triggered |
tests/run-make/missing-crate-dependency/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // A simple smoke test to check that rustc fails compilation |
| 2 | 4 | // and outputs a helpful message when a dependency is missing |
| 3 | 5 | // in a dependency chain. |
tests/run-make/multiple-emits/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::{path, rustc}; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
tests/run-make/native-lib-alt-naming/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // On MSVC the alternative naming format for static libraries (`libfoo.a`) is accepted in addition |
| 2 | 4 | // to the default format (`foo.lib`). |
| 3 | 5 |
tests/run-make/native-link-modifier-verbatim-linker/rmake.rs+1| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | // This test is the same as native-link-modifier-rustc, but without rlibs. |
| 4 | 4 | // See https://github.com/rust-lang/rust/issues/99425 |
| 5 | 5 | |
| 6 | //@ needs-target-std | |
| 6 | 7 | //@ ignore-apple |
| 7 | 8 | // Reason: linking fails due to the unusual ".ext" staticlib name. |
| 8 | 9 |
tests/run-make/native-link-modifier-verbatim-rustc/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // `verbatim` is a native link modifier that forces rustc to only accept libraries with |
| 2 | 4 | // a specified name. This test checks that this modifier works as intended. |
| 3 | 5 | // This test is the same as native-link-modifier-linker, but with rlibs. |
tests/run-make/no-builtins-attribute/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // `no_builtins` is an attribute related to LLVM's optimizations. In order to ensure that it has an |
| 2 | 4 | // effect on link-time optimizations (LTO), it should be added to function declarations in a crate. |
| 3 | 5 | // This test uses the `llvm-filecheck` tool to determine that this attribute is successfully |
tests/run-make/no-builtins-lto/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // The rlib produced by a no_builtins crate should be explicitly linked |
| 2 | 4 | // during compilation, and as a result be present in the linker arguments. |
| 3 | 5 | // See the comments inside this file for more details. |
tests/run-make/non-unicode-env/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::{rfs, rustc}; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
tests/run-make/non-unicode-in-incremental-dir/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::{rfs, rustc}; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
tests/run-make/notify-all-emit-artifacts/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // rust should produce artifact notifications about files it was asked to --emit. |
| 2 | 4 | // |
| 3 | 5 | // It should work in incremental mode both on the first pass where files are generated as well |
tests/run-make/optimization-remarks-dir/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // In this test, the function `bar` has #[inline(never)] and the function `foo` |
| 2 | 4 | // does not. This test outputs LLVM optimization remarks twice - first for all |
| 3 | 5 | // functions (including `bar`, and the `inline` mention), and then for only `foo` |
tests/run-make/overwrite-input/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // An attempt to set the output `-o` into a directory or a file we cannot write into should indeed |
| 2 | 4 | // be an error; but not an ICE (Internal Compiler Error). This test attempts both and checks |
| 3 | 5 | // that the standard error matches what is expected. |
tests/run-make/parallel-rustc-no-overwrite/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // When two instances of rustc are invoked in parallel, they |
| 2 | 4 | // can conflict on their temporary files and overwrite each others', |
| 3 | 5 | // leading to unsuccessful compilation. The -Z temps-dir flag adds |
tests/run-make/pass-linker-flags-from-dep/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // A similar test to pass-linker-flags, testing that the `-l link-arg` flag |
| 2 | 4 | // respects the order relative to other `-l` flags, but this time, the flags |
| 3 | 5 | // are passed on the compilation of a dependency. This test checks that the |
tests/run-make/pass-linker-flags/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This test checks the proper function of `-l link-arg=NAME`, which, unlike |
| 2 | 4 | // -C link-arg, is supposed to guarantee that the order relative to other -l |
| 3 | 5 | // options will be respected. In this test, compilation fails (because none of the |
tests/run-make/pgo-gen-no-imp-symbols/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // LLVM's profiling instrumentation adds a few symbols that are used by the profiler runtime. |
| 2 | 4 | // Since these show up as globals in the LLVM IR, the compiler generates dllimport-related |
| 3 | 5 | // __imp_ stubs for them. This can lead to linker errors because the instrumentation |
tests/run-make/pretty-print-with-dep-file/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Passing --emit=dep-info to the Rust compiler should create a .d file... |
| 2 | 4 | // but it failed to do so in Rust 1.69.0 when combined with -Z unpretty=expanded |
| 3 | 5 | // due to a bug. This test checks that -Z unpretty=expanded does not prevent the |
tests/run-make/proc-macro-three-crates/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // A compiler bug caused the following issue: |
| 2 | 4 | // If a crate A depends on crate B, and crate B |
| 3 | 5 | // depends on crate C, and crate C contains a procedural |
tests/run-make/remap-path-prefix-dwarf/rmake.rs+1| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | // It tests several cases, each of them has a detailed description attached to it. |
| 5 | 5 | // See https://github.com/rust-lang/rust/pull/96867 |
| 6 | 6 | |
| 7 | //@ needs-target-std | |
| 7 | 8 | //@ ignore-windows |
| 8 | 9 | // Reason: the remap path prefix is not printed in the dwarf dump. |
| 9 | 10 |
tests/run-make/remap-path-prefix/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Generating metadata alongside remap-path-prefix would fail to actually remap the path |
| 2 | 4 | // in the metadata. After this was fixed in #85344, this test checks that "auxiliary" is being |
| 3 | 5 | // successfully remapped to "/the/aux" in the rmeta files. |
tests/run-make/repr128-dwarf/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | //@ ignore-windows |
| 2 | 3 | // This test should be replaced with one in tests/debuginfo once GDB or LLDB support 128-bit enums. |
| 3 | 4 |
tests/run-make/reproducible-build-2/rmake.rs+1| ... | ... | @@ -6,6 +6,7 @@ |
| 6 | 6 | // Outputs should be identical. |
| 7 | 7 | // See https://github.com/rust-lang/rust/issues/34902 |
| 8 | 8 | |
| 9 | //@ needs-target-std | |
| 9 | 10 | //@ ignore-windows |
| 10 | 11 | // Reasons: |
| 11 | 12 | // 1. The object files are reproducible, but their paths are not, which causes |
tests/run-make/resolve-rename/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // If a library is compiled with -C extra-filename, the rust compiler |
| 2 | 4 | // will take this into account when searching for libraries. However, |
| 3 | 5 | // if that library is then renamed, the rust compiler should fall back |
tests/run-make/rlib-format-packed-bundled-libs-2/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler |
| 2 | 4 | // only require a native library and no supplementary object files to compile. |
| 3 | 5 | // This test simply checks that this flag can be passed alongside verbatim syntax |
tests/run-make/rustc-macro-dep-files/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // --emit dep-info used to print all macro-generated code it could |
| 2 | 4 | // find as if it was part of a nonexistent file named "proc-macro source", |
| 3 | 5 | // which is not a valid path. After this was fixed in #36776, this test checks |
tests/run-make/rustdoc-scrape-examples-invalid-expr/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] |
| 2 | 3 | mod scrape; |
| 3 | 4 |
tests/run-make/rustdoc-scrape-examples-multiple/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] |
| 2 | 3 | mod scrape; |
| 3 | 4 |
tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] |
| 2 | 3 | mod scrape; |
| 3 | 4 |
tests/run-make/rustdoc-scrape-examples-remap/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | mod scrape; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
tests/run-make/rustdoc-scrape-examples-test/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] |
| 2 | 3 | mod scrape; |
| 3 | 4 |
tests/run-make/rustdoc-scrape-examples-whitespace/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | #[path = "../rustdoc-scrape-examples-remap/scrape.rs"] |
| 2 | 3 | mod scrape; |
| 3 | 4 |
tests/run-make/rustdoc-with-short-out-dir-option/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | use run_make_support::{htmldocck, rustdoc}; |
| 2 | 3 | |
| 3 | 4 | fn main() { |
tests/run-make/share-generics-dylib/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This test makes sure all generic instances get re-exported from Rust dylibs for use by |
| 2 | 4 | // `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`) |
| 3 | 5 | // which both provide an instance of `Cell<i32>::set`. There is `instance_user_dylib` which is |
tests/run-make/short-ice/rmake.rs+1| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | // was shortened down to an appropriate length. |
| 5 | 5 | // See https://github.com/rust-lang/rust/issues/107910 |
| 6 | 6 | |
| 7 | //@ needs-target-std | |
| 7 | 8 | //@ ignore-windows |
| 8 | 9 | // Reason: the assert_eq! on line 32 fails, as error output on Windows is different. |
| 9 | 10 |
tests/run-make/stable-symbol-names/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // A typo in rustc caused generic symbol names to be non-deterministic - |
| 2 | 4 | // that is, it was possible to compile the same file twice with no changes |
| 3 | 5 | // and get outputs with different symbol names. |
tests/run-make/staticlib-blank-lib/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // In this test, the static library foo is made blank, which used to cause |
| 2 | 4 | // a compilation error. As the compiler now returns Ok upon encountering a blank |
| 3 | 5 | // staticlib as of #12379, this test checks that compilation is successful despite |
tests/run-make/staticlib-broken-bitcode/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Regression test for https://github.com/rust-lang/rust/issues/128955#issuecomment-2657811196 |
| 2 | 4 | // which checks that rustc can read an archive containing LLVM bitcode with a |
| 3 | 5 | // newer version from the one rustc links against. |
tests/run-make/staticlib-thin-archive/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Regression test for https://github.com/rust-lang/rust/issues/107407 which |
| 2 | 4 | // checks that rustc can read thin archive. Before the object crate added thin |
| 3 | 5 | // archive support rustc would add emit object files to the staticlib and after |
tests/run-make/stdin-rustc/rmake.rs+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | //@ needs-target-std | |
| 1 | 2 | //! This test checks rustc `-` (stdin) support |
| 2 | 3 | |
| 3 | 4 | use std::path::PathBuf; |
tests/run-make/symbol-visibility/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Dynamic libraries on Rust used to export a very high amount of symbols, |
| 2 | 4 | // going as far as filling the output with mangled names and generic function |
| 3 | 5 | // names. After the rework of #38117, this test checks that no mangled Rust symbols |
tests/run-make/symbols-include-type-name/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Method names used to be obfuscated when exported into symbols, |
| 2 | 4 | // leaving only an obscure `<impl>`. After the fix in #30328, |
| 3 | 5 | // this test checks that method names are successfully saved in the symbol list. |
tests/run-make/track-path-dep-info/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This test checks the functionality of `tracked_path::path`, a procedural macro |
| 2 | 4 | // feature that adds a dependency to another file inside the procmacro. In this case, |
| 3 | 5 | // the text file is added through this method, and the test checks that the compilation |
tests/run-make/type-mismatch-same-crate-name/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // When a compilation failure deals with seemingly identical types, some helpful |
| 2 | 4 | // errors should be printed. |
| 3 | 5 | // The main use case of this error is when there are two crates |
tests/run-make/unknown-mod-stdin/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // Rustc displays a compilation error when it finds a `mod` (module) |
| 2 | 4 | // statement referencing a file that does not exist. However, a bug from 2019 |
| 3 | 5 | // caused invalid `mod` statements to silently insert empty inline modules |
tests/run-make/unstable-feature-usage-metrics-incremental/rmake.rs+1| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | //! - forked from dump-ice-to-disk test, which has flakeyness issues on i686-mingw, I'm assuming |
| 11 | 11 | //! those will be present in this test as well on the same platform |
| 12 | 12 | |
| 13 | //@ needs-target-std | |
| 13 | 14 | //@ ignore-windows |
| 14 | 15 | //FIXME(#128911): still flakey on i686-mingw. |
| 15 | 16 |
tests/run-make/unstable-feature-usage-metrics/rmake.rs+1| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | //! - forked from dump-ice-to-disk test, which has flakeyness issues on i686-mingw, I'm assuming |
| 11 | 11 | //! those will be present in this test as well on the same platform |
| 12 | 12 | |
| 13 | //@ needs-target-std | |
| 13 | 14 | //@ ignore-windows |
| 14 | 15 | //FIXME(#128911): still flakey on i686-mingw. |
| 15 | 16 |
tests/run-make/use-suggestions-rust-2018/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // The compilation error caused by calling on an unimported crate |
| 2 | 4 | // should have a suggestion to write, say, crate::bar::Foo instead |
| 3 | 5 | // of just bar::Foo. However, this suggestion used to only appear for |
tests/run-make/used/rmake.rs+2| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | //@ needs-target-std | |
| 2 | // | |
| 1 | 3 | // This test ensures that the compiler is keeping static variables, even if not referenced |
| 2 | 4 | // by another part of the program, in the output object file. |
| 3 | 5 | // |
tests/ui/abi/numbers-arithmetic/float-struct.rs created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | //@ run-pass | |
| 2 | ||
| 3 | use std::fmt::Debug; | |
| 4 | use std::hint::black_box; | |
| 5 | ||
| 6 | #[repr(C)] | |
| 7 | #[derive(Copy, Clone, PartialEq, Debug, Default)] | |
| 8 | struct Regular(f32, f64); | |
| 9 | ||
| 10 | #[repr(C, packed)] | |
| 11 | #[derive(Copy, Clone, PartialEq, Debug, Default)] | |
| 12 | struct Packed(f32, f64); | |
| 13 | ||
| 14 | #[repr(C, align(64))] | |
| 15 | #[derive(Copy, Clone, PartialEq, Debug, Default)] | |
| 16 | struct AlignedF32(f32); | |
| 17 | ||
| 18 | #[repr(C)] | |
| 19 | #[derive(Copy, Clone, PartialEq, Debug, Default)] | |
| 20 | struct Aligned(f64, AlignedF32); | |
| 21 | ||
| 22 | #[inline(never)] | |
| 23 | extern "C" fn read<T: Copy>(x: &T) -> T { | |
| 24 | *black_box(x) | |
| 25 | } | |
| 26 | ||
| 27 | #[inline(never)] | |
| 28 | extern "C" fn write<T: Copy>(x: T, dest: &mut T) { | |
| 29 | *dest = black_box(x) | |
| 30 | } | |
| 31 | ||
| 32 | #[track_caller] | |
| 33 | fn check<T: Copy + PartialEq + Debug + Default>(x: T) { | |
| 34 | assert_eq!(read(&x), x); | |
| 35 | let mut out = T::default(); | |
| 36 | write(x, &mut out); | |
| 37 | assert_eq!(out, x); | |
| 38 | } | |
| 39 | ||
| 40 | fn main() { | |
| 41 | check(Regular(1.0, 2.0)); | |
| 42 | check(Packed(3.0, 4.0)); | |
| 43 | check(Aligned(5.0, AlignedF32(6.0))); | |
| 44 | } |
tests/ui/parser/doc-comment-after-missing-comma-issue-142311.rs created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | //! Check that if the parser suggests converting `///` to a regular comment | |
| 2 | //! when it appears after a missing comma in an list (e.g. `enum` variants). | |
| 3 | //! | |
| 4 | //! Related issue | |
| 5 | //! - https://github.com/rust-lang/rust/issues/142311 | |
| 6 | ||
| 7 | enum Foo { | |
| 8 | /// Like the noise a sheep makes | |
| 9 | Bar | |
| 10 | /// Like where people drink | |
| 11 | //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `/// Like where people drink` | |
| 12 | Baa///xxxxxx | |
| 13 | //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `///xxxxxx` | |
| 14 | Baz///xxxxxx | |
| 15 | //~^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `///xxxxxx` | |
| 16 | } | |
| 17 | ||
| 18 | fn foo() { | |
| 19 | let a = [ | |
| 20 | 1///xxxxxx | |
| 21 | //~^ ERROR expected one of `,`, `.`, `;`, `?`, `]`, or an operator, found doc comment `///xxxxxx` | |
| 22 | 2 | |
| 23 | ]; | |
| 24 | } | |
| 25 | ||
| 26 | fn bar() { | |
| 27 | let a = [ | |
| 28 | 1, | |
| 29 | 2///xxxxxx | |
| 30 | //~^ ERROR expected one of `,`, `.`, `?`, `]`, or an operator, found doc comment `///xxxxxx` | |
| 31 | ]; | |
| 32 | } | |
| 33 | ||
| 34 | fn main() {} |
tests/ui/parser/doc-comment-after-missing-comma-issue-142311.stderr created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | error: expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `/// Like where people drink` | |
| 2 | --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:10:5 | |
| 3 | | | |
| 4 | LL | Bar | |
| 5 | | - | |
| 6 | | | | |
| 7 | | expected one of `(`, `,`, `=`, `{`, or `}` | |
| 8 | | help: missing `,` | |
| 9 | LL | /// Like where people drink | |
| 10 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unexpected token | |
| 11 | ||
| 12 | error: expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `///xxxxxx` | |
| 13 | --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:12:8 | |
| 14 | | | |
| 15 | LL | Baa///xxxxxx | |
| 16 | | -^^^^^^^^ | |
| 17 | | | | |
| 18 | | expected one of `(`, `,`, `=`, `{`, or `}` | |
| 19 | | help: missing `,` | |
| 20 | ||
| 21 | error: expected one of `(`, `,`, `=`, `{`, or `}`, found doc comment `///xxxxxx` | |
| 22 | --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:14:8 | |
| 23 | | | |
| 24 | LL | Baz///xxxxxx | |
| 25 | | ^^^^^^^^^ expected one of `(`, `,`, `=`, `{`, or `}` | |
| 26 | | | |
| 27 | = help: doc comments must come before what they document, if a comment was intended use `//` | |
| 28 | = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` | |
| 29 | ||
| 30 | error: expected one of `,`, `.`, `;`, `?`, `]`, or an operator, found doc comment `///xxxxxx` | |
| 31 | --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:20:10 | |
| 32 | | | |
| 33 | LL | 1///xxxxxx | |
| 34 | | ^^^^^^^^^ expected one of `,`, `.`, `;`, `?`, `]`, or an operator | |
| 35 | ||
| 36 | error: expected one of `,`, `.`, `?`, `]`, or an operator, found doc comment `///xxxxxx` | |
| 37 | --> $DIR/doc-comment-after-missing-comma-issue-142311.rs:29:10 | |
| 38 | | | |
| 39 | LL | 2///xxxxxx | |
| 40 | | ^^^^^^^^^ expected one of `,`, `.`, `?`, `]`, or an operator | |
| 41 | ||
| 42 | error: aborting due to 5 previous errors | |
| 43 |