diff --git a/compiler/rustc_ast/src/util/comments/tests.rs b/compiler/rustc_ast/src/util/comments/tests.rs index 61bb2468e79b9..f88b534a0c114 100644 --- a/compiler/rustc_ast/src/util/comments/tests.rs +++ b/compiler/rustc_ast/src/util/comments/tests.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + use rustc_span::create_default_session_globals_then; use super::*; diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index fc44340851c47..25d4146255647 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -94,8 +94,7 @@ mod styled_buffer; mod tests; pub mod translation; -pub type PErr<'a> = Diag<'a>; -pub type PResult<'a, T> = Result>; +pub type PResult<'a, T> = Result>; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } @@ -576,6 +575,10 @@ pub enum StashKey { UndeterminedMacroResolution, /// Used by `Parser::maybe_recover_trailing_expr` ExprInPat, + /// If in the parser we detect a field expr with turbofish generic params it's possible that + /// it's a method call without parens. If later on in `hir_typeck` we find out that this is + /// the case we suppress this message and we give a better suggestion. + GenericInFieldExpr, } fn default_track_diagnostic(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R { diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs index 5c10fa4697156..953e48a6d3347 100644 --- a/compiler/rustc_hir/src/tests.rs +++ b/compiler/rustc_hir/src/tests.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + use rustc_data_structures::stable_hasher::Hash64; use rustc_span::def_id::{DefPathHash, StableCrateId}; use rustc_span::edition::Edition; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index df4da03f0f59d..90e93bdbb5075 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -3,6 +3,7 @@ use std::assert_matches::debug_assert_matches; use rustc_abi::FieldIdx; use rustc_ast::InlineAsmTemplatePiece; use rustc_data_structures::fx::FxIndexSet; +use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem}; use rustc_middle::bug; use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; @@ -21,6 +22,12 @@ pub struct InlineAsmCtxt<'a, 'tcx> { get_operand_ty: Box) -> Ty<'tcx> + 'a>, } +enum NonAsmTypeReason<'tcx> { + UnevaluatedSIMDArrayLength(DefId, ty::Const<'tcx>), + Invalid(Ty<'tcx>), + InvalidElement(DefId, Ty<'tcx>), +} + impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self { InlineAsmCtxt { @@ -56,7 +63,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { false } - fn get_asm_ty(&self, ty: Ty<'tcx>) -> Option { + fn get_asm_ty(&self, ty: Ty<'tcx>) -> Result> { let asm_ty_isize = match self.tcx.sess.target.pointer_width { 16 => InlineAsmType::I16, 32 => InlineAsmType::I32, @@ -65,64 +72,62 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { }; match *ty.kind() { - ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8), - ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16), - ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32), - ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64), - ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128), - ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize), - ty::Float(FloatTy::F16) => Some(InlineAsmType::F16), - ty::Float(FloatTy::F32) => Some(InlineAsmType::F32), - ty::Float(FloatTy::F64) => Some(InlineAsmType::F64), - ty::Float(FloatTy::F128) => Some(InlineAsmType::F128), - ty::FnPtr(..) => Some(asm_ty_isize), - ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize), + ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Ok(InlineAsmType::I8), + ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Ok(InlineAsmType::I16), + ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Ok(InlineAsmType::I32), + ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Ok(InlineAsmType::I64), + ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Ok(InlineAsmType::I128), + ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Ok(asm_ty_isize), + ty::Float(FloatTy::F16) => Ok(InlineAsmType::F16), + ty::Float(FloatTy::F32) => Ok(InlineAsmType::F32), + ty::Float(FloatTy::F64) => Ok(InlineAsmType::F64), + ty::Float(FloatTy::F128) => Ok(InlineAsmType::F128), + ty::FnPtr(..) => Ok(asm_ty_isize), + ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Ok(asm_ty_isize), ty::Adt(adt, args) if adt.repr().simd() => { let fields = &adt.non_enum_variant().fields; - let elem_ty = fields[FieldIdx::ZERO].ty(self.tcx, args); + let field = &fields[FieldIdx::ZERO]; + let elem_ty = field.ty(self.tcx, args); let (size, ty) = match elem_ty.kind() { ty::Array(ty, len) => { + let len = self.tcx.normalize_erasing_regions(self.typing_env, *len); if let Some(len) = len.try_to_target_usize(self.tcx) { (len, *ty) } else { - return None; + return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength( + field.did, len, + )); } } _ => (fields.len() as u64, elem_ty), }; match ty.kind() { - ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::VecI8(size)), - ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => { - Some(InlineAsmType::VecI16(size)) - } - ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => { - Some(InlineAsmType::VecI32(size)) - } - ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => { - Some(InlineAsmType::VecI64(size)) - } + ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Ok(InlineAsmType::VecI8(size)), + ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Ok(InlineAsmType::VecI16(size)), + ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Ok(InlineAsmType::VecI32(size)), + ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Ok(InlineAsmType::VecI64(size)), ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => { - Some(InlineAsmType::VecI128(size)) + Ok(InlineAsmType::VecI128(size)) } ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => { - Some(match self.tcx.sess.target.pointer_width { + Ok(match self.tcx.sess.target.pointer_width { 16 => InlineAsmType::VecI16(size), 32 => InlineAsmType::VecI32(size), 64 => InlineAsmType::VecI64(size), width => bug!("unsupported pointer width: {width}"), }) } - ty::Float(FloatTy::F16) => Some(InlineAsmType::VecF16(size)), - ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)), - ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(size)), - ty::Float(FloatTy::F128) => Some(InlineAsmType::VecF128(size)), - _ => None, + ty::Float(FloatTy::F16) => Ok(InlineAsmType::VecF16(size)), + ty::Float(FloatTy::F32) => Ok(InlineAsmType::VecF32(size)), + ty::Float(FloatTy::F64) => Ok(InlineAsmType::VecF64(size)), + ty::Float(FloatTy::F128) => Ok(InlineAsmType::VecF128(size)), + _ => Err(NonAsmTypeReason::InvalidElement(field.did, ty)), } } ty::Infer(_) => bug!("unexpected infer ty in asm operand"), - _ => None, + _ => Err(NonAsmTypeReason::Invalid(ty)), } } @@ -163,17 +168,42 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } _ => self.get_asm_ty(ty), }; - let Some(asm_ty) = asm_ty else { - let msg = format!("cannot use value of type `{ty}` for inline assembly"); - self.tcx - .dcx() - .struct_span_err(expr.span, msg) - .with_note( - "only integers, floats, SIMD vectors, pointers and function pointers \ - can be used as arguments for inline assembly", - ) - .emit(); - return None; + let asm_ty = match asm_ty { + Ok(asm_ty) => asm_ty, + Err(reason) => { + match reason { + NonAsmTypeReason::UnevaluatedSIMDArrayLength(did, len) => { + let msg = format!("cannot evaluate SIMD vector length `{len}`"); + self.tcx + .dcx() + .struct_span_err(self.tcx.def_span(did), msg) + .with_span_note( + expr.span, + "SIMD vector length needs to be known statically for use in `asm!`", + ) + .emit(); + } + NonAsmTypeReason::Invalid(ty) => { + let msg = format!("cannot use value of type `{ty}` for inline assembly"); + self.tcx.dcx().struct_span_err(expr.span, msg).with_note( + "only integers, floats, SIMD vectors, pointers and function pointers \ + can be used as arguments for inline assembly", + ).emit(); + } + NonAsmTypeReason::InvalidElement(did, ty) => { + let msg = format!( + "cannot use SIMD vector with element type `{ty}` for inline assembly" + ); + self.tcx.dcx() + .struct_span_err(self.tcx.def_span(did), msg).with_span_note( + expr.span, + "only integers, floats, SIMD vectors, pointers and function pointers \ + can be used as arguments for inline assembly", + ).emit(); + } + } + return None; + } }; // Check that the type implements Copy. The only case where this can diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b3ce1df3defbc..569038652777b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3076,7 +3076,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.help("methods are immutable and cannot be assigned to"); } - err.emit() + // See `StashKey::GenericInFieldExpr` for more info + self.dcx().try_steal_replace_and_emit_err(field.span, StashKey::GenericInFieldExpr, err) } fn point_at_param_definition(&self, err: &mut Diag<'_>, param: ty::ParamTy) { diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index ddd146fe785e3..b57c248ed2bf1 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -613,19 +613,16 @@ impl<'tcx> AnnotateUnitFallbackVisitor<'_, 'tcx> { if arg_segment.args.is_none() && let Some(all_args) = self.fcx.typeck_results.borrow().node_args_opt(id) && let generics = self.fcx.tcx.generics_of(def_id) - && let args = &all_args[generics.parent_count..] + && let args = all_args[generics.parent_count..].iter().zip(&generics.own_params) // We can't turbofish consts :( - && args.iter().all(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_) | ty::GenericArgKind::Lifetime(_))) + && args.clone().all(|(_, param)| matches!(param.kind, ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Lifetime)) { - let n_tys = args - .iter() - .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_))) - .count(); - for (idx, arg) in args - .iter() - .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_))) - .enumerate() - { + // We filter out APITs, which are not turbofished. + let non_apit_type_args = args.filter(|(_, param)| { + matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: false, .. }) + }); + let n_tys = non_apit_type_args.clone().count(); + for (idx, (arg, _)) in non_apit_type_args.enumerate() { if let Some(ty) = arg.as_type() && let Some(vid) = self.fcx.root_vid(ty) && self.reachable_vids.contains(&vid) diff --git a/compiler/rustc_lint/src/tests.rs b/compiler/rustc_lint/src/tests.rs index 7fbf381a8d321..186dec5904b49 100644 --- a/compiler/rustc_lint/src/tests.rs +++ b/compiler/rustc_lint/src/tests.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + use rustc_span::{Symbol, create_default_session_globals_then}; use crate::levels::parse_lint_and_tool_name; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs index df4c0593246cf..d79d2c316ee78 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs @@ -4,52 +4,26 @@ //! field-deref on a local variable, `x.field`, has the same meaning //! in both domains). Indexed projections are the exception: `a[x]` //! needs to be treated as mapping to the same move path as `a[y]` as -//! well as `a[13]`, etc. +//! well as `a[13]`, etc. So we map these `x`/`y` values to `()`. //! //! (In theory, the analysis could be extended to work with sets of //! paths, so that `a[0]` and `a[13]` could be kept distinct, while //! `a[x]` would still overlap them both. But that is not this //! representation does today.) -use rustc_middle::mir::{Local, Operand, PlaceElem, ProjectionElem}; -use rustc_middle::ty::Ty; - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub(crate) struct AbstractOperand; -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub(crate) struct AbstractType; -pub(crate) type AbstractElem = ProjectionElem; +use rustc_middle::mir::{PlaceElem, ProjectionElem, ProjectionKind}; pub(crate) trait Lift { - type Abstract; - fn lift(&self) -> Self::Abstract; -} -impl<'tcx> Lift for Operand<'tcx> { - type Abstract = AbstractOperand; - fn lift(&self) -> Self::Abstract { - AbstractOperand - } -} -impl Lift for Local { - type Abstract = AbstractOperand; - fn lift(&self) -> Self::Abstract { - AbstractOperand - } -} -impl<'tcx> Lift for Ty<'tcx> { - type Abstract = AbstractType; - fn lift(&self) -> Self::Abstract { - AbstractType - } + fn lift(&self) -> ProjectionKind; } + impl<'tcx> Lift for PlaceElem<'tcx> { - type Abstract = AbstractElem; - fn lift(&self) -> Self::Abstract { + fn lift(&self) -> ProjectionKind { match *self { ProjectionElem::Deref => ProjectionElem::Deref, - ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty.lift()), - ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty.lift()), - ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()), + ProjectionElem::Field(f, _ty) => ProjectionElem::Field(f, ()), + ProjectionElem::OpaqueCast(_ty) => ProjectionElem::OpaqueCast(()), + ProjectionElem::Index(_i) => ProjectionElem::Index(()), ProjectionElem::Subslice { from, to, from_end } => { ProjectionElem::Subslice { from, to, from_end } } @@ -57,7 +31,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> { ProjectionElem::ConstantIndex { offset, min_length, from_end } } ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u), - ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(ty.lift()), + ProjectionElem::Subtype(_ty) => ProjectionElem::Subtype(()), } } } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 926bd187431e6..8aea8d2ae3ca7 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::{Ty, TyCtxt}; use rustc_span::Span; use smallvec::SmallVec; -use self::abs_domain::{AbstractElem, Lift}; +use self::abs_domain::Lift; use crate::un_derefer::UnDerefer; mod abs_domain; @@ -300,7 +300,7 @@ pub struct MovePathLookup<'tcx> { /// subsequent search so that it is solely relative to that /// base-place). For the remaining lookup, we map the projection /// elem to the associated MovePathIndex. - projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>, + projections: FxHashMap<(MovePathIndex, ProjectionKind), MovePathIndex>, un_derefer: UnDerefer<'tcx>, } diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index c6c9eb3b0b263..ee38f16d4ecd5 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -1,7 +1,7 @@ use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast_pretty::pprust::token_to_string; -use rustc_errors::{Applicability, PErr}; +use rustc_errors::{Applicability, Diag}; use rustc_span::symbol::kw; use super::diagnostics::{report_suspicious_mismatch_block, same_indentation_level}; @@ -14,7 +14,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { pub(super) fn lex_token_trees( &mut self, is_delimited: bool, - ) -> (Spacing, TokenStream, Result<(), Vec>>) { + ) -> (Spacing, TokenStream, Result<(), Vec>>) { // Move past the opening delimiter. let open_spacing = self.bump_minimal(); @@ -56,7 +56,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { } } - fn eof_err(&mut self) -> PErr<'psess> { + fn eof_err(&mut self) -> Diag<'psess> { let msg = "this file contains an unclosed delimiter"; let mut err = self.dcx().struct_span_err(self.token.span, msg); @@ -98,7 +98,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { fn lex_token_tree_open_delim( &mut self, open_delim: Delimiter, - ) -> Result>> { + ) -> Result>> { // The span for beginning of the delimited section. let pre_span = self.token.span; @@ -250,8 +250,8 @@ impl<'psess, 'src> Lexer<'psess, 'src> { fn unclosed_delim_err( &mut self, tts: TokenStream, - mut errs: Vec>, - ) -> Vec> { + mut errs: Vec>, + ) -> Vec> { // If there are unclosed delims, see if there are diff markers and if so, point them // out instead of complaining about the unclosed delims. let mut parser = Parser::new(self.psess, tts, None); @@ -308,7 +308,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { errs } - fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> { + fn close_delim_err(&mut self, delim: Delimiter) -> Diag<'psess> { // An unexpected closing delimiter (i.e., there is no matching opening delimiter). let token_str = token_to_string(&self.token); let msg = format!("unexpected closing delimiter: `{token_str}`"); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 34131e3af6e2c..e5edf605d823e 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -16,7 +16,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, PErr, PResult, Subdiagnostic, + Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, PResult, Subdiagnostic, Suggestions, pluralize, }; use rustc_session::errors::ExprParenthesesNeeded; @@ -2132,7 +2132,7 @@ impl<'a> Parser<'a> { &mut self, delim: Delimiter, lo: Span, - err: PErr<'a>, + err: Diag<'a>, ) -> P { let guar = err.emit(); // Recover from parse error, callers expect the closing delim to be consumed. @@ -3014,7 +3014,7 @@ impl<'a> Parser<'a> { } /// Check for exclusive ranges written as `..<` - pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: PErr<'a>) -> PErr<'a> { + pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: Diag<'a>) -> Diag<'a> { if maybe_lt == token::Lt && (self.expected_tokens.contains(&TokenType::Token(token::Gt)) || matches!(self.token.kind, token::Literal(..))) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index eeb83a85e59bb..0904a42d8a431 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1369,11 +1369,14 @@ impl<'a> Parser<'a> { )) } else { // Field access `expr.f` + let span = lo.to(self.prev_token.span); if let Some(args) = seg.args { - self.dcx().emit_err(errors::FieldExpressionWithGeneric(args.span())); + // See `StashKey::GenericInFieldExpr` for more info on why we stash this. + self.dcx() + .create_err(errors::FieldExpressionWithGeneric(args.span())) + .stash(seg.ident.span, StashKey::GenericInFieldExpr); } - let span = lo.to(self.prev_token.span); Ok(self.mk_expr(span, ExprKind::Field(self_arg, seg.ident))) } } diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index decaecd2682ce..1813960dad05f 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + use std::assert_matches::assert_matches; use std::io::prelude::*; use std::iter::Peekable; diff --git a/compiler/rustc_parse/src/parser/tokenstream/tests.rs b/compiler/rustc_parse/src/parser/tokenstream/tests.rs index efe266f529057..b13b68c266a0e 100644 --- a/compiler/rustc_parse/src/parser/tokenstream/tests.rs +++ b/compiler/rustc_parse/src/parser/tokenstream/tests.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + use rustc_ast::token::{self, IdentIsRaw}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_span::{BytePos, Span, Symbol, create_default_session_globals_then}; diff --git a/compiler/rustc_span/src/edit_distance/tests.rs b/compiler/rustc_span/src/edit_distance/tests.rs index c9c7a1f1bf2f6..9540f934d7ebe 100644 --- a/compiler/rustc_span/src/edit_distance/tests.rs +++ b/compiler/rustc_span/src/edit_distance/tests.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(bootstrap), allow(rustc::symbol_intern_string_literal))] + use super::*; #[test] diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs index d5acd37092a0a..4f370ec8bd032 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs @@ -42,6 +42,8 @@ pub(crate) fn opts() -> TargetOptions { eh_frame_header: false, no_default_libraries: false, has_thread_local: true, + crt_static_allows_dylibs: true, + crt_static_respected: true, // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. debuginfo_kind: DebuginfoKind::Pdb, diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 04b7315e650a2..ae34fc653260e 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -10,9 +10,6 @@ use core::hint; #[cfg(not(test))] use core::ptr::{self, NonNull}; -#[cfg(test)] -mod tests; - extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 5d3997e14e3e9..116e0e73e9659 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -155,9 +155,6 @@ use crate::collections::TryReserveError; use crate::slice; use crate::vec::{self, AsVecIntoIter, Vec}; -#[cfg(test)] -mod tests; - /// A priority queue implemented with a binary heap. /// /// This will be a max-heap. diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 9c074383a5ecb..c7d6d8a55c2e3 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -1,8 +1,5 @@ //! [`CString`] and its related types. -#[cfg(test)] -mod tests; - use core::borrow::Borrow; use core::ffi::{CStr, c_char}; use core::num::NonZero; diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 927c3aa23b9f7..78cdeeb2866ef 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -239,8 +239,6 @@ pub mod string; pub mod sync; #[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))] pub mod task; -#[cfg(test)] -mod tests; pub mod vec; #[doc(hidden)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b8bdd298c27ab..6cf41a3fa4e16 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -39,9 +39,6 @@ use crate::string::String; #[cfg(not(no_global_oom_handling))] use crate::vec::Vec; -#[cfg(test)] -mod tests; - /// A soft limit on the amount of references that may be made to an `Arc`. /// /// Going above this limit will abort your program (although not diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/tests/alloc.rs similarity index 93% rename from library/alloc/src/alloc/tests.rs rename to library/alloc/tests/alloc.rs index 5d6077f057a2c..1e722d667955c 100644 --- a/library/alloc/src/alloc/tests.rs +++ b/library/alloc/tests/alloc.rs @@ -1,10 +1,9 @@ -use super::*; +use alloc::alloc::*; +use alloc::boxed::Box; extern crate test; use test::Bencher; -use crate::boxed::Box; - #[test] fn allocate_zeroed() { unsafe { diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/tests/c_str2.rs similarity index 98% rename from library/alloc/src/ffi/c_str/tests.rs rename to library/alloc/tests/c_str2.rs index d6b797347c2ec..0f4c27fa12322 100644 --- a/library/alloc/src/ffi/c_str/tests.rs +++ b/library/alloc/tests/c_str2.rs @@ -1,11 +1,12 @@ +use alloc::ffi::CString; +use alloc::rc::Rc; +use alloc::sync::Arc; use core::assert_matches::assert_matches; -use core::ffi::FromBytesUntilNulError; +use core::ffi::{CStr, FromBytesUntilNulError, c_char}; #[allow(deprecated)] use core::hash::SipHasher13 as DefaultHasher; use core::hash::{Hash, Hasher}; -use super::*; - #[test] fn c_to_rust() { let data = b"123\0"; diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/tests/collections/binary_heap.rs similarity index 99% rename from library/alloc/src/collections/binary_heap/tests.rs rename to library/alloc/tests/collections/binary_heap.rs index ad0a020a1a961..55405ffe8c4f6 100644 --- a/library/alloc/src/collections/binary_heap/tests.rs +++ b/library/alloc/tests/collections/binary_heap.rs @@ -1,7 +1,9 @@ +use alloc::boxed::Box; +use alloc::collections::binary_heap::*; +use std::iter::TrustedLen; +use std::mem; use std::panic::{AssertUnwindSafe, catch_unwind}; -use super::*; -use crate::boxed::Box; use crate::testing::crash_test::{CrashTestDummy, Panic}; #[test] @@ -531,7 +533,7 @@ fn panic_safe() { self.0.partial_cmp(&other.0) } } - let mut rng = crate::test_helpers::test_rng(); + let mut rng = crate::test_rng(); const DATASZ: usize = 32; // Miri is too slow let ntest = if cfg!(miri) { 1 } else { 10 }; diff --git a/library/alloc/tests/collections/mod.rs b/library/alloc/tests/collections/mod.rs new file mode 100644 index 0000000000000..e73f3aaef8c83 --- /dev/null +++ b/library/alloc/tests/collections/mod.rs @@ -0,0 +1 @@ +mod binary_heap; diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index bcab17e7b2ddc..393bdfe48b741 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -5,8 +5,10 @@ #![feature(btree_extract_if)] #![feature(cow_is_borrowed)] #![feature(core_intrinsics)] +#![feature(downcast_unchecked)] #![feature(extract_if)] #![feature(exact_size_is_empty)] +#![feature(hashmap_internals)] #![feature(linked_list_cursors)] #![feature(map_try_insert)] #![feature(pattern)] @@ -29,9 +31,11 @@ #![feature(const_str_from_utf8)] #![feature(panic_update_hook)] #![feature(pointer_is_aligned_to)] +#![feature(test)] #![feature(thin_box)] #![feature(drain_keep_rest)] #![feature(local_waker)] +#![feature(str_as_str)] #![feature(strict_provenance_lints)] #![feature(vec_pop_if)] #![feature(unique_rc_arc)] @@ -40,25 +44,33 @@ #![deny(fuzzy_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] +extern crate test; + use std::hash::{DefaultHasher, Hash, Hasher}; +mod alloc; mod arc; mod autotraits; mod borrow; mod boxed; mod btree_set_hash; mod c_str; +mod c_str2; +mod collections; mod const_fns; mod cow_str; mod fmt; mod heap; mod linked_list; +mod misc_tests; mod rc; mod slice; mod sort; mod str; mod string; +mod sync; mod task; +mod testing; mod thin_box; mod vec; mod vec_deque; @@ -69,6 +81,18 @@ fn hash(t: &T) -> u64 { s.finish() } +/// Copied from `std::test_helpers::test_rng`, since these tests rely on the +/// seed not being the same for every RNG invocation too. +fn test_rng() -> rand_xorshift::XorShiftRng { + use std::hash::{BuildHasher, Hash, Hasher}; + let mut hasher = std::hash::RandomState::new().build_hasher(); + std::panic::Location::caller().hash(&mut hasher); + let hc64 = hasher.finish(); + let seed_vec = hc64.to_le_bytes().into_iter().chain(0u8..8).collect::>(); + let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap(); + rand::SeedableRng::from_seed(seed) +} + // FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten. // See https://github.com/kripken/emscripten-fastcomp/issues/169 #[cfg(not(target_os = "emscripten"))] diff --git a/library/alloc/src/tests.rs b/library/alloc/tests/misc_tests.rs similarity index 100% rename from library/alloc/src/tests.rs rename to library/alloc/tests/misc_tests.rs diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/tests/sync.rs similarity index 98% rename from library/alloc/src/sync/tests.rs rename to library/alloc/tests/sync.rs index de5816fda974a..7a9a4abfdc672 100644 --- a/library/alloc/src/sync/tests.rs +++ b/library/alloc/tests/sync.rs @@ -1,14 +1,16 @@ +use alloc::sync::*; +use std::alloc::{AllocError, Allocator, Layout}; +use std::any::Any; use std::clone::Clone; use std::mem::MaybeUninit; use std::option::Option::None; +use std::ptr::NonNull; use std::sync::Mutex; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::SeqCst; +use std::sync::atomic::Ordering::*; +use std::sync::atomic::{self, AtomicUsize}; use std::sync::mpsc::channel; use std::thread; -use super::*; - struct Canary(*mut AtomicUsize); impl Drop for Canary { diff --git a/library/alloc/tests/testing/crash_test.rs b/library/alloc/tests/testing/crash_test.rs new file mode 100644 index 0000000000000..502fe6c10c6fd --- /dev/null +++ b/library/alloc/tests/testing/crash_test.rs @@ -0,0 +1,80 @@ +use std::cmp::Ordering; +use std::fmt::Debug; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::SeqCst; + +/// A blueprint for crash test dummy instances that monitor drops. +/// Some instances may be configured to panic at some point. +/// +/// Crash test dummies are identified and ordered by an id, so they can be used +/// as keys in a BTreeMap. +#[derive(Debug)] +pub struct CrashTestDummy { + pub id: usize, + dropped: AtomicUsize, +} + +impl CrashTestDummy { + /// Creates a crash test dummy design. The `id` determines order and equality of instances. + pub fn new(id: usize) -> CrashTestDummy { + CrashTestDummy { id, dropped: AtomicUsize::new(0) } + } + + /// Creates an instance of a crash test dummy that records what events it experiences + /// and optionally panics. + pub fn spawn(&self, panic: Panic) -> Instance<'_> { + Instance { origin: self, panic } + } + + /// Returns how many times instances of the dummy have been dropped. + pub fn dropped(&self) -> usize { + self.dropped.load(SeqCst) + } +} + +#[derive(Debug)] +pub struct Instance<'a> { + origin: &'a CrashTestDummy, + panic: Panic, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Panic { + Never, + InDrop, +} + +impl Instance<'_> { + pub fn id(&self) -> usize { + self.origin.id + } +} + +impl Drop for Instance<'_> { + fn drop(&mut self) { + self.origin.dropped.fetch_add(1, SeqCst); + if self.panic == Panic::InDrop { + panic!("panic in `drop`"); + } + } +} + +impl PartialOrd for Instance<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + self.id().partial_cmp(&other.id()) + } +} + +impl Ord for Instance<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.id().cmp(&other.id()) + } +} + +impl PartialEq for Instance<'_> { + fn eq(&self, other: &Self) -> bool { + self.id().eq(&other.id()) + } +} + +impl Eq for Instance<'_> {} diff --git a/library/alloc/tests/testing/mod.rs b/library/alloc/tests/testing/mod.rs new file mode 100644 index 0000000000000..0a3dd191dc891 --- /dev/null +++ b/library/alloc/tests/testing/mod.rs @@ -0,0 +1 @@ +pub mod crash_test; diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index 496b78439ea6c..9b23874bcf7ba 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -71,7 +71,7 @@ pub mod rust_2021 { /// The 2024 version of the core prelude. /// /// See the [module-level documentation](self) for more. -#[unstable(feature = "prelude_2024", issue = "121042")] +#[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")] pub mod rust_2024 { #[stable(feature = "rust1", since = "1.0.0")] pub use super::common::*; @@ -84,7 +84,7 @@ pub mod rust_2024 { #[doc(no_inline)] pub use crate::convert::{TryFrom, TryInto}; - #[unstable(feature = "prelude_2024", issue = "121042")] + #[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")] #[doc(no_inline)] pub use crate::future::{Future, IntoFuture}; } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 6d0361b8c63f4..3639feaacf3ab 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1587,15 +1587,6 @@ impl *mut T { /// beyond the allocation that the pointer points into. It is up to the caller to ensure that /// the returned offset is correct in all terms other than alignment. /// - /// When this is called during compile-time evaluation (which is unstable), the implementation - /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the - /// actual alignment of pointers is not known yet during compile-time, so an offset with - /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8; - /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet - /// known, so the execution has to be correct for either choice. It is therefore impossible to - /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual - /// for unstable APIs.) - /// /// # Panics /// /// The function panics if `align` is not a power-of-two. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 49a0322003905..047f5b0c4c584 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -348,7 +348,6 @@ #![feature(pin_coerce_unsized_trait)] #![feature(pointer_is_aligned_to)] #![feature(portable_simd)] -#![feature(prelude_2024)] #![feature(ptr_as_uninit)] #![feature(ptr_mask)] #![feature(random)] diff --git a/library/std/src/os/hurd/mod.rs b/library/std/src/os/hurd/mod.rs index aee86c7f61655..6cd50aeada1da 100644 --- a/library/std/src/os/hurd/mod.rs +++ b/library/std/src/os/hurd/mod.rs @@ -1,6 +1,7 @@ //! Hurd-specific definitions #![stable(feature = "raw_ext", since = "1.1.0")] +#![forbid(unsafe_op_in_unsafe_fn)] pub mod fs; pub mod raw; diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index 0c610ba67e65c..fffc1e9264e7c 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -25,6 +25,7 @@ //! //! # Prelude contents //! +//! The items included in the prelude depend on the edition of the crate. //! The first version of the prelude is used in Rust 2015 and Rust 2018, //! and lives in [`std::prelude::v1`]. //! [`std::prelude::rust_2015`] and [`std::prelude::rust_2018`] re-export this prelude. @@ -67,15 +68,21 @@ //! The prelude used in Rust 2021, [`std::prelude::rust_2021`], includes all of the above, //! and in addition re-exports: //! -//! * [std::convert]::{[TryFrom], [TryInto]}, +//! * [std::convert]::{[TryFrom], [TryInto]}. //! * [std::iter]::[FromIterator]. //! +//! The prelude used in Rust 2024, [`std::prelude::rust_2024`], includes all of the above, +//! and in addition re-exports: +//! +//! * [std::future]::{[Future], [IntoFuture]}. +//! //! [std::borrow]: crate::borrow //! [std::boxed]: crate::boxed //! [std::clone]: crate::clone //! [std::cmp]: crate::cmp //! [std::convert]: crate::convert //! [std::default]: crate::default +//! [std::future]: crate::future //! [std::iter]: crate::iter //! [std::marker]: crate::marker //! [std::mem]: crate::mem @@ -85,6 +92,7 @@ //! [`std::prelude::rust_2015`]: rust_2015 //! [`std::prelude::rust_2018`]: rust_2018 //! [`std::prelude::rust_2021`]: rust_2021 +//! [`std::prelude::rust_2024`]: rust_2024 //! [std::result]: crate::result //! [std::slice]: crate::slice //! [std::string]: crate::string @@ -94,6 +102,8 @@ //! [book-dtor]: ../../book/ch15-03-drop.html //! [book-enums]: ../../book/ch06-01-defining-an-enum.html //! [book-iter]: ../../book/ch13-02-iterators.html +//! [Future]: crate::future::Future +//! [IntoFuture]: crate::future::IntoFuture // No formatting: this file is nothing but re-exports, and their order is worth preserving. #![cfg_attr(rustfmt, rustfmt::skip)] @@ -158,12 +168,12 @@ pub mod rust_2021 { /// The 2024 version of the prelude of The Rust Standard Library. /// /// See the [module-level documentation](self) for more. -#[unstable(feature = "prelude_2024", issue = "121042")] +#[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")] pub mod rust_2024 { #[stable(feature = "rust1", since = "1.0.0")] pub use super::common::*; - #[unstable(feature = "prelude_2024", issue = "121042")] + #[stable(feature = "prelude_2024", since = "CURRENT_RUSTC_VERSION")] #[doc(no_inline)] pub use core::prelude::rust_2024::*; } diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 79baa5b0b83ec..40d409310ffab 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -178,3 +178,8 @@ cfg_if::cfg_if! { #[cfg(target_os = "hurd")] #[link(name = "gcc_s")] extern "C" {} + +#[cfg(all(target_os = "windows", target_env = "gnu", target_abi = "llvm"))] +#[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))] +#[link(name = "unwind", cfg(not(target_feature = "crt-static")))] +extern "C" {} diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 715f8b57876ae..1fa9e480166b7 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -102,12 +102,9 @@ pub type _Unwind_Exception_Cleanup_Fn = // rustc_codegen_ssa::src::back::symbol_export, rustc_middle::middle::exported_symbols // and RFC 2841 #[cfg_attr( - any( - all( - feature = "llvm-libunwind", - any(target_os = "fuchsia", target_os = "linux", target_os = "xous") - ), - all(target_os = "windows", target_env = "gnu", target_abi = "llvm") + all( + feature = "llvm-libunwind", + any(target_os = "fuchsia", target_os = "linux", target_os = "xous") ), link(name = "unwind", kind = "static", modifiers = "-bundle") )] diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 38abca8b8da17..226b7e2f232e8 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -1035,12 +1035,7 @@ impl Builder<'_> { rustflags.arg("-Wrustc::internal"); // cfg(bootstrap) - remove this check when lint is in bootstrap compiler if stage != 0 { - // Lint is allow by default so downstream tools don't get a lit - // they can do nothing about - // We shouldn't be preinterning symbols used by tests - if cmd_kind != Kind::Test { - rustflags.arg("-Drustc::symbol_intern_string_literal"); - } + rustflags.arg("-Drustc::symbol_intern_string_literal"); } // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all // of the individual lints are satisfied. diff --git a/tests/ui/asm/generic_const_simd_vec_len.rs b/tests/ui/asm/generic_const_simd_vec_len.rs new file mode 100644 index 0000000000000..fb8c5274ddb82 --- /dev/null +++ b/tests/ui/asm/generic_const_simd_vec_len.rs @@ -0,0 +1,21 @@ +//! This is a regression test to ensure that we emit a diagnostic pointing to the +//! reason the type was rejected in inline assembly. + +//@ only-x86_64 + +#![feature(repr_simd)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct Foo([u8; C]); +//~^ ERROR: cannot evaluate SIMD vector length + +pub unsafe fn foo(a: Foo) { + std::arch::asm!( + "movaps {src}, {src}", + src = in(xmm_reg) a, + //~^ NOTE: SIMD vector length needs to be known statically + ); +} + +fn main() {} diff --git a/tests/ui/asm/generic_const_simd_vec_len.stderr b/tests/ui/asm/generic_const_simd_vec_len.stderr new file mode 100644 index 0000000000000..486281b6062d9 --- /dev/null +++ b/tests/ui/asm/generic_const_simd_vec_len.stderr @@ -0,0 +1,14 @@ +error: cannot evaluate SIMD vector length `C` + --> $DIR/generic_const_simd_vec_len.rs:10:32 + | +LL | pub struct Foo([u8; C]); + | ^^^^^^^ + | +note: SIMD vector length needs to be known statically for use in `asm!` + --> $DIR/generic_const_simd_vec_len.rs:16:27 + | +LL | src = in(xmm_reg) a, + | ^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/asm/named_const_simd_vec_len.rs b/tests/ui/asm/named_const_simd_vec_len.rs new file mode 100644 index 0000000000000..7df4d922d5c91 --- /dev/null +++ b/tests/ui/asm/named_const_simd_vec_len.rs @@ -0,0 +1,22 @@ +//! This is a regression test to ensure that we evaluate +//! SIMD vector length constants instead of assuming they are literals. + +//@ only-x86_64 +//@ check-pass + +#![feature(repr_simd)] + +const C: usize = 16; + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct Foo([u8; C]); + +pub unsafe fn foo(a: Foo) { + std::arch::asm!( + "movaps {src}, {src}", + src = in(xmm_reg) a, + ); +} + +fn main() {} diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed index 91d30de74c7c0..11ec273fc4bf9 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed @@ -11,6 +11,8 @@ fn main() { m(); q(); let _ = meow(); + let _ = fallback_return(); + let _ = fully_apit(); } fn m() { @@ -49,3 +51,29 @@ fn meow() -> Result<(), ()> { //[e2024]~^ error: the trait bound `(): From` is not satisfied Ok(()) } + +pub fn takes_apit(_y: impl Fn() -> T) -> Result { + Err(()) +} + +pub fn fallback_return() -> Result<(), ()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + takes_apit::<()>(|| Default::default())?; + //[e2024]~^ error: the trait bound `!: Default` is not satisfied + Ok(()) +} + +fn mk() -> Result { + Err(()) +} + +fn takes_apit2(_x: impl Default) {} + +fn fully_apit() -> Result<(), ()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + takes_apit2(mk::<()>()?); + //[e2024]~^ error: the trait bound `!: Default` is not satisfied + Ok(()) +} diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr index 6fdb548c4317a..9009d61793613 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr @@ -1,5 +1,5 @@ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:16:1 + --> $DIR/never-type-fallback-breaking.rs:18:1 | LL | fn m() { | ^^^^^^ @@ -8,7 +8,7 @@ LL | fn m() { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:20:17 + --> $DIR/never-type-fallback-breaking.rs:22:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | let x: () = match true { | ++++ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:28:1 + --> $DIR/never-type-fallback-breaking.rs:30:1 | LL | fn q() -> Option<()> { | ^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | fn q() -> Option<()> { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:35:5 + --> $DIR/never-type-fallback-breaking.rs:37:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ LL | deserialize::<()>()?; | ++++++ warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:45:1 + --> $DIR/never-type-fallback-breaking.rs:47:1 | LL | fn meow() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | fn meow() -> Result<(), ()> { = note: for more information, see issue #123748 = help: specify the types explicitly note: in edition 2024, the requirement `(): From` will fail - --> $DIR/never-type-fallback-breaking.rs:48:5 + --> $DIR/never-type-fallback-breaking.rs:50:5 | LL | help(1)?; | ^^^^^^^ @@ -56,5 +56,43 @@ help: use `()` annotations to avoid fallback changes LL | help::<(), _>(1)?; | +++++++++ -warning: 3 warnings emitted +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:59:1 + | +LL | pub fn fallback_return() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see issue #123748 + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/never-type-fallback-breaking.rs:62:19 + | +LL | takes_apit(|| Default::default())?; + | ^^^^^^^^^^^^^^^^^^ +help: use `()` annotations to avoid fallback changes + | +LL | takes_apit::<()>(|| Default::default())?; + | ++++++ + +warning: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:73:1 + | +LL | fn fully_apit() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + = note: for more information, see issue #123748 + = help: specify the types explicitly +note: in edition 2024, the requirement `!: Default` will fail + --> $DIR/never-type-fallback-breaking.rs:76:17 + | +LL | takes_apit2(mk()?); + | ^^^^^ +help: use `()` annotations to avoid fallback changes + | +LL | takes_apit2(mk::<()>()?); + | ++++++ + +warning: 5 warnings emitted diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr index 9d79dfb4099fb..2daf00f7804ff 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:20:17 + --> $DIR/never-type-fallback-breaking.rs:22:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -8,7 +8,7 @@ LL | true => Default::default(), = help: did you intend to use the type `()` here instead? error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:35:5 + --> $DIR/never-type-fallback-breaking.rs:37:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -16,13 +16,13 @@ LL | deserialize()?; = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) = help: did you intend to use the type `()` here instead? note: required by a bound in `deserialize` - --> $DIR/never-type-fallback-breaking.rs:31:23 + --> $DIR/never-type-fallback-breaking.rs:33:23 | LL | fn deserialize() -> Option { | ^^^^^^^ required by this bound in `deserialize` error[E0277]: the trait bound `(): From` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:48:5 + --> $DIR/never-type-fallback-breaking.rs:50:5 | LL | help(1)?; | ^^^^^^^ the trait `From` is not implemented for `()` @@ -39,11 +39,36 @@ LL | help(1)?; and 4 others = note: required for `!` to implement `Into<()>` note: required by a bound in `help` - --> $DIR/never-type-fallback-breaking.rs:42:20 + --> $DIR/never-type-fallback-breaking.rs:44:20 | LL | fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result { | ^^^^^^^^ required by this bound in `help` -error: aborting due to 3 previous errors +error[E0277]: the trait bound `!: Default` is not satisfied + --> $DIR/never-type-fallback-breaking.rs:62:19 + | +LL | takes_apit(|| Default::default())?; + | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` + | + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: did you intend to use the type `()` here instead? + +error[E0277]: the trait bound `!: Default` is not satisfied + --> $DIR/never-type-fallback-breaking.rs:76:17 + | +LL | takes_apit2(mk()?); + | ----------- ^^^^^ the trait `Default` is not implemented for `!` + | | + | required by a bound introduced by this call + | + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: did you intend to use the type `()` here instead? +note: required by a bound in `takes_apit2` + --> $DIR/never-type-fallback-breaking.rs:71:25 + | +LL | fn takes_apit2(_x: impl Default) {} + | ^^^^^^^ required by this bound in `takes_apit2` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs index 24e33ff6bf6b7..daafc526eff41 100644 --- a/tests/ui/editions/never-type-fallback-breaking.rs +++ b/tests/ui/editions/never-type-fallback-breaking.rs @@ -11,6 +11,8 @@ fn main() { m(); q(); let _ = meow(); + let _ = fallback_return(); + let _ = fully_apit(); } fn m() { @@ -49,3 +51,29 @@ fn meow() -> Result<(), ()> { //[e2024]~^ error: the trait bound `(): From` is not satisfied Ok(()) } + +pub fn takes_apit(_y: impl Fn() -> T) -> Result { + Err(()) +} + +pub fn fallback_return() -> Result<(), ()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + takes_apit(|| Default::default())?; + //[e2024]~^ error: the trait bound `!: Default` is not satisfied + Ok(()) +} + +fn mk() -> Result { + Err(()) +} + +fn takes_apit2(_x: impl Default) {} + +fn fully_apit() -> Result<(), ()> { + //[e2021]~^ this function depends on never type fallback being `()` + //[e2021]~| this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + takes_apit2(mk()?); + //[e2024]~^ error: the trait bound `!: Default` is not satisfied + Ok(()) +} diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr index b5b5d87e7dd06..8d08fb7f2a821 100644 --- a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr +++ b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr @@ -15,8 +15,8 @@ LL | foo(|| panic!()); = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default help: use `()` annotations to avoid fallback changes | -LL | foo::<(), _>(|| panic!()); - | +++++++++ +LL | foo::<()>(|| panic!()); + | ++++++ warning: 1 warning emitted diff --git a/tests/ui/parser/bad-name.stderr b/tests/ui/parser/bad-name.stderr index a336923f4fd89..112fdcad3369c 100644 --- a/tests/ui/parser/bad-name.stderr +++ b/tests/ui/parser/bad-name.stderr @@ -1,9 +1,3 @@ -error: field expressions cannot have generic arguments - --> $DIR/bad-name.rs:2:12 - | -LL | let x.y::.z foo; - | ^^^^^^^ - error: expected a pattern, found an expression --> $DIR/bad-name.rs:2:7 | @@ -18,5 +12,11 @@ error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, LL | let x.y::.z foo; | ^^^ expected one of 9 possible tokens +error: field expressions cannot have generic arguments + --> $DIR/bad-name.rs:2:12 + | +LL | let x.y::.z foo; + | ^^^^^^^ + error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/method-missing-parentheses.rs b/tests/ui/suggestions/method-missing-parentheses.rs index f10bfb56d2e12..bc576b71f0d0b 100644 --- a/tests/ui/suggestions/method-missing-parentheses.rs +++ b/tests/ui/suggestions/method-missing-parentheses.rs @@ -1,5 +1,4 @@ fn main() { let _ = vec![].into_iter().collect::; //~^ ERROR attempted to take value of method `collect` on type `std::vec::IntoIter<_>` - //~| ERROR field expressions cannot have generic arguments } diff --git a/tests/ui/suggestions/method-missing-parentheses.stderr b/tests/ui/suggestions/method-missing-parentheses.stderr index 1bfff56a6a906..f0ff1f0334a39 100644 --- a/tests/ui/suggestions/method-missing-parentheses.stderr +++ b/tests/ui/suggestions/method-missing-parentheses.stderr @@ -1,9 +1,3 @@ -error: field expressions cannot have generic arguments - --> $DIR/method-missing-parentheses.rs:2:41 - | -LL | let _ = vec![].into_iter().collect::; - | ^^^^^^^ - error[E0615]: attempted to take value of method `collect` on type `std::vec::IntoIter<_>` --> $DIR/method-missing-parentheses.rs:2:32 | @@ -15,6 +9,6 @@ help: use parentheses to call the method LL | let _ = vec![].into_iter().collect::(); | ++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0615`.