diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index a705d3bc1073f..c1bf65367aab5 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -30,7 +30,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::FieldIdx; use rustc_target::spec::abi; use rustc_trait_selection::infer::InferCtxtExt; @@ -1383,7 +1383,9 @@ fn infer_return_ty_for_fn_sig<'tcx>( Applicability::MachineApplicable, ); should_recover = true; - } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) { + } else if let Some(sugg) = + suggest_impl_trait(&tcx.infer_ctxt().build(), tcx.param_env(def_id), ret_ty) + { diag.span_suggestion( ty.span, "replace with an appropriate return type", @@ -1426,11 +1428,10 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } -fn suggest_impl_trait<'tcx>( - tcx: TyCtxt<'tcx>, +pub fn suggest_impl_trait<'tcx>( + infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, ret_ty: Ty<'tcx>, - span: Span, - def_id: LocalDefId, ) -> Option { let format_as_assoc: fn(_, _, _, _, _) -> _ = |tcx: TyCtxt<'tcx>, @@ -1464,24 +1465,28 @@ fn suggest_impl_trait<'tcx>( for (trait_def_id, assoc_item_def_id, formatter) in [ ( - tcx.get_diagnostic_item(sym::Iterator), - tcx.get_diagnostic_item(sym::IteratorItem), + infcx.tcx.get_diagnostic_item(sym::Iterator), + infcx.tcx.get_diagnostic_item(sym::IteratorItem), format_as_assoc, ), ( - tcx.lang_items().future_trait(), - tcx.get_diagnostic_item(sym::FutureOutput), + infcx.tcx.lang_items().future_trait(), + infcx.tcx.get_diagnostic_item(sym::FutureOutput), format_as_assoc, ), - (tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized), ( - tcx.lang_items().fn_mut_trait(), - tcx.lang_items().fn_once_output(), + infcx.tcx.lang_items().fn_trait(), + infcx.tcx.lang_items().fn_once_output(), + format_as_parenthesized, + ), + ( + infcx.tcx.lang_items().fn_mut_trait(), + infcx.tcx.lang_items().fn_once_output(), format_as_parenthesized, ), ( - tcx.lang_items().fn_once_trait(), - tcx.lang_items().fn_once_output(), + infcx.tcx.lang_items().fn_once_trait(), + infcx.tcx.lang_items().fn_once_output(), format_as_parenthesized, ), ] { @@ -1491,36 +1496,45 @@ fn suggest_impl_trait<'tcx>( let Some(assoc_item_def_id) = assoc_item_def_id else { continue; }; - if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy { + if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy { continue; } - let param_env = tcx.param_env(def_id); - let infcx = tcx.infer_ctxt().build(); - let args = ty::GenericArgs::for_item(tcx, trait_def_id, |param, _| { - if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) } + let sugg = infcx.probe(|_| { + let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| { + if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) } + }); + if !infcx + .type_implements_trait(trait_def_id, args, param_env) + .must_apply_modulo_regions() + { + return None; + } + let ocx = ObligationCtxt::new(&infcx); + let item_ty = ocx.normalize( + &ObligationCause::dummy(), + param_env, + Ty::new_projection(infcx.tcx, assoc_item_def_id, args), + ); + // FIXME(compiler-errors): We may benefit from resolving regions here. + if ocx.select_where_possible().is_empty() + && let item_ty = infcx.resolve_vars_if_possible(item_ty) + && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None) + && let Some(sugg) = formatter( + infcx.tcx, + infcx.resolve_vars_if_possible(args), + trait_def_id, + assoc_item_def_id, + item_ty, + ) + { + return Some(sugg); + } + + None }); - if !infcx.type_implements_trait(trait_def_id, args, param_env).must_apply_modulo_regions() { - continue; - } - let ocx = ObligationCtxt::new(&infcx); - let item_ty = ocx.normalize( - &ObligationCause::misc(span, def_id), - param_env, - Ty::new_projection(tcx, assoc_item_def_id, args), - ); - // FIXME(compiler-errors): We may benefit from resolving regions here. - if ocx.select_where_possible().is_empty() - && let item_ty = infcx.resolve_vars_if_possible(item_ty) - && let Some(item_ty) = item_ty.make_suggestable(tcx, false, None) - && let Some(sugg) = formatter( - tcx, - infcx.resolve_vars_if_possible(args), - trait_def_id, - assoc_item_def_id, - item_ty, - ) - { - return Some(sugg); + + if sugg.is_some() { + return sugg; } } None diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 442bfd75746ee..1e1136ef46778 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -20,6 +20,7 @@ use rustc_hir::{ CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate, }; +use rustc_hir_analysis::collect::suggest_impl_trait; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::traits::{self}; use rustc_middle::lint::in_external_macro; @@ -814,17 +815,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() }, ); return true; - } else if let ty::Closure(_, args) = found.kind() - // FIXME(compiler-errors): Get better at printing binders... - && let closure = args.as_closure() - && closure.sig().is_suggestable(self.tcx, false) - { + } else if let Some(sugg) = suggest_impl_trait(self, self.param_env, found) { err.subdiagnostic( self.dcx(), - errors::AddReturnTypeSuggestion::Add { - span, - found: closure.print_as_impl_trait().to_string(), - }, + errors::AddReturnTypeSuggestion::Add { span, found: sugg }, ); return true; } else { diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index fdb6ab8f59b95..64f52ea7ac196 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -144,6 +144,9 @@ infer_fps_items_are_distinct = fn items are distinct from fn pointers infer_fps_remove_ref = consider removing the reference infer_fps_use_ref = consider using a reference infer_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime + +infer_full_type_written = the full type name has been written to '{$path}' + infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement infer_label_bad = {$bad_kind -> diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 6192eaf3c3a43..4593108edac03 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -18,6 +18,8 @@ use crate::infer::error_reporting::{ ObligationCauseAsDiagArg, }; +use std::path::PathBuf; + pub mod note_and_explain; #[derive(Diagnostic)] @@ -47,6 +49,9 @@ pub struct AnnotationRequired<'a> { pub infer_subdiags: Vec>, #[subdiagnostic] pub multi_suggestions: Vec>, + #[note(infer_full_type_written)] + pub was_written: Option<()>, + pub path: PathBuf, } // Copy of `AnnotationRequired` for E0283 @@ -65,6 +70,9 @@ pub struct AmbiguousImpl<'a> { pub infer_subdiags: Vec>, #[subdiagnostic] pub multi_suggestions: Vec>, + #[note(infer_full_type_written)] + pub was_written: Option<()>, + pub path: PathBuf, } // Copy of `AnnotationRequired` for E0284 @@ -83,6 +91,9 @@ pub struct AmbiguousReturn<'a> { pub infer_subdiags: Vec>, #[subdiagnostic] pub multi_suggestions: Vec>, + #[note(infer_full_type_written)] + pub was_written: Option<()>, + pub path: PathBuf, } // Used when a better one isn't available diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index f89ed256a08c2..3b5658ed0ee64 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -18,13 +18,15 @@ use rustc_middle::infer::unify_key::{ }; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer}; -use rustc_middle::ty::{self, InferConst}; -use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgsRef}; -use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults}; +use rustc_middle::ty::{ + self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Ty, TyCtxt, + TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, +}; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{BytePos, Span}; +use rustc_span::{BytePos, Span, DUMMY_SP}; use std::borrow::Cow; use std::iter; +use std::path::PathBuf; pub enum TypeAnnotationNeeded { /// ```compile_fail,E0282 @@ -153,6 +155,29 @@ impl UnderspecifiedArgKind { } } +struct ClosureEraser<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> TypeFolder> for ClosureEraser<'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.kind() { + ty::Closure(_, args) => { + let closure_sig = args.as_closure().sig(); + Ty::new_fn_ptr( + self.tcx, + self.tcx.signature_unclosure(closure_sig, hir::Unsafety::Normal), + ) + } + _ => ty.super_fold_with(self), + } + } +} + fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> { let mut printer = FmtPrinter::new(infcx.tcx, ns); let ty_getter = move |ty_vid| { @@ -209,6 +234,10 @@ fn ty_to_string<'tcx>( ) -> String { let mut printer = fmt_printer(infcx, Namespace::TypeNS); let ty = infcx.resolve_vars_if_possible(ty); + // We use `fn` ptr syntax for closures, but this only works when the closure + // does not capture anything. + let ty = ty.fold_with(&mut ClosureEraser { tcx: infcx.tcx }); + match (ty.kind(), called_method_def_id) { // We don't want the regular output for `fn`s because it includes its path in // invalid pseudo-syntax, we want the `fn`-pointer output instead. @@ -223,11 +252,6 @@ fn ty_to_string<'tcx>( "Vec<_>".to_string() } _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(), - // FIXME: The same thing for closures, but this only works when the closure - // does not capture anything. - // - // We do have to hide the `extern "rust-call"` ABI in that case though, - // which is too much of a bother for now. _ => { ty.print(&mut printer).unwrap(); printer.into_buffer() @@ -387,6 +411,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, + was_written: None, + path: Default::default(), }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -396,6 +422,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, + was_written: None, + path: Default::default(), }), TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn { span, @@ -405,6 +433,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, + was_written: None, + path: Default::default(), }), } } @@ -442,7 +472,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { return self.bad_inference_failure_err(failure_span, arg_data, error_code); }; - let (source_kind, name) = kind.ty_localized_msg(self); + let (source_kind, name, path) = kind.ty_localized_msg(self); let failure_span = if should_label_span && !failure_span.overlaps(span) { Some(failure_span) } else { @@ -518,7 +548,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), GenericArgKind::Type(_) => self .next_ty_var(TypeVariableOrigin { - span: rustc_span::DUMMY_SP, + span: DUMMY_SP, kind: TypeVariableOriginKind::MiscVariable, }) .into(), @@ -526,7 +556,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .next_const_var( arg.ty(), ConstVariableOrigin { - span: rustc_span::DUMMY_SP, + span: DUMMY_SP, kind: ConstVariableOriginKind::MiscVariable, }, ) @@ -547,7 +577,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => { let placeholder = Some(self.next_ty_var(TypeVariableOrigin { - span: rustc_span::DUMMY_SP, + span: DUMMY_SP, kind: TypeVariableOriginKind::MiscVariable, })); if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) { @@ -584,7 +614,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => { let placeholder = Some(self.next_ty_var(TypeVariableOrigin { - span: rustc_span::DUMMY_SP, + span: DUMMY_SP, kind: TypeVariableOriginKind::MiscVariable, })); if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) { @@ -606,6 +636,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, + was_written: path.as_ref().map(|_| ()), + path: path.unwrap_or_default(), }), TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl { span, @@ -615,6 +647,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, + was_written: path.as_ref().map(|_| ()), + path: path.unwrap_or_default(), }), TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn { span, @@ -624,6 +658,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, + was_written: path.as_ref().map(|_| ()), + path: path.unwrap_or_default(), }), } } @@ -688,22 +724,23 @@ impl<'tcx> InferSource<'tcx> { } impl<'tcx> InferSourceKind<'tcx> { - fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String) { + fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option) { + let mut path = None; match *self { InferSourceKind::LetBinding { ty, .. } | InferSourceKind::ClosureArg { ty, .. } | InferSourceKind::ClosureReturn { ty, .. } => { if ty.is_closure() { - ("closure", closure_as_fn_str(infcx, ty)) + ("closure", closure_as_fn_str(infcx, ty), path) } else if !ty.is_ty_or_numeric_infer() { - ("normal", ty_to_string(infcx, ty, None)) + ("normal", infcx.tcx.short_ty_string(ty, &mut path), path) } else { - ("other", String::new()) + ("other", String::new(), path) } } // FIXME: We should be able to add some additional info here. InferSourceKind::GenericArg { .. } - | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new()), + | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new(), path), } } } diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 16e3b8c11c133..b2403836397a1 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -105,7 +105,7 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di BuiltinLintDiag::RedundantImport(spans, ident) => { for (span, is_imported) in spans { let introduced = if is_imported { "imported" } else { "defined" }; - let span_msg = if span.is_dummy() { "by prelude" } else { "here" }; + let span_msg = if span.is_dummy() { "by the extern prelude" } else { "here" }; diag.span_label( span, format!("the item `{ident}` is already {introduced} {span_msg}"), diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 111a4fdcea174..503caa35358ab 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1074,10 +1074,14 @@ impl UnusedParens { // Otherwise proceed with linting. _ => {} } - let spans = inner - .span - .find_ancestor_inside(value.span) - .map(|inner| (value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi()))); + let spans = if !value.span.from_expansion() { + inner + .span + .find_ancestor_inside(value.span) + .map(|inner| (value.span.with_hi(inner.lo()), value.span.with_lo(inner.hi()))) + } else { + None + }; self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space, false); } } @@ -1233,11 +1237,13 @@ impl EarlyLintPass for UnusedParens { if self.with_self_ty_parens && b.generic_params.len() > 0 => {} ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {} _ => { - let spans = r - .span - .find_ancestor_inside(ty.span) - .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi()))); - + let spans = if !ty.span.from_expansion() { + r.span + .find_ancestor_inside(ty.span) + .map(|r| (ty.span.with_hi(r.lo()), ty.span.with_lo(r.hi()))) + } else { + None + }; self.emit_unused_delims(cx, ty.span, spans, "type", (false, false), false); } } diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 44ae72bcd26bf..d448c5338fc46 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -227,13 +227,10 @@ mod impls { impl_clone! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 - f32 f64 + f16 f32 f64 f128 bool char } - #[cfg(not(bootstrap))] - impl_clone! { f16 f128 } - #[unstable(feature = "never_type", issue = "35121")] impl Clone for ! { #[inline] diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 81bba927554a4..fa218600ed925 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1497,12 +1497,9 @@ mod impls { } partial_eq_impl! { - bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 + bool char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } - #[cfg(not(bootstrap))] - partial_eq_impl! { f16 f128 } - macro_rules! eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] @@ -1553,10 +1550,7 @@ mod impls { } } - partial_ord_impl! { f32 f64 } - - #[cfg(not(bootstrap))] - partial_ord_impl! { f16 f128 } + partial_ord_impl! { f16 f32 f64 f128 } macro_rules! ord_impl { ($($t:ty)*) => ($( diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 0167d04c413fe..1737c631f0bd0 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -34,8 +34,10 @@ macro_rules! impl_float_to_int { } } +impl_float_to_int!(f16 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); impl_float_to_int!(f32 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); impl_float_to_int!(f64 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); +impl_float_to_int!(f128 => u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); // Conversion traits for primitive integer and float types // Conversions T -> T are covered by a blanket impl and therefore excluded @@ -163,7 +165,12 @@ impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0" impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); // float -> float +impl_from!(f16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(f32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); macro_rules! impl_float_from_bool { ($float:ty) => { diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index dbdbaccb5353f..f4f33f8584bd0 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -517,8 +517,6 @@ impl CStr { /// # Examples /// /// ``` - /// #![feature(cstr_count_bytes)] - /// /// use std::ffi::CStr; /// /// let cstr = CStr::from_bytes_with_nul(b"foo\0").unwrap(); @@ -530,7 +528,7 @@ impl CStr { #[inline] #[must_use] #[doc(alias("len", "strlen"))] - #[unstable(feature = "cstr_count_bytes", issue = "114441")] + #[stable(feature = "cstr_count_bytes", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")] pub const fn count_bytes(&self) -> usize { self.inner.len() - 1 diff --git a/library/core/src/fmt/nofloat.rs b/library/core/src/fmt/nofloat.rs index cfb94cd9de530..a36e7efcd95c7 100644 --- a/library/core/src/fmt/nofloat.rs +++ b/library/core/src/fmt/nofloat.rs @@ -11,5 +11,7 @@ macro_rules! floating { }; } +floating! { f16 } floating! { f32 } floating! { f64 } +floating! { f128 } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 0ba3a557a035a..10d2698c5dd1b 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -200,8 +200,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), feature(f128))] -#![cfg_attr(not(bootstrap), feature(f16))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -226,6 +224,8 @@ #![feature(doc_notable_trait)] #![feature(effects)] #![feature(extern_types)] +#![feature(f128)] +#![feature(f16)] #![feature(freeze_impls)] #![feature(fundamental)] #![feature(generic_arg_infer)] @@ -347,6 +347,10 @@ pub mod u8; #[path = "num/shells/usize.rs"] pub mod usize; +#[path = "num/f128.rs"] +pub mod f128; +#[path = "num/f16.rs"] +pub mod f16; #[path = "num/f32.rs"] pub mod f32; #[path = "num/f64.rs"] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index fb97b3bfa0926..1d073a6d649b8 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -422,17 +422,11 @@ marker_impls! { Copy for usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, - f32, f64, + f16, f32, f64, f128, bool, char, {T: ?Sized} *const T, {T: ?Sized} *mut T, -} -#[cfg(not(bootstrap))] -marker_impls! { - #[stable(feature = "rust1", since = "1.0.0")] - Copy for - f16, f128, } #[unstable(feature = "never_type", issue = "35121")] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs new file mode 100644 index 0000000000000..3bc3e2dbf1242 --- /dev/null +++ b/library/core/src/num/f128.rs @@ -0,0 +1,16 @@ +//! Constants for the `f128` quadruple-precision floating point type. +//! +//! *[See also the `f128` primitive type][f128].* +//! +//! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! For the constants defined directly in this module +//! (as distinct from those defined in the `consts` sub-module), +//! new code should instead use the associated constants +//! defined directly on the `f128` type. + +#![unstable(feature = "f128", issue = "116909")] + +/// Basic mathematical constants. +#[unstable(feature = "f128", issue = "116909")] +pub mod consts {} diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs new file mode 100644 index 0000000000000..969ebdc5690c1 --- /dev/null +++ b/library/core/src/num/f16.rs @@ -0,0 +1,16 @@ +//! Constants for the `f16` half-precision floating point type. +//! +//! *[See also the `f16` primitive type][f16].* +//! +//! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! For the constants defined directly in this module +//! (as distinct from those defined in the `consts` sub-module), +//! new code should instead use the associated constants +//! defined directly on the `f16` type. + +#![unstable(feature = "f16", issue = "116909")] + +/// Basic mathematical constants. +#[unstable(feature = "f16", issue = "116909")] +pub mod consts {} diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index fd50f80474833..5e77788d8ea36 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -109,7 +109,7 @@ macro_rules! add_impl { )*) } -add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } +add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// The subtraction operator `-`. /// @@ -218,7 +218,7 @@ macro_rules! sub_impl { )*) } -sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } +sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// The multiplication operator `*`. /// @@ -348,7 +348,7 @@ macro_rules! mul_impl { )*) } -mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } +mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// The division operator `/`. /// @@ -506,7 +506,7 @@ macro_rules! div_impl_float { )*) } -div_impl_float! { f32 f64 } +div_impl_float! { f16 f32 f64 f128 } /// The remainder operator `%`. /// @@ -623,7 +623,7 @@ macro_rules! rem_impl_float { )*) } -rem_impl_float! { f32 f64 } +rem_impl_float! { f16 f32 f64 f128 } /// The unary negation operator `-`. /// @@ -698,7 +698,7 @@ macro_rules! neg_impl { )*) } -neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 } +neg_impl! { isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// The addition assignment operator `+=`. /// @@ -765,7 +765,7 @@ macro_rules! add_assign_impl { )+) } -add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } +add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// The subtraction assignment operator `-=`. /// @@ -832,7 +832,7 @@ macro_rules! sub_assign_impl { )+) } -sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } +sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// The multiplication assignment operator `*=`. /// @@ -890,7 +890,7 @@ macro_rules! mul_assign_impl { )+) } -mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } +mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// The division assignment operator `/=`. /// @@ -947,7 +947,7 @@ macro_rules! div_assign_impl { )+) } -div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } +div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } /// The remainder assignment operator `%=`. /// @@ -1008,4 +1008,4 @@ macro_rules! rem_assign_impl { )+) } -rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 } +rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 15da4171bda21..e8e23f2a7ecc5 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1074,7 +1074,22 @@ mod prim_tuple {} #[doc(hidden)] impl (T,) {} +#[rustc_doc_primitive = "f16"] +#[doc(alias = "half")] +/// A 16-bit floating point type (specifically, the "binary16" type defined in IEEE 754-2008). +/// +/// This type is very similar to [`prim@f32`] but has decreased precision because it uses half as many +/// bits. Please see [the documentation for [`prim@f32`] or [Wikipedia on +/// half-precision values][wikipedia] for more information. +/// +/// *[See also the `std::f16::consts` module](crate::f16::consts).* +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Half-precision_floating-point_format +#[unstable(feature = "f16", issue = "116909")] +mod prim_f16 {} + #[rustc_doc_primitive = "f32"] +#[doc(alias = "single")] /// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). /// /// This type can represent a wide range of decimal numbers, like `3.5`, `27`, @@ -1143,6 +1158,7 @@ impl (T,) {} mod prim_f32 {} #[rustc_doc_primitive = "f64"] +#[doc(alias = "double")] /// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008). /// /// This type is very similar to [`f32`], but has increased @@ -1157,6 +1173,20 @@ mod prim_f32 {} #[stable(feature = "rust1", since = "1.0.0")] mod prim_f64 {} +#[rustc_doc_primitive = "f128"] +#[doc(alias = "quad")] +/// A 128-bit floating point type (specifically, the "binary128" type defined in IEEE 754-2008). +/// +/// This type is very similar to [`prim@f32`] and [`prim@f64`], but has increased precision by using twice +/// as many bits as `f64`. Please see [the documentation for [`prim@f32`] or [Wikipedia on +/// quad-precision values][wikipedia] for more information. +/// +/// *[See also the `std::f128::consts` module](crate::f128::consts).* +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format +#[unstable(feature = "f128", issue = "116909")] +mod prim_f128 {} + #[rustc_doc_primitive = "i8"] // /// The 8-bit signed integer type. diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs new file mode 100644 index 0000000000000..4710d7c50b444 --- /dev/null +++ b/library/std/src/f128.rs @@ -0,0 +1,11 @@ +//! Constants for the `f128` double-precision floating point type. +//! +//! *[See also the `f128` primitive type](primitive@f128).* +//! +//! Mathematically significant numbers are provided in the `consts` sub-module. + +#[cfg(test)] +mod tests; + +#[unstable(feature = "f128", issue = "116909")] +pub use core::f128::consts; diff --git a/library/std/src/f128/tests.rs b/library/std/src/f128/tests.rs new file mode 100644 index 0000000000000..b64c7f856a15f --- /dev/null +++ b/library/std/src/f128/tests.rs @@ -0,0 +1,40 @@ +#![allow(dead_code)] // FIXME(f16_f128): remove once constants are used + +/// Smallest number +const TINY_BITS: u128 = 0x1; +/// Next smallest number +const TINY_UP_BITS: u128 = 0x2; +/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 +const MAX_DOWN_BITS: u128 = 0x7ffeffffffffffffffffffffffffffff; +/// Zeroed exponent, full significant +const LARGEST_SUBNORMAL_BITS: u128 = 0x0000ffffffffffffffffffffffffffff; +/// Exponent = 0b1, zeroed significand +const SMALLEST_NORMAL_BITS: u128 = 0x00010000000000000000000000000000; +/// First pattern over the mantissa +const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa; +/// Second pattern over the mantissa +const NAN_MASK2: u128 = 0x00005555555555555555555555555555; + +/// Compare by value +#[allow(unused_macros)] +macro_rules! assert_f128_eq { + ($a:expr, $b:expr) => { + let (l, r): (&f128, &f128) = (&$a, &$b); + assert_eq!(*l, *r, "\na: {:#0130x}\nb: {:#0130x}", l.to_bits(), r.to_bits()) + }; +} + +/// Compare by representation +#[allow(unused_macros)] +macro_rules! assert_f128_biteq { + ($a:expr, $b:expr) => { + let (l, r): (&f128, &f128) = (&$a, &$b); + let lb = l.to_bits(); + let rb = r.to_bits(); + assert_eq!( + lb, rb, + "float {:?} is not bitequal to {:?}.\na: {:#0130x}\nb: {:#0130x}", + *l, *r, lb, rb + ); + }; +} diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs new file mode 100644 index 0000000000000..c36f9f5d4c6a8 --- /dev/null +++ b/library/std/src/f16.rs @@ -0,0 +1,11 @@ +//! Constants for the `f16` double-precision floating point type. +//! +//! *[See also the `f16` primitive type](primitive@f16).* +//! +//! Mathematically significant numbers are provided in the `consts` sub-module. + +#[cfg(test)] +mod tests; + +#[unstable(feature = "f16", issue = "116909")] +pub use core::f16::consts; diff --git a/library/std/src/f16/tests.rs b/library/std/src/f16/tests.rs new file mode 100644 index 0000000000000..d65c43eca4bb8 --- /dev/null +++ b/library/std/src/f16/tests.rs @@ -0,0 +1,46 @@ +#![allow(dead_code)] // FIXME(f16_f128): remove once constants are used + +// We run out of precision pretty quickly with f16 +const F16_APPROX_L1: f16 = 0.001; +const F16_APPROX_L2: f16 = 0.01; +const F16_APPROX_L3: f16 = 0.1; +const F16_APPROX_L4: f16 = 0.5; + +/// Smallest number +const TINY_BITS: u16 = 0x1; +/// Next smallest number +const TINY_UP_BITS: u16 = 0x2; +/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0 +const MAX_DOWN_BITS: u16 = 0x7bfe; +/// Zeroed exponent, full significant +const LARGEST_SUBNORMAL_BITS: u16 = 0x03ff; +/// Exponent = 0b1, zeroed significand +const SMALLEST_NORMAL_BITS: u16 = 0x0400; +/// First pattern over the mantissa +const NAN_MASK1: u16 = 0x02aa; +/// Second pattern over the mantissa +const NAN_MASK2: u16 = 0x0155; + +/// Compare by value +#[allow(unused_macros)] +macro_rules! assert_f16_eq { + ($a:expr, $b:expr) => { + let (l, r): (&f16, &f16) = (&$a, &$b); + assert_eq!(*l, *r, "\na: {:#018x}\nb: {:#018x}", l.to_bits(), r.to_bits()) + }; +} + +/// Compare by representation +#[allow(unused_macros)] +macro_rules! assert_f16_biteq { + ($a:expr, $b:expr) => { + let (l, r): (&f16, &f16) = (&$a, &$b); + let lb = l.to_bits(); + let rb = r.to_bits(); + assert_eq!( + lb, rb, + "float {:?} is not bitequal to {:?}.\na: {:#018x}\nb: {:#018x}", + *l, *r, lb, rb + ); + }; +} diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index b1102b440e02a..1b8fafd0089fa 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -465,14 +465,20 @@ impl File { OpenOptions::new() } - /// Attempts to sync all OS-internal metadata to disk. + /// Attempts to sync all OS-internal file content and metadata to disk. /// /// This function will attempt to ensure that all in-memory data reaches the /// filesystem before returning. /// /// This can be used to handle errors that would otherwise only be caught - /// when the `File` is closed. Dropping a file will ignore errors in - /// synchronizing this in-memory data. + /// when the `File` is closed, as dropping a `File` will ignore all errors. + /// Note, however, that `sync_all` is generally more expensive than closing + /// a file by dropping it, because the latter is not required to block until + /// the data has been written to the filesystem. + /// + /// If synchronizing the metadata is not required, use [`sync_data`] instead. + /// + /// [`sync_data`]: File::sync_data /// /// # Examples /// @@ -489,6 +495,7 @@ impl File { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "fsync")] pub fn sync_all(&self) -> io::Result<()> { self.inner.fsync() } @@ -520,6 +527,7 @@ impl File { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[doc(alias = "fdatasync")] pub fn sync_data(&self) -> io::Result<()> { self.inner.datasync() } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index c713eefc72c93..ac475b5530a78 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -214,7 +214,16 @@ //! [slice]: prim@slice #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))] -#![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))] +#![cfg_attr( + feature = "restricted-std", + unstable( + feature = "restricted_std", + issue = "none", + reason = "You have attempted to use a standard library built for a platform that it doesn't \ + know how to support. Consider building it for a known environment, disabling it with \ + `#![no_std]` or overriding this warning by enabling this feature". + ) +)] #![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)] #![doc( html_playground_url = "https://play.rust-lang.org/", @@ -283,6 +292,8 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] +#![feature(f128)] +#![feature(f16)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] #![feature(lang_items)] @@ -558,6 +569,10 @@ pub use core::u8; #[allow(deprecated, deprecated_in_future)] pub use core::usize; +#[unstable(feature = "f128", issue = "116909")] +pub mod f128; +#[unstable(feature = "f16", issue = "116909")] +pub mod f16; pub mod f32; pub mod f64; diff --git a/tests/codegen/float/f128.rs b/tests/codegen/float/f128.rs new file mode 100644 index 0000000000000..97d545e028307 --- /dev/null +++ b/tests/codegen/float/f128.rs @@ -0,0 +1,129 @@ +// Verify that our intrinsics generate the correct LLVM calls for f128 + +#![crate_type = "lib"] +#![feature(f128)] +#![feature(core_intrinsics)] + +// CHECK-LABEL: i1 @f128_eq( +#[no_mangle] +pub fn f128_eq(a: f128, b: f128) -> bool { + // CHECK: fcmp oeq fp128 %{{.+}}, %{{.+}} + a == b +} + +// CHECK-LABEL: i1 @f128_ne( +#[no_mangle] +pub fn f128_ne(a: f128, b: f128) -> bool { + // CHECK: fcmp une fp128 %{{.+}}, %{{.+}} + a != b +} + +// CHECK-LABEL: i1 @f128_gt( +#[no_mangle] +pub fn f128_gt(a: f128, b: f128) -> bool { + // CHECK: fcmp ogt fp128 %{{.+}}, %{{.+}} + a > b +} + +// CHECK-LABEL: i1 @f128_ge( +#[no_mangle] +pub fn f128_ge(a: f128, b: f128) -> bool { + // CHECK: fcmp oge fp128 %{{.+}}, %{{.+}} + a >= b +} + +// CHECK-LABEL: i1 @f128_lt( +#[no_mangle] +pub fn f128_lt(a: f128, b: f128) -> bool { + // CHECK: fcmp olt fp128 %{{.+}}, %{{.+}} + a < b +} + +// CHECK-LABEL: i1 @f128_le( +#[no_mangle] +pub fn f128_le(a: f128, b: f128) -> bool { + // CHECK: fcmp ole fp128 %{{.+}}, %{{.+}} + a <= b +} + +// CHECK-LABEL: fp128 @f128_neg( +#[no_mangle] +pub fn f128_neg(a: f128) -> f128 { + // CHECK: fneg fp128 + -a +} + +// CHECK-LABEL: fp128 @f128_add( +#[no_mangle] +pub fn f128_add(a: f128, b: f128) -> f128 { + // CHECK: fadd fp128 %{{.+}}, %{{.+}} + a + b +} + +// CHECK-LABEL: fp128 @f128_sub( +#[no_mangle] +pub fn f128_sub(a: f128, b: f128) -> f128 { + // CHECK: fsub fp128 %{{.+}}, %{{.+}} + a - b +} + +// CHECK-LABEL: fp128 @f128_mul( +#[no_mangle] +pub fn f128_mul(a: f128, b: f128) -> f128 { + // CHECK: fmul fp128 %{{.+}}, %{{.+}} + a * b +} + +// CHECK-LABEL: fp128 @f128_div( +#[no_mangle] +pub fn f128_div(a: f128, b: f128) -> f128 { + // CHECK: fdiv fp128 %{{.+}}, %{{.+}} + a / b +} + +// CHECK-LABEL: fp128 @f128_rem( +#[no_mangle] +pub fn f128_rem(a: f128, b: f128) -> f128 { + // CHECK: frem fp128 %{{.+}}, %{{.+}} + a % b +} + +// CHECK-LABEL: void @f128_add_assign( +#[no_mangle] +pub fn f128_add_assign(a: &mut f128, b: f128) { + // CHECK: fadd fp128 %{{.+}}, %{{.+}} + // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}} + *a += b; +} + +// CHECK-LABEL: void @f128_sub_assign( +#[no_mangle] +pub fn f128_sub_assign(a: &mut f128, b: f128) { + // CHECK: fsub fp128 %{{.+}}, %{{.+}} + // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}} + *a -= b; +} + +// CHECK-LABEL: void @f128_mul_assign( +#[no_mangle] +pub fn f128_mul_assign(a: &mut f128, b: f128) { + // CHECK: fmul fp128 %{{.+}}, %{{.+}} + // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}} + *a *= b +} + +// CHECK-LABEL: void @f128_div_assign( +#[no_mangle] +pub fn f128_div_assign(a: &mut f128, b: f128) { + // CHECK: fdiv fp128 %{{.+}}, %{{.+}} + // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}} + *a /= b +} + +// CHECK-LABEL: void @f128_rem_assign( +#[no_mangle] +pub fn f128_rem_assign(a: &mut f128, b: f128) { + // CHECK: frem fp128 %{{.+}}, %{{.+}} + // CHECK-NEXT: store fp128 %{{.+}}, ptr %{{.+}} + *a %= b +} diff --git a/tests/codegen/float/f16.rs b/tests/codegen/float/f16.rs new file mode 100644 index 0000000000000..d1f75cc3b6851 --- /dev/null +++ b/tests/codegen/float/f16.rs @@ -0,0 +1,129 @@ +// Verify that our intrinsics generate the correct LLVM calls for f16 + +#![crate_type = "lib"] +#![feature(f16)] +#![feature(core_intrinsics)] + +// CHECK-LABEL: i1 @f16_eq( +#[no_mangle] +pub fn f16_eq(a: f16, b: f16) -> bool { + // CHECK: fcmp oeq half %{{.+}}, %{{.+}} + a == b +} + +// CHECK-LABEL: i1 @f16_ne( +#[no_mangle] +pub fn f16_ne(a: f16, b: f16) -> bool { + // CHECK: fcmp une half %{{.+}}, %{{.+}} + a != b +} + +// CHECK-LABEL: i1 @f16_gt( +#[no_mangle] +pub fn f16_gt(a: f16, b: f16) -> bool { + // CHECK: fcmp ogt half %{{.+}}, %{{.+}} + a > b +} + +// CHECK-LABEL: i1 @f16_ge( +#[no_mangle] +pub fn f16_ge(a: f16, b: f16) -> bool { + // CHECK: fcmp oge half %{{.+}}, %{{.+}} + a >= b +} + +// CHECK-LABEL: i1 @f16_lt( +#[no_mangle] +pub fn f16_lt(a: f16, b: f16) -> bool { + // CHECK: fcmp olt half %{{.+}}, %{{.+}} + a < b +} + +// CHECK-LABEL: i1 @f16_le( +#[no_mangle] +pub fn f16_le(a: f16, b: f16) -> bool { + // CHECK: fcmp ole half %{{.+}}, %{{.+}} + a <= b +} + +// CHECK-LABEL: half @f16_neg( +#[no_mangle] +pub fn f16_neg(a: f16) -> f16 { + // CHECK: fneg half %{{.+}} + -a +} + +// CHECK-LABEL: half @f16_add( +#[no_mangle] +pub fn f16_add(a: f16, b: f16) -> f16 { + // CHECK: fadd half %{{.+}}, %{{.+}} + a + b +} + +// CHECK-LABEL: half @f16_sub( +#[no_mangle] +pub fn f16_sub(a: f16, b: f16) -> f16 { + // CHECK: fsub half %{{.+}}, %{{.+}} + a - b +} + +// CHECK-LABEL: half @f16_mul( +#[no_mangle] +pub fn f16_mul(a: f16, b: f16) -> f16 { + // CHECK: fmul half %{{.+}}, %{{.+}} + a * b +} + +// CHECK-LABEL: half @f16_div( +#[no_mangle] +pub fn f16_div(a: f16, b: f16) -> f16 { + // CHECK: fdiv half %{{.+}}, %{{.+}} + a / b +} + +// CHECK-LABEL: half @f16_rem( +#[no_mangle] +pub fn f16_rem(a: f16, b: f16) -> f16 { + // CHECK: frem half %{{.+}}, %{{.+}} + a % b +} + +// CHECK-LABEL: void @f16_add_assign( +#[no_mangle] +pub fn f16_add_assign(a: &mut f16, b: f16) { + // CHECK: fadd half %{{.+}}, %{{.+}} + // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}} + *a += b; +} + +// CHECK-LABEL: void @f16_sub_assign( +#[no_mangle] +pub fn f16_sub_assign(a: &mut f16, b: f16) { + // CHECK: fsub half %{{.+}}, %{{.+}} + // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}} + *a -= b; +} + +// CHECK-LABEL: void @f16_mul_assign( +#[no_mangle] +pub fn f16_mul_assign(a: &mut f16, b: f16) { + // CHECK: fmul half %{{.+}}, %{{.+}} + // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}} + *a *= b +} + +// CHECK-LABEL: void @f16_div_assign( +#[no_mangle] +pub fn f16_div_assign(a: &mut f16, b: f16) { + // CHECK: fdiv half %{{.+}}, %{{.+}} + // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}} + *a /= b +} + +// CHECK-LABEL: void @f16_rem_assign( +#[no_mangle] +pub fn f16_rem_assign(a: &mut f16, b: f16) { + // CHECK: frem half %{{.+}}, %{{.+}} + // CHECK-NEXT: store half %{{.+}}, ptr %{{.+}} + *a %= b +} diff --git a/tests/ui/array-slice-vec/vector-no-ann.stderr b/tests/ui/array-slice-vec/vector-no-ann.stderr index 24b6abfb34260..716971eb12045 100644 --- a/tests/ui/array-slice-vec/vector-no-ann.stderr +++ b/tests/ui/array-slice-vec/vector-no-ann.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Vec` +error[E0282]: type annotations needed for `Vec<_>` --> $DIR/vector-no-ann.rs:2:9 | LL | let _foo = Vec::new(); diff --git a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr index 92f38d5a79620..640d946421a5f 100644 --- a/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr +++ b/tests/ui/async-await/track-caller/async-closure-gate.afn.stderr @@ -62,7 +62,7 @@ error[E0308]: mismatched types --> $DIR/async-closure-gate.rs:27:5 | LL | fn foo3() { - | - help: a return type might be missing here: `-> _` + | - help: try adding a return type: `-> impl Future` LL | / async { LL | | LL | | let _ = #[track_caller] || { @@ -78,7 +78,7 @@ error[E0308]: mismatched types --> $DIR/async-closure-gate.rs:44:5 | LL | fn foo5() { - | - help: a return type might be missing here: `-> _` + | - help: try adding a return type: `-> impl Future` LL | / async { LL | | LL | | let _ = || { diff --git a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr index 92f38d5a79620..640d946421a5f 100644 --- a/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr +++ b/tests/ui/async-await/track-caller/async-closure-gate.nofeat.stderr @@ -62,7 +62,7 @@ error[E0308]: mismatched types --> $DIR/async-closure-gate.rs:27:5 | LL | fn foo3() { - | - help: a return type might be missing here: `-> _` + | - help: try adding a return type: `-> impl Future` LL | / async { LL | | LL | | let _ = #[track_caller] || { @@ -78,7 +78,7 @@ error[E0308]: mismatched types --> $DIR/async-closure-gate.rs:44:5 | LL | fn foo5() { - | - help: a return type might be missing here: `-> _` + | - help: try adding a return type: `-> impl Future` LL | / async { LL | | LL | | let _ = || { diff --git a/tests/ui/const-generics/defaults/doesnt_infer.rs b/tests/ui/const-generics/defaults/doesnt_infer.rs index 9c59e672d8e4c..e14c08fc1487d 100644 --- a/tests/ui/const-generics/defaults/doesnt_infer.rs +++ b/tests/ui/const-generics/defaults/doesnt_infer.rs @@ -9,5 +9,5 @@ impl Foo { fn main() { let foo = Foo::<1>::foo(); let foo = Foo::foo(); - //~^ error: type annotations needed for `Foo` + //~^ ERROR type annotations needed for `Foo<_>` } diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr index 65ee0ecfdc5a4..93d5860339712 100644 --- a/tests/ui/const-generics/defaults/doesnt_infer.stderr +++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Foo` +error[E0282]: type annotations needed for `Foo<_>` --> $DIR/doesnt_infer.rs:11:9 | LL | let foo = Foo::foo(); diff --git a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr index 5b296a14869fe..5ee42c19dd3db 100644 --- a/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/tests/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed for `Mask<_, N>` +error[E0283]: type annotations needed for `Mask<_, _>` --> $DIR/issue-91614.rs:6:9 | LL | let y = Mask::<_, _>::splat(false); diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr index f27d52a1437f5..5cda4681b5c8b 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.full.stderr @@ -18,7 +18,7 @@ help: try adding a `where` bound LL | pub const fn new() -> Self where [(); Self::SIZE]: { | +++++++++++++++++++++++ -error[E0282]: type annotations needed for `ArrayHolder` +error[E0282]: type annotations needed for `ArrayHolder<_>` --> $DIR/issue-62504.rs:26:9 | LL | let mut array = ArrayHolder::new(); diff --git a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr index 1664669eee05a..beb159779ff5c 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-62504.min.stderr @@ -22,7 +22,7 @@ note: tuple struct defined here LL | struct ArrayHolder([u32; X]); | ^^^^^^^^^^^ -error[E0282]: type annotations needed for `ArrayHolder` +error[E0282]: type annotations needed for `ArrayHolder<_>` --> $DIR/issue-62504.rs:26:9 | LL | let mut array = ArrayHolder::new(); diff --git a/tests/ui/generic-const-items/inference-failure.stderr b/tests/ui/generic-const-items/inference-failure.stderr index 10ecd83ec53c4..594743a47f424 100644 --- a/tests/ui/generic-const-items/inference-failure.stderr +++ b/tests/ui/generic-const-items/inference-failure.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Option` +error[E0282]: type annotations needed for `Option<_>` --> $DIR/inference-failure.rs:8:9 | LL | let _ = NONE; diff --git a/tests/ui/generic-const-items/parameter-defaults.stderr b/tests/ui/generic-const-items/parameter-defaults.stderr index b8220af5d0e93..13562c98f6d96 100644 --- a/tests/ui/generic-const-items/parameter-defaults.stderr +++ b/tests/ui/generic-const-items/parameter-defaults.stderr @@ -4,7 +4,7 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type` LL | const NONE: Option = None::; | ^^^^^^ -error[E0282]: type annotations needed for `Option` +error[E0282]: type annotations needed for `Option<_>` --> $DIR/parameter-defaults.rs:13:9 | LL | let _ = NONE; diff --git a/tests/ui/imports/redundant-import-extern-prelude.rs b/tests/ui/imports/redundant-import-extern-prelude.rs new file mode 100644 index 0000000000000..acf59b09a1dec --- /dev/null +++ b/tests/ui/imports/redundant-import-extern-prelude.rs @@ -0,0 +1,17 @@ +// Check that we detect imports that are redundant due to the extern prelude +// and that we emit a reasonable diagnostic. +// issue: rust-lang/rust#121915 +//~^^^ NOTE the item `aux_issue_121915` is already defined by the extern prelude + +// See also the discussion in . + +//@ compile-flags: --extern aux_issue_121915 --edition 2018 +//@ aux-build: aux-issue-121915.rs + +#[deny(unused_imports)] +//~^ NOTE the lint level is defined here +fn main() { + use aux_issue_121915; + //~^ ERROR the item `aux_issue_121915` is imported redundantly + aux_issue_121915::item(); +} diff --git a/tests/ui/imports/redundant-import-issue-121915.stderr b/tests/ui/imports/redundant-import-extern-prelude.stderr similarity index 68% rename from tests/ui/imports/redundant-import-issue-121915.stderr rename to tests/ui/imports/redundant-import-extern-prelude.stderr index 0047d7c34207c..d49e013c3d34d 100644 --- a/tests/ui/imports/redundant-import-issue-121915.stderr +++ b/tests/ui/imports/redundant-import-extern-prelude.stderr @@ -1,11 +1,11 @@ error: the item `aux_issue_121915` is imported redundantly - --> $DIR/redundant-import-issue-121915.rs:6:9 + --> $DIR/redundant-import-extern-prelude.rs:14:9 | LL | use aux_issue_121915; - | ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by prelude + | ^^^^^^^^^^^^^^^^ the item `aux_issue_121915` is already defined by the extern prelude | note: the lint level is defined here - --> $DIR/redundant-import-issue-121915.rs:4:8 + --> $DIR/redundant-import-extern-prelude.rs:11:8 | LL | #[deny(unused_imports)] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/imports/redundant-import-issue-121915.rs b/tests/ui/imports/redundant-import-issue-121915.rs deleted file mode 100644 index 237acc4af2565..0000000000000 --- a/tests/ui/imports/redundant-import-issue-121915.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ compile-flags: --extern aux_issue_121915 --edition 2018 -//@ aux-build: aux-issue-121915.rs - -#[deny(unused_imports)] -fn main() { - use aux_issue_121915; - //~^ ERROR the item `aux_issue_121915` is imported redundantly - aux_issue_121915::item(); -} diff --git a/tests/ui/imports/redundant-import-lang-prelude-attr.rs b/tests/ui/imports/redundant-import-lang-prelude-attr.rs new file mode 100644 index 0000000000000..18d0e688206b0 --- /dev/null +++ b/tests/ui/imports/redundant-import-lang-prelude-attr.rs @@ -0,0 +1,18 @@ +// Check that we detect imports (of built-in attributes) that are redundant due to +// the language prelude and that we emit a reasonable diagnostic. +//~^^ NOTE the item `allow` is already defined by the extern prelude + +// Note that we use the term "extern prelude" in the label even though "language prelude" +// would be more correct. However, it's not worth special-casing this. + +// See also the discussion in . + +//@ edition: 2018 + +#![deny(unused_imports)] +//~^ NOTE the lint level is defined here + +use allow; //~ ERROR the item `allow` is imported redundantly + +#[allow(unused)] +fn main() {} diff --git a/tests/ui/imports/redundant-import-lang-prelude-attr.stderr b/tests/ui/imports/redundant-import-lang-prelude-attr.stderr new file mode 100644 index 0000000000000..a3ca7ce24ed0b --- /dev/null +++ b/tests/ui/imports/redundant-import-lang-prelude-attr.stderr @@ -0,0 +1,14 @@ +error: the item `allow` is imported redundantly + --> $DIR/redundant-import-lang-prelude-attr.rs:15:5 + | +LL | use allow; + | ^^^^^ the item `allow` is already defined by the extern prelude + | +note: the lint level is defined here + --> $DIR/redundant-import-lang-prelude-attr.rs:12:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/redundant-import-lang-prelude.rs b/tests/ui/imports/redundant-import-lang-prelude.rs new file mode 100644 index 0000000000000..3faf9423c37f8 --- /dev/null +++ b/tests/ui/imports/redundant-import-lang-prelude.rs @@ -0,0 +1,18 @@ +// Check that we detect imports that are redundant due to the language prelude +// and that we emit a reasonable diagnostic. +//~^^ NOTE the item `u8` is already defined by the extern prelude + +// Note that we use the term "extern prelude" in the label even though "language prelude" +// would be more correct. However, it's not worth special-casing this. + +// See also the discussion in . + +#![deny(unused_imports)] +//~^ NOTE the lint level is defined here + +use std::primitive::u8; +//~^ ERROR the item `u8` is imported redundantly + +const _: u8 = 0; + +fn main() {} diff --git a/tests/ui/imports/redundant-import-lang-prelude.stderr b/tests/ui/imports/redundant-import-lang-prelude.stderr new file mode 100644 index 0000000000000..e6a4535f9802d --- /dev/null +++ b/tests/ui/imports/redundant-import-lang-prelude.stderr @@ -0,0 +1,14 @@ +error: the item `u8` is imported redundantly + --> $DIR/redundant-import-lang-prelude.rs:13:5 + | +LL | use std::primitive::u8; + | ^^^^^^^^^^^^^^^^^^ the item `u8` is already defined by the extern prelude + | +note: the lint level is defined here + --> $DIR/redundant-import-lang-prelude.rs:10:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/imports/redundant-import-undetected-macro-use-prelude.rs b/tests/ui/imports/redundant-import-undetected-macro-use-prelude.rs new file mode 100644 index 0000000000000..4a79cb2c208f9 --- /dev/null +++ b/tests/ui/imports/redundant-import-undetected-macro-use-prelude.rs @@ -0,0 +1,23 @@ +// This test demonstrates that we currently don't make an effort to detect +// imports made redundant by the `#[macro_use]` prelude. +// See also the discussion in . + +//@ check-pass +//@ aux-build:two_macros.rs +#![deny(unused_imports)] + +#[macro_use] +extern crate two_macros; + +// This import is actually redundant due to the `#[macro_use]` above. +use two_macros::n; + +// We intentionally reference two items from the `#[macro_use]`'d crate because +// if we were to reference only item `n`, we would flag the `#[macro_use]` +// attribute as redundant which would be correct of course. +// That's interesting on its own -- we prefer "blaming" the `#[macro_use]` +// over the import (here, `use two_macros::n`) when it comes to redundancy. +n!(); +m!(); + +fn main() {} diff --git a/tests/ui/inference/cannot-infer-closure-circular.rs b/tests/ui/inference/cannot-infer-closure-circular.rs index affb481496d02..1b41171e74a76 100644 --- a/tests/ui/inference/cannot-infer-closure-circular.rs +++ b/tests/ui/inference/cannot-infer-closure-circular.rs @@ -4,7 +4,7 @@ fn main() { // error handles this gracefully, and in particular doesn't generate an extra // note about the `?` operator in the closure body, which isn't relevant to // the inference. - let x = |r| { //~ ERROR type annotations needed for `Result<(), E>` + let x = |r| { //~ ERROR type annotations needed for `Result<(), _>` let v = r?; Ok(v) }; diff --git a/tests/ui/inference/cannot-infer-closure-circular.stderr b/tests/ui/inference/cannot-infer-closure-circular.stderr index e3cf0cca83711..a16e832f8ef91 100644 --- a/tests/ui/inference/cannot-infer-closure-circular.stderr +++ b/tests/ui/inference/cannot-infer-closure-circular.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Result<(), E>` +error[E0282]: type annotations needed for `Result<(), _>` --> $DIR/cannot-infer-closure-circular.rs:7:14 | LL | let x = |r| { diff --git a/tests/ui/inference/erase-type-params-in-label.stderr b/tests/ui/inference/erase-type-params-in-label.stderr index 546e679f2d0bc..4e9a74c1e403d 100644 --- a/tests/ui/inference/erase-type-params-in-label.stderr +++ b/tests/ui/inference/erase-type-params-in-label.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed for `Foo` +error[E0283]: type annotations needed for `Foo` --> $DIR/erase-type-params-in-label.rs:2:9 | LL | let foo = foo(1, ""); @@ -15,7 +15,7 @@ help: consider giving `foo` an explicit type, where the type for type parameter LL | let foo: Foo = foo(1, ""); | ++++++++++++++++++++++ -error[E0283]: type annotations needed for `Bar` +error[E0283]: type annotations needed for `Bar` --> $DIR/erase-type-params-in-label.rs:5:9 | LL | let bar = bar(1, ""); diff --git a/tests/ui/inference/issue-104649.stderr b/tests/ui/inference/issue-104649.stderr index afece960914da..391ed16f349d7 100644 --- a/tests/ui/inference/issue-104649.stderr +++ b/tests/ui/inference/issue-104649.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `A, Error>>` +error[E0282]: type annotations needed for `A, Error>>` --> $DIR/issue-104649.rs:24:9 | LL | let a = A(Result::Ok(Result::Ok(()))); diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr index 6c93241ea07cd..6391672f8617d 100644 --- a/tests/ui/inference/issue-72690.stderr +++ b/tests/ui/inference/issue-72690.stderr @@ -50,7 +50,7 @@ help: try using a fully qualified path to specify the expected types LL | |x| String::from(>::as_ref("x")); | ++++++++++++++++++++++++++ ~ -error[E0283]: type annotations needed for `&T` +error[E0283]: type annotations needed for `&_` --> $DIR/issue-72690.rs:17:9 | LL | let _ = "x".as_ref(); diff --git a/tests/ui/inference/issue-83606.rs b/tests/ui/inference/issue-83606.rs index c387046e91008..4454b5e60f069 100644 --- a/tests/ui/inference/issue-83606.rs +++ b/tests/ui/inference/issue-83606.rs @@ -6,5 +6,5 @@ fn foo(_: impl std::fmt::Display) -> [usize; N] { fn main() { let _ = foo("foo"); - //~^ ERROR: type annotations needed for `[usize; N]` + //~^ ERROR type annotations needed for `[usize; _]` } diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr index 00de4029e4281..8e6ff6d568de7 100644 --- a/tests/ui/inference/issue-83606.stderr +++ b/tests/ui/inference/issue-83606.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `[usize; N]` +error[E0282]: type annotations needed for `[usize; _]` --> $DIR/issue-83606.rs:8:9 | LL | let _ = foo("foo"); diff --git a/tests/ui/issues/issue-11771.stderr b/tests/ui/issues/issue-11771.stderr index 161fce4b0315c..d4a4647f6a10d 100644 --- a/tests/ui/issues/issue-11771.stderr +++ b/tests/ui/issues/issue-11771.stderr @@ -6,15 +6,15 @@ LL | 1 + | = help: the trait `Add<()>` is not implemented for `{integer}` = help: the following other types implement trait `Add`: + <&'a f128 as Add> + <&'a f16 as Add> <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> <&'a i32 as Add> <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + and 56 others error[E0277]: cannot add `()` to `{integer}` --> $DIR/issue-11771.rs:8:7 @@ -24,15 +24,15 @@ LL | 1 + | = help: the trait `Add<()>` is not implemented for `{integer}` = help: the following other types implement trait `Add`: + <&'a f128 as Add> + <&'a f16 as Add> <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> <&'a i32 as Add> <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + and 56 others error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-12187-1.stderr b/tests/ui/issues/issue-12187-1.stderr index 93dc1df8f6342..704854fe58581 100644 --- a/tests/ui/issues/issue-12187-1.stderr +++ b/tests/ui/issues/issue-12187-1.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `&T` +error[E0282]: type annotations needed for `&_` --> $DIR/issue-12187-1.rs:6:9 | LL | let &v = new(); diff --git a/tests/ui/issues/issue-12187-2.stderr b/tests/ui/issues/issue-12187-2.stderr index e9ba52ff4fde2..eeef63a1d0bd2 100644 --- a/tests/ui/issues/issue-12187-2.stderr +++ b/tests/ui/issues/issue-12187-2.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `&T` +error[E0282]: type annotations needed for `&_` --> $DIR/issue-12187-2.rs:6:9 | LL | let &v = new(); diff --git a/tests/ui/issues/issue-17551.stderr b/tests/ui/issues/issue-17551.stderr index 68f54a310844b..b9cb76fc298d9 100644 --- a/tests/ui/issues/issue-17551.stderr +++ b/tests/ui/issues/issue-17551.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `B` +error[E0282]: type annotations needed for `B<_>` --> $DIR/issue-17551.rs:6:9 | LL | let foo = B(marker::PhantomData); diff --git a/tests/ui/issues/issue-23046.stderr b/tests/ui/issues/issue-23046.stderr index b6e23814543f3..f70ac0c9f388a 100644 --- a/tests/ui/issues/issue-23046.stderr +++ b/tests/ui/issues/issue-23046.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Expr<'_, VAR>` +error[E0282]: type annotations needed for `Expr<'_, _>` --> $DIR/issue-23046.rs:17:15 | LL | let ex = |x| { diff --git a/tests/ui/issues/issue-50582.stderr b/tests/ui/issues/issue-50582.stderr index 1967b51128f61..b765d2f087d0a 100644 --- a/tests/ui/issues/issue-50582.stderr +++ b/tests/ui/issues/issue-50582.stderr @@ -16,15 +16,15 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new(); | = help: the trait `Add<()>` is not implemented for `{integer}` = help: the following other types implement trait `Add`: + <&'a f128 as Add> + <&'a f16 as Add> <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> <&'a i32 as Add> <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + and 56 others error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-98299.stderr b/tests/ui/issues/issue-98299.stderr index e99d8e5cc80a0..becf16d1db91b 100644 --- a/tests/ui/issues/issue-98299.stderr +++ b/tests/ui/issues/issue-98299.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `SmallCString` +error[E0282]: type annotations needed for `SmallCString<_>` --> $DIR/issue-98299.rs:4:36 | LL | SmallCString::try_from(p).map(|cstr| cstr); diff --git a/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.rs b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.rs new file mode 100644 index 0000000000000..59bb65a357bae --- /dev/null +++ b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.rs @@ -0,0 +1,39 @@ +//@ run-pass + +#![warn(unused_parens)] +#![allow(dead_code)] + +trait Foo { + fn bar(); + fn tar(); +} + +macro_rules! unused_parens { + ($ty:ident) => { + impl<$ty: Foo> Foo for ($ty,) { + fn bar() { <$ty>::bar() } + fn tar() {} + } + }; + + ($ty:ident $(, $rest:ident)*) => { + impl<$ty: Foo, $($rest: Foo),*> Foo for ($ty, $($rest),*) { + fn bar() { + <$ty>::bar(); + <($($rest),*)>::bar() //~WARN unnecessary parentheses around type + } + fn tar() { + let (_t) = 1; //~WARN unnecessary parentheses around pattern + //~| WARN unnecessary parentheses around pattern + let (_t1,) = (1,); + let (_t2, _t3) = (1, 2); + } + } + + unused_parens!($($rest),*); + } +} + +unused_parens!(T1, T2, T3); + +fn main() {} diff --git a/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr new file mode 100644 index 0000000000000..b1390debec73b --- /dev/null +++ b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr @@ -0,0 +1,40 @@ +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-in-macro-issue-120642.rs:26:19 + | +LL | let (_t) = 1; + | ^^^^ +... +LL | unused_parens!(T1, T2, T3); + | -------------------------- in this macro invocation + | +note: the lint level is defined here + --> $DIR/unused-parens-in-macro-issue-120642.rs:3:9 + | +LL | #![warn(unused_parens)] + | ^^^^^^^^^^^^^ + = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unnecessary parentheses around type + --> $DIR/unused-parens-in-macro-issue-120642.rs:23:18 + | +LL | <($($rest),*)>::bar() + | ^^^^^^^^^^^^ +... +LL | unused_parens!(T1, T2, T3); + | -------------------------- in this macro invocation + | + = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-in-macro-issue-120642.rs:26:19 + | +LL | let (_t) = 1; + | ^^^^ +... +LL | unused_parens!(T1, T2, T3); + | -------------------------- in this macro invocation + | + = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: 3 warnings emitted + diff --git a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr index 0a022dc3984f5..b2d2d039ff6a2 100644 --- a/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr +++ b/tests/ui/methods/method-ambig-one-trait-unknown-int-type.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Vec` +error[E0282]: type annotations needed for `Vec<_>` --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9 | LL | let mut x = Vec::new(); diff --git a/tests/ui/mismatched_types/binops.stderr b/tests/ui/mismatched_types/binops.stderr index f8047c8e2d449..099c580a0565e 100644 --- a/tests/ui/mismatched_types/binops.stderr +++ b/tests/ui/mismatched_types/binops.stderr @@ -6,15 +6,15 @@ LL | 1 + Some(1); | = help: the trait `Add>` is not implemented for `{integer}` = help: the following other types implement trait `Add`: + <&'a f128 as Add> + <&'a f16 as Add> <&'a f32 as Add> <&'a f64 as Add> <&'a i128 as Add> <&'a i16 as Add> <&'a i32 as Add> <&'a i64 as Add> - <&'a i8 as Add> - <&'a isize as Add> - and 48 others + and 56 others error[E0277]: cannot subtract `Option<{integer}>` from `usize` --> $DIR/binops.rs:3:16 @@ -37,15 +37,15 @@ LL | 3 * (); | = help: the trait `Mul<()>` is not implemented for `{integer}` = help: the following other types implement trait `Mul`: + <&'a f128 as Mul> + <&'a f16 as Mul> <&'a f32 as Mul> <&'a f64 as Mul> <&'a i128 as Mul> <&'a i16 as Mul> <&'a i32 as Mul> <&'a i64 as Mul> - <&'a i8 as Mul> - <&'a isize as Mul> - and 49 others + and 57 others error[E0277]: cannot divide `{integer}` by `&str` --> $DIR/binops.rs:5:7 @@ -55,15 +55,15 @@ LL | 4 / ""; | = help: the trait `Div<&str>` is not implemented for `{integer}` = help: the following other types implement trait `Div`: + <&'a f128 as Div> + <&'a f16 as Div> <&'a f32 as Div> <&'a f64 as Div> <&'a i128 as Div> <&'a i16 as Div> <&'a i32 as Div> <&'a i64 as Div> - <&'a i8 as Div> - <&'a isize as Div> - and 54 others + and 62 others error[E0277]: can't compare `{integer}` with `String` --> $DIR/binops.rs:6:7 diff --git a/tests/ui/suggestions/return-closures.stderr b/tests/ui/suggestions/return-closures.stderr index 97c13200ac36b..ef1f50b8a6ce8 100644 --- a/tests/ui/suggestions/return-closures.stderr +++ b/tests/ui/suggestions/return-closures.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/return-closures.rs:3:5 | LL | fn foo() { - | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32` + | - help: try adding a return type: `-> impl FnOnce(&i32) -> i32` LL | LL | |x: &i32| 1i32 | ^^^^^^^^^^^^^^ expected `()`, found closure diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs index af25010e3bd28..0ffa82497899a 100644 --- a/tests/ui/traits/copy-guessing.rs +++ b/tests/ui/traits/copy-guessing.rs @@ -18,7 +18,7 @@ fn assert_impls_fnR>(_: &T){} fn main() { let n = None; - //~^ ERROR type annotations needed for `Option` + //~^ ERROR type annotations needed for `Option<_>` let e = S(&n); let f = || { // S being copy is critical for this to work diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr index 750140c017c25..cae91579ee0eb 100644 --- a/tests/ui/traits/copy-guessing.stderr +++ b/tests/ui/traits/copy-guessing.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Option` +error[E0282]: type annotations needed for `Option<_>` --> $DIR/copy-guessing.rs:20:9 | LL | let n = None; diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr index 5be8d2f4b325e..0f4b3c3c877c9 100644 --- a/tests/ui/traits/issue-77982.stderr +++ b/tests/ui/traits/issue-77982.stderr @@ -55,7 +55,7 @@ help: try using a fully qualified path to specify the expected types LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(>::into(0u32))).collect(); | +++++++++++++++++++++++ ~ -error[E0283]: type annotations needed for `Box` +error[E0283]: type annotations needed for `Box<_>` --> $DIR/issue-77982.rs:37:9 | LL | let _ = ().foo(); @@ -73,7 +73,7 @@ help: consider giving this pattern a type, where the type for type parameter `T` LL | let _: Box = ().foo(); | ++++++++ -error[E0283]: type annotations needed for `Box` +error[E0283]: type annotations needed for `Box<_>` --> $DIR/issue-77982.rs:41:9 | LL | let _ = (&()).bar(); diff --git a/tests/ui/type-inference/or_else-multiple-type-params.stderr b/tests/ui/type-inference/or_else-multiple-type-params.stderr index d1bbe308ed3dd..3176a2d490ebc 100644 --- a/tests/ui/type-inference/or_else-multiple-type-params.stderr +++ b/tests/ui/type-inference/or_else-multiple-type-params.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Result` +error[E0282]: type annotations needed for `Result` --> $DIR/or_else-multiple-type-params.rs:7:18 | LL | .or_else(|err| { diff --git a/tests/ui/typeck/return_type_containing_closure.rs b/tests/ui/typeck/return_type_containing_closure.rs index 8b826daeede48..b81cac0a58ab9 100644 --- a/tests/ui/typeck/return_type_containing_closure.rs +++ b/tests/ui/typeck/return_type_containing_closure.rs @@ -1,5 +1,5 @@ #[allow(unused)] -fn foo() { //~ HELP a return type might be missing here +fn foo() { //~ HELP try adding a return type vec!['a'].iter().map(|c| c) //~^ ERROR mismatched types [E0308] //~| NOTE expected `()`, found `Map, ...>` diff --git a/tests/ui/typeck/return_type_containing_closure.stderr b/tests/ui/typeck/return_type_containing_closure.stderr index ea9c74be36238..3f14650a82cce 100644 --- a/tests/ui/typeck/return_type_containing_closure.stderr +++ b/tests/ui/typeck/return_type_containing_closure.stderr @@ -10,10 +10,10 @@ help: consider using a semicolon here | LL | vec!['a'].iter().map(|c| c); | + -help: a return type might be missing here +help: try adding a return type | -LL | fn foo() -> _ { - | ++++ +LL | fn foo() -> impl Iterator { + | ++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr index 5a76ef3e87587..058dbb1e220f6 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Option` +error[E0282]: type annotations needed for `Option<_>` --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:8:9 | LL | let mut closure0 = None;