Auto merge of #123762 - fmease:rollup-jdfx54z, r=fmease

Rollup of 8 pull requests

Successful merges:

 - #122470 (`f16` and `f128` step 4: basic library support)
 - #122954 (Be more specific when flagging imports as redundant due to the extern prelude)
 - #123314 (Skip `unused_parens` report for `Paren(Path(..))` in macro.)
 - #123360 (Document restricted_std)
 - #123661 (Stabilize `cstr_count_bytes`)
 - #123703 (Use `fn` ptr signature instead of `{closure@..}` in infer error)
 - #123756 (clean up docs for `File::sync_*`)
 - #123761 (Use `suggest_impl_trait` in return type suggestion on type error)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-04-11 00:35:00 +00:00
commit 4435924bb6
70 changed files with 872 additions and 186 deletions

View file

@ -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<String> {
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,
),
(
tcx.lang_items().fn_once_trait(),
tcx.lang_items().fn_once_output(),
infcx.tcx.lang_items().fn_mut_trait(),
infcx.tcx.lang_items().fn_once_output(),
format_as_parenthesized,
),
(
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

View file

@ -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 {

View file

@ -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 ->

View file

@ -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<SourceKindSubdiag<'a>>,
#[subdiagnostic]
pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
#[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<SourceKindSubdiag<'a>>,
#[subdiagnostic]
pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
#[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<SourceKindSubdiag<'a>>,
#[subdiagnostic]
pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
#[note(infer_full_type_written)]
pub was_written: Option<()>,
pub path: PathBuf,
}
// Used when a better one isn't available

View file

@ -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<TyCtxt<'tcx>> 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<PathBuf>) {
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),
}
}
}

View file

@ -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}"),

View file

@ -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);
}
}

View file

@ -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]

View file

@ -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)*) => ($(

View file

@ -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) => {

View file

@ -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

View file

@ -11,5 +11,7 @@ macro_rules! floating {
};
}
floating! { f16 }
floating! { f32 }
floating! { f64 }
floating! { f128 }

View file

@ -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"]

View file

@ -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")]

View file

@ -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 {}

View file

@ -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 {}

View file

@ -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 }

View file

@ -1074,7 +1074,22 @@ mod prim_tuple {}
#[doc(hidden)]
impl<T> (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> (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.

11
library/std/src/f128.rs Normal file
View file

@ -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;

View file

@ -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
);
};
}

11
library/std/src/f16.rs Normal file
View file

@ -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;

View file

@ -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
);
};
}

View file

@ -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()
}

View file

@ -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;

129
tests/codegen/float/f128.rs Normal file
View file

@ -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
}

129
tests/codegen/float/f16.rs Normal file
View file

@ -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
}

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `Vec<T>`
error[E0282]: type annotations needed for `Vec<_>`
--> $DIR/vector-no-ann.rs:2:9
|
LL | let _foo = Vec::new();

View file

@ -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<Output = ()>`
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<Output = ()>`
LL | / async {
LL | |
LL | | let _ = || {

View file

@ -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<Output = ()>`
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<Output = ()>`
LL | / async {
LL | |
LL | | let _ = || {

View file

@ -9,5 +9,5 @@ impl<const N: u32> Foo<N> {
fn main() {
let foo = Foo::<1>::foo();
let foo = Foo::foo();
//~^ error: type annotations needed for `Foo<N>`
//~^ ERROR type annotations needed for `Foo<_>`
}

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `Foo<N>`
error[E0282]: type annotations needed for `Foo<_>`
--> $DIR/doesnt_infer.rs:11:9
|
LL | let foo = Foo::foo();

View file

@ -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);

View file

@ -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<X>`
error[E0282]: type annotations needed for `ArrayHolder<_>`
--> $DIR/issue-62504.rs:26:9
|
LL | let mut array = ArrayHolder::new();

View file

@ -22,7 +22,7 @@ note: tuple struct defined here
LL | struct ArrayHolder<const X: usize>([u32; X]);
| ^^^^^^^^^^^
error[E0282]: type annotations needed for `ArrayHolder<X>`
error[E0282]: type annotations needed for `ArrayHolder<_>`
--> $DIR/issue-62504.rs:26:9
|
LL | let mut array = ArrayHolder::new();

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `Option<T>`
error[E0282]: type annotations needed for `Option<_>`
--> $DIR/inference-failure.rs:8:9
|
LL | let _ = NONE;

View file

@ -4,7 +4,7 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`
LL | const NONE<T = ()>: Option<T> = None::<T>;
| ^^^^^^
error[E0282]: type annotations needed for `Option<T>`
error[E0282]: type annotations needed for `Option<_>`
--> $DIR/parameter-defaults.rs:13:9
|
LL | let _ = NONE;

View file

@ -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 <https://github.com/rust-lang/rust/pull/122954>.
//@ 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();
}

View file

@ -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)]
| ^^^^^^^^^^^^^^

View file

@ -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();
}

View file

@ -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 <https://github.com/rust-lang/rust/pull/122954>.
//@ 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() {}

View file

@ -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

View file

@ -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 <https://github.com/rust-lang/rust/pull/122954>.
#![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() {}

View file

@ -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

View file

@ -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 <https://github.com/rust-lang/rust/pull/122954>.
//@ 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() {}

View file

@ -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)
};

View file

@ -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| {

View file

@ -1,4 +1,4 @@
error[E0283]: type annotations needed for `Foo<i32, &str, W, Z>`
error[E0283]: type annotations needed for `Foo<i32, &str, _, _>`
--> $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<i32, &str, W, Z> = foo(1, "");
| ++++++++++++++++++++++
error[E0283]: type annotations needed for `Bar<i32, &str, Z>`
error[E0283]: type annotations needed for `Bar<i32, &str, _>`
--> $DIR/erase-type-params-in-label.rs:5:9
|
LL | let bar = bar(1, "");

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), E>, Error>>`
error[E0282]: type annotations needed for `A<std::result::Result<std::result::Result<(), _>, Error>>`
--> $DIR/issue-104649.rs:24:9
|
LL | let a = A(Result::Ok(Result::Ok(())));

View file

@ -50,7 +50,7 @@ help: try using a fully qualified path to specify the expected types
LL | |x| String::from(<str as AsRef<T>>::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();

View file

@ -6,5 +6,5 @@ fn foo<const N: usize>(_: impl std::fmt::Display) -> [usize; N] {
fn main() {
let _ = foo("foo");
//~^ ERROR: type annotations needed for `[usize; N]`
//~^ ERROR type annotations needed for `[usize; _]`
}

View file

@ -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");

View file

@ -6,15 +6,15 @@ LL | 1 +
|
= help: the trait `Add<()>` is not implemented for `{integer}`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f128 as Add<f128>>
<&'a f16 as Add<f16>>
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
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<Rhs>`:
<&'a f128 as Add<f128>>
<&'a f16 as Add<f16>>
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
and 48 others
and 56 others
error: aborting due to 2 previous errors

View file

@ -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();

View file

@ -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();

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `B<T>`
error[E0282]: type annotations needed for `B<_>`
--> $DIR/issue-17551.rs:6:9
|
LL | let foo = B(marker::PhantomData);

View file

@ -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| {

View file

@ -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<Rhs>`:
<&'a f128 as Add<f128>>
<&'a f16 as Add<f16>>
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
and 48 others
and 56 others
error: aborting due to 2 previous errors

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `SmallCString<N>`
error[E0282]: type annotations needed for `SmallCString<_>`
--> $DIR/issue-98299.rs:4:36
|
LL | SmallCString::try_from(p).map(|cstr| cstr);

View file

@ -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() {}

View file

@ -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

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `Vec<T>`
error[E0282]: type annotations needed for `Vec<_>`
--> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:9
|
LL | let mut x = Vec::new();

View file

@ -6,15 +6,15 @@ LL | 1 + Some(1);
|
= help: the trait `Add<Option<{integer}>>` is not implemented for `{integer}`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f128 as Add<f128>>
<&'a f16 as Add<f16>>
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
<&'a i128 as Add<i128>>
<&'a i16 as Add<i16>>
<&'a i32 as Add<i32>>
<&'a i64 as Add<i64>>
<&'a i8 as Add<i8>>
<&'a isize as Add<isize>>
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<Rhs>`:
<&'a f128 as Mul<f128>>
<&'a f16 as Mul<f16>>
<&'a f32 as Mul<f32>>
<&'a f64 as Mul<f64>>
<&'a i128 as Mul<i128>>
<&'a i16 as Mul<i16>>
<&'a i32 as Mul<i32>>
<&'a i64 as Mul<i64>>
<&'a i8 as Mul<i8>>
<&'a isize as Mul<isize>>
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<Rhs>`:
<&'a f128 as Div<f128>>
<&'a f16 as Div<f16>>
<&'a f32 as Div<f32>>
<&'a f64 as Div<f64>>
<&'a i128 as Div<i128>>
<&'a i16 as Div<i16>>
<&'a i32 as Div<i32>>
<&'a i64 as Div<i64>>
<&'a i8 as Div<i8>>
<&'a isize as Div<isize>>
and 54 others
and 62 others
error[E0277]: can't compare `{integer}` with `String`
--> $DIR/binops.rs:6:7

View file

@ -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

View file

@ -18,7 +18,7 @@ fn assert_impls_fn<R,T: Fn()->R>(_: &T){}
fn main() {
let n = None;
//~^ ERROR type annotations needed for `Option<T>`
//~^ ERROR type annotations needed for `Option<_>`
let e = S(&n);
let f = || {
// S being copy is critical for this to work

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `Option<T>`
error[E0282]: type annotations needed for `Option<_>`
--> $DIR/copy-guessing.rs:20:9
|
LL | let n = None;

View file

@ -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(<u32 as Into<T>>::into(0u32))).collect();
| +++++++++++++++++++++++ ~
error[E0283]: type annotations needed for `Box<T>`
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<T> = ().foo();
| ++++++++
error[E0283]: type annotations needed for `Box<T>`
error[E0283]: type annotations needed for `Box<_>`
--> $DIR/issue-77982.rs:41:9
|
LL | let _ = (&()).bar();

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `Result<Child, F>`
error[E0282]: type annotations needed for `Result<Child, _>`
--> $DIR/or_else-multiple-type-params.rs:7:18
|
LL | .or_else(|err| {

View file

@ -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<Iter<'_, char>, ...>`

View file

@ -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<Item = &char> {
| ++++++++++++++++++++++++++++++
error: aborting due to 1 previous error

View file

@ -1,4 +1,4 @@
error[E0282]: type annotations needed for `Option<T>`
error[E0282]: type annotations needed for `Option<_>`
--> $DIR/unboxed-closures-failed-recursive-fn-2.rs:8:9
|
LL | let mut closure0 = None;