diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index cd1f73d529818..eb906d5fde7b4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1921,17 +1921,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(assigned_span, format!("first assignment to {}", place_description)); } } - if let Some(decl) = local_decl { - if let Some(name) = local_name { - if decl.can_be_made_mutable() { - err.span_suggestion( - decl.source_info.span, - "consider making this binding mutable", - format!("mut {}", name), - Applicability::MachineApplicable, - ); - } - } + if let Some(decl) = local_decl + && let Some(name) = local_name + && decl.can_be_made_mutable() + { + err.span_suggestion( + decl.source_info.span, + "consider making this binding mutable", + format!("mut {}", name), + Applicability::MachineApplicable, + ); } err.span_label(span, msg); self.buffer_error(err); diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index da6610c002efc..2217c0e14b2aa 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -375,15 +375,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some(Cause::DropVar(local, location)) => { let mut should_note_order = false; - if self.local_names[local].is_some() { - if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place { - if let Some(borrowed_local) = place.as_local() { - if self.local_names[borrowed_local].is_some() && local != borrowed_local - { - should_note_order = true; - } - } - } + if self.local_names[local].is_some() + && let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place + && let Some(borrowed_local) = place.as_local() + && self.local_names[borrowed_local].is_some() && local != borrowed_local + { + should_note_order = true; } BorrowExplanation::UsedLaterWhenDropped { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 2c9bd8ea96e9a..610798c7c05c8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1086,21 +1086,17 @@ fn get_mut_span_in_struct_field<'tcx>( field: &mir::Field, ) -> Option { // Expect our local to be a reference to a struct of some kind. - if let ty::Ref(_, ty, _) = ty.kind() { - if let ty::Adt(def, _) = ty.kind() { - let field = def.all_fields().nth(field.index())?; - // Use the HIR types to construct the diagnostic message. - let node = tcx.hir().find_by_def_id(field.did.as_local()?)?; - // Now we're dealing with the actual struct that we're going to suggest a change to, - // we can expect a field that is an immutable reference to a type. - if let hir::Node::Field(field) = node { - if let hir::TyKind::Rptr(lifetime, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = - field.ty.kind - { - return Some(lifetime.span.between(ty.span)); - } - } - } + if let ty::Ref(_, ty, _) = ty.kind() + && let ty::Adt(def, _) = ty.kind() + && let field = def.all_fields().nth(field.index())? + // Use the HIR types to construct the diagnostic message. + && let node = tcx.hir().find_by_def_id(field.did.as_local()?)? + // Now we're dealing with the actual struct that we're going to suggest a change to, + // we can expect a field that is an immutable reference to a type. + && let hir::Node::Field(field) = node + && let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind + { + return Some(lt.span.between(ty.span)); } None diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 64f05f6004f53..369aef6798ba6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -140,14 +140,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// Returns `true` if a closure is inferred to be an `FnMut` closure. fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { - if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref() { - if let ty::BoundRegionKind::BrEnv = free_region.bound_region { - if let DefiningTy::Closure(_, substs) = - self.regioncx.universal_regions().defining_ty - { - return substs.as_closure().kind() == ty::ClosureKind::FnMut; - } - } + if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref() + && let ty::BoundRegionKind::BrEnv = free_region.bound_region + && let DefiningTy::Closure(_, substs) = self.regioncx.universal_regions().defining_ty + { + return substs.as_closure().kind() == ty::ClosureKind::FnMut; } false diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c489f409fb53b..82d2d0dd4557f 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1,15 +1,16 @@ //! This query borrow-checks the MIR to (further) ensure it is not broken. +#![allow(rustc::potential_query_instability)] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] #![feature(trusted_step)] #![feature(try_blocks)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate rustc_middle; @@ -159,16 +160,14 @@ fn do_mir_borrowck<'a, 'tcx>( for var_debug_info in &input_body.var_debug_info { if let VarDebugInfoContents::Place(place) = var_debug_info.value { if let Some(local) = place.as_local() { - if let Some(prev_name) = local_names[local] { - if var_debug_info.name != prev_name { - span_bug!( - var_debug_info.source_info.span, - "local {:?} has many names (`{}` vs `{}`)", - local, - prev_name, - var_debug_info.name - ); - } + if let Some(prev_name) = local_names[local] && var_debug_info.name != prev_name { + span_bug!( + var_debug_info.source_info.span, + "local {:?} has many names (`{}` vs `{}`)", + local, + prev_name, + var_debug_info.name + ); } local_names[local] = Some(var_debug_info.name); } diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 773e9e90b0c6b..5a935c3b8fbfd 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -60,10 +60,8 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( // This Local/Local case is handled by the more general code below, but // it's so common that it's a speed win to check for it first. - if let Some(l1) = borrow_place.as_local() { - if let Some(l2) = access_place.as_local() { - return l1 == l2; - } + if let Some(l1) = borrow_place.as_local() && let Some(l2) = access_place.as_local() { + return l1 == l2; } place_components_conflict(tcx, body, borrow_place, borrow_kind, access_place, access, bias) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 83b54810db2f2..046f4f9451f58 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -236,13 +236,9 @@ pub fn get_codegen_backend( static LOAD: SyncOnceCell Box> = SyncOnceCell::new(); let load = LOAD.get_or_init(|| { - #[cfg(feature = "llvm")] - const DEFAULT_CODEGEN_BACKEND: &str = "llvm"; + let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm"); - #[cfg(not(feature = "llvm"))] - const DEFAULT_CODEGEN_BACKEND: &str = "cranelift"; - - match backend_name.unwrap_or(DEFAULT_CODEGEN_BACKEND) { + match backend_name.unwrap_or(default_codegen_backend) { filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), #[cfg(feature = "llvm")] "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 0582a4e01bfeb..ad9a16fb39ae2 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -166,7 +166,12 @@ impl LintStore { self.early_passes.push(Box::new(pass)); } - /// Used by clippy. + /// This lint pass is softly deprecated. It misses expanded code and has caused a few + /// errors in the past. Currently, it is only used in Clippy. New implementations + /// should avoid using this interface, as it might be removed in the future. + /// + /// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838) + /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518) pub fn register_pre_expansion_pass( &mut self, pass: impl Fn() -> EarlyLintPassObject + 'static + sync::Send + sync::Sync, diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 72c0985a63c33..a94c2b9f5f7d4 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -17,7 +17,13 @@ crate fn lit_to_const<'tcx>( let param_ty = ParamEnv::reveal_all().and(ty); let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size; trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); - let result = width.truncate(n); + let result = match &ty.kind() { + ty::Uint(_) => { + let max_value = width.unsigned_int_max(); + if n >= max_value { max_value } else { width.truncate(n) } + } + _ => width.truncate(n), + }; trace!("trunc result: {}", result); Ok(ConstValue::Scalar(Scalar::from_uint(result, width))) }; diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 4a310e2be3e3c..14a6e686a6424 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1054,12 +1054,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut result = Vec::new(); for ast_bound in ast_bounds { - if let Some(trait_ref) = ast_bound.trait_ref() { - if let Some(trait_did) = trait_ref.trait_def_id() { - if self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) { - result.push(ast_bound.clone()); - } - } + if let Some(trait_ref) = ast_bound.trait_ref() + && let Some(trait_did) = trait_ref.trait_def_id() + && self.tcx().trait_may_define_assoc_type(trait_did, assoc_name) + { + result.push(ast_bound.clone()); } } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 8ed87497f1b32..100d2d07a5c9f 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -282,13 +282,12 @@ pub(super) fn check_fn<'a, 'tcx>( sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`"); } - if let Node::Item(item) = hir.get(fn_id) { - if let ItemKind::Fn(_, ref generics, _) = item.kind { - if !generics.params.is_empty() { + if let Node::Item(item) = hir.get(fn_id) + && let ItemKind::Fn(_, ref generics, _) = item.kind + && !generics.params.is_empty() + { sess.span_err(span, "should have no type parameters"); } - } - } } else { let span = sess.source_map().guess_head_span(span); sess.span_err(span, "function should have one argument"); @@ -319,17 +318,15 @@ pub(super) fn check_fn<'a, 'tcx>( sess.span_err(decl.inputs[0].span, "argument should be `Layout`"); } - if let Node::Item(item) = hir.get(fn_id) { - if let ItemKind::Fn(_, ref generics, _) = item.kind { - if !generics.params.is_empty() { + if let Node::Item(item) = hir.get(fn_id) + && let ItemKind::Fn(_, ref generics, _) = item.kind + && !generics.params.is_empty() + { sess.span_err( span, - "`#[alloc_error_handler]` function should have no type \ - parameters", + "`#[alloc_error_handler]` function should have no type parameters", ); } - } - } } else { let span = sess.source_map().guess_head_span(span); sess.span_err(span, "function should have one argument"); @@ -1146,9 +1143,10 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) { if repr.packed() { for attr in tcx.get_attrs(def.did).iter() { for r in attr::find_repr_attrs(&tcx.sess, attr) { - if let attr::ReprPacked(pack) = r { - if let Some(repr_pack) = repr.pack { - if pack as u64 != repr_pack.bytes() { + if let attr::ReprPacked(pack) = r + && let Some(repr_pack) = repr.pack + && pack as u64 != repr_pack.bytes() + { struct_span_err!( tcx.sess, sp, @@ -1156,8 +1154,6 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: &ty::AdtDef) { "type has conflicting packed representation hints" ) .emit(); - } - } } } } @@ -1399,12 +1395,11 @@ fn display_discriminant_value<'tcx>( ) -> String { if let Some(expr) = &variant.disr_expr { let body = &tcx.hir().body(expr.body).value; - if let hir::ExprKind::Lit(lit) = &body.kind { - if let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node { - if evaluated != *lit_value { + if let hir::ExprKind::Lit(lit) = &body.kind + && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node + && evaluated != *lit_value + { return format!("`{}` (overflowed from `{}`)", evaluated, lit_value); - } - } } } format!("`{}`", evaluated) diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 8ca27b010b6af..c6b14d3e10458 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -1696,13 +1696,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { } fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { - if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) { - if let hir::FnRetTy::Return(ty) = fn_decl.output { - let ty = >::ast_ty_to_ty(fcx, ty); - if let ty::Dynamic(..) = ty.kind() { + if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) + && let hir::FnRetTy::Return(ty) = fn_decl.output + && let ty = >::ast_ty_to_ty(fcx, ty) + && let ty::Dynamic(..) = ty.kind() + { return true; - } - } } false } diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 80096b90f9530..faead1bf5cd6d 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -587,9 +587,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match (&expr.kind, expected.kind(), checked_ty.kind()) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (exp.kind(), check.kind()) { (&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => { - if let hir::ExprKind::Lit(_) = expr.kind { - if let Ok(src) = sm.span_to_snippet(sp) { - if replace_prefix(&src, "b\"", "\"").is_some() { + if let hir::ExprKind::Lit(_) = expr.kind + && let Ok(src) = sm.span_to_snippet(sp) + && replace_prefix(&src, "b\"", "\"").is_some() + { let pos = sp.lo() + BytePos(1); return Some(( sp.with_hi(pos), @@ -600,12 +601,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } } - } - } (&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => { - if let hir::ExprKind::Lit(_) = expr.kind { - if let Ok(src) = sm.span_to_snippet(sp) { - if replace_prefix(&src, "\"", "b\"").is_some() { + if let hir::ExprKind::Lit(_) = expr.kind + && let Ok(src) = sm.span_to_snippet(sp) + && replace_prefix(&src, "\"", "b\"").is_some() + { return Some(( sp.shrink_to_lo(), "consider adding a leading `b`", @@ -613,8 +613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, true, )); - } - } + } } _ => {} diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 8d4ffefda73bb..14a1318517a19 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -810,10 +810,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Use the span of the trailing expression for our cause, // not the span of the entire function if !explicit_return { - if let ExprKind::Block(body, _) = return_expr.kind { - if let Some(last_expr) = body.expr { - span = last_expr.span; - } + if let ExprKind::Block(body, _) = return_expr.kind && let Some(last_expr) = body.expr { + span = last_expr.span; } } ret_coercion.borrow_mut().coerce( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 4b6460b62b77a..76339998a2fbb 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -402,25 +402,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if arg_count == 0 || i + 1 == arg_count { &label } else { "" }, ); } - if let Some(def_id) = fn_def_id { - if let Some(def_span) = tcx.def_ident_span(def_id) { - let mut spans: MultiSpan = def_span.into(); - - let params = tcx - .hir() - .get_if_local(def_id) - .and_then(|node| node.body_id()) - .into_iter() - .map(|id| tcx.hir().body(id).params) - .flatten(); - - for param in params { - spans.push_span_label(param.span, String::new()); - } - - let def_kind = tcx.def_kind(def_id); - err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id))); + if let Some(def_id) = fn_def_id && let Some(def_span) = tcx.def_ident_span(def_id) { + let mut spans: MultiSpan = def_span.into(); + + let params = tcx + .hir() + .get_if_local(def_id) + .and_then(|node| node.body_id()) + .into_iter() + .map(|id| tcx.hir().body(id).params) + .flatten(); + + for param in params { + spans.push_span_label(param.span, String::new()); } + + let def_kind = tcx.def_kind(def_id); + err.span_note(spans, &format!("{} defined here", def_kind.descr(def_id))); } if sugg_unit { let sugg_span = tcx.sess.source_map().end_point(call_expr.span); diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index ccaea10233dc1..32de5d23c1ea7 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -430,12 +430,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { actual.prefix_string(self.tcx), ty_str_reported, ); - if let Mode::MethodCall = mode { - if let SelfSource::MethodCall(call) = source { - self.suggest_await_before_method( - &mut err, item_name, actual, call, span, - ); - } + if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source { + self.suggest_await_before_method( + &mut err, item_name, actual, cal, span, + ); } if let Some(span) = tcx.resolutions(()).confused_type_with_std_module.get(&span) @@ -1525,43 +1523,41 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Arc), "Arc::new"), (self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"), ] { - if let Some(new_rcvr_t) = *rcvr_ty { - if let Ok(pick) = self.lookup_probe( - span, - item_name, - new_rcvr_t, - rcvr, - crate::check::method::probe::ProbeScope::AllTraits, - ) { - debug!("try_alt_rcvr: pick candidate {:?}", pick); - let did = Some(pick.item.container.id()); - // We don't want to suggest a container type when the missing - // method is `.clone()` or `.deref()` otherwise we'd suggest - // `Arc::new(foo).clone()`, which is far from what the user wants. - // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not - // implement the `AsRef` trait. - let skip = skippable.contains(&did) - || (("Pin::new" == *pre) && (sym::as_ref == item_name.name)); - // Make sure the method is defined for the *actual* receiver: we don't - // want to treat `Box` as a receiver if it only works because of - // an autoderef to `&self` - if pick.autoderefs == 0 && !skip { - err.span_label( - pick.item.ident(self.tcx).span, - &format!("the method is available for `{}` here", new_rcvr_t), - ); - err.multipart_suggestion( - "consider wrapping the receiver expression with the \ - appropriate type", - vec![ - (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)), - (rcvr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MaybeIncorrect, - ); - // We don't care about the other suggestions. - alt_rcvr_sugg = true; - } + if let Some(new_rcvr_t) = *rcvr_ty && let Ok(pick) = self.lookup_probe( + span, + item_name, + new_rcvr_t, + rcvr, + crate::check::method::probe::ProbeScope::AllTraits, + ) { + debug!("try_alt_rcvr: pick candidate {:?}", pick); + let did = Some(pick.item.container.id()); + // We don't want to suggest a container type when the missing + // method is `.clone()` or `.deref()` otherwise we'd suggest + // `Arc::new(foo).clone()`, which is far from what the user wants. + // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not + // implement the `AsRef` trait. + let skip = skippable.contains(&did) + || (("Pin::new" == *pre) && (sym::as_ref == item_name.name)); + // Make sure the method is defined for the *actual* receiver: we don't + // want to treat `Box` as a receiver if it only works because of + // an autoderef to `&self` + if pick.autoderefs == 0 && !skip { + err.span_label( + pick.item.ident(self.tcx).span, + &format!("the method is available for `{}` here", new_rcvr_t), + ); + err.multipart_suggestion( + "consider wrapping the receiver expression with the \ + appropriate type", + vec![ + (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)), + (rcvr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MaybeIncorrect, + ); + // We don't care about the other suggestions. + alt_rcvr_sugg = true; } } } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 7c6917734b2ae..9963a922268a4 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -685,9 +685,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn check_dereferenceable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat<'_>) -> bool { - if let PatKind::Binding(..) = inner.kind { - if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { - if let ty::Dynamic(..) = mt.ty.kind() { + if let PatKind::Binding(..) = inner.kind + && let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) + && let ty::Dynamic(..) = mt.ty.kind() + { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. let type_str = self.ty_to_string(expected); @@ -705,8 +706,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); return false; } - } - } true } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 2317ae43f1143..88e3e67c99ee3 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -190,25 +190,23 @@ crate fn placeholder_type_error<'tcx>( let mut is_fn = false; let mut is_const_or_static = false; - if let Some(hir_ty) = hir_ty { - if let hir::TyKind::BareFn(_) = hir_ty.kind { - is_fn = true; - - // Check if parent is const or static - let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); - let parent_node = tcx.hir().get(parent_id); - - is_const_or_static = matches!( - parent_node, - Node::Item(&hir::Item { - kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), - .. - }) | Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Const(..), - .. - }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) - ); - } + if let Some(hir_ty) = hir_ty && let hir::TyKind::BareFn(_) = hir_ty.kind { + is_fn = true; + + // Check if parent is const or static + let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); + let parent_node = tcx.hir().get(parent_id); + + is_const_or_static = matches!( + parent_node, + Node::Item(&hir::Item { + kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), + .. + }) | Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Const(..), + .. + }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + ); } // if function is wrapped around a const or static, @@ -2417,16 +2415,14 @@ fn const_evaluatable_predicates_of<'tcx>( let node = tcx.hir().get(hir_id); let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; - if let hir::Node::Item(item) = node { - if let hir::ItemKind::Impl(ref impl_) = item.kind { - if let Some(of_trait) = &impl_.of_trait { - debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); - collector.visit_trait_ref(of_trait); - } - - debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); - collector.visit_ty(impl_.self_ty); + if let hir::Node::Item(item) = node && let hir::ItemKind::Impl(ref impl_) = item.kind { + if let Some(of_trait) = &impl_.of_trait { + debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); + collector.visit_trait_ref(of_trait); } + + debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); + collector.visit_ty(impl_.self_ty); } if let Some(generics) = node.generics() { @@ -3280,15 +3276,14 @@ fn asm_target_features<'tcx>(tcx: TyCtxt<'tcx>, id: DefId) -> &'tcx FxHashSet, def_id: DefId) -> bool { - if let Some(impl_item) = tcx.opt_associated_item(def_id) { - if let ty::AssocItemContainer::ImplContainer(_) = impl_item.container { - if let Some(trait_item) = impl_item.trait_item_def_id { - return tcx - .codegen_fn_attrs(trait_item) - .flags - .intersects(CodegenFnAttrFlags::TRACK_CALLER); - } - } + if let Some(impl_item) = tcx.opt_associated_item(def_id) + && let ty::AssocItemContainer::ImplContainer(_) = impl_item.container + && let Some(trait_item) = impl_item.trait_item_def_id + { + return tcx + .codegen_fn_attrs(trait_item) + .flags + .intersects(CodegenFnAttrFlags::TRACK_CALLER); } false diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index f0289fd505a47..de030c5b60bcc 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -55,22 +55,23 @@ This API is completely unstable and subject to change. */ +#![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] +#![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] +#![feature(hash_drain_filter)] #![feature(if_let_guard)] #![feature(is_sorted)] +#![feature(let_chains)] #![feature(let_else)] #![feature(min_specialization)] -#![feature(nll)] -#![feature(try_blocks)] #![feature(never_type)] -#![feature(slice_partition_dedup)] -#![feature(control_flow_enum)] -#![feature(hash_drain_filter)] +#![feature(nll)] #![feature(once_cell)] +#![feature(slice_partition_dedup)] +#![feature(try_blocks)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_typeck/src/outlives/implicit_infer.rs index 89f0bd8d42154..61ca09f6b982c 100644 --- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs +++ b/compiler/rustc_typeck/src/outlives/implicit_infer.rs @@ -304,13 +304,12 @@ pub fn check_explicit_predicates<'tcx>( // = X` binding from the object type (there must be such a // binding) and thus infer an outlives requirement that `X: // 'b`. - if let Some(self_ty) = ignored_self_ty { - if let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() { - if ty.walk().any(|arg| arg == self_ty.into()) { - debug!("skipping self ty = {:?}", &ty); - continue; - } - } + if let Some(self_ty) = ignored_self_ty + && let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() + && ty.walk().any(|arg| arg == self_ty.into()) + { + debug!("skipping self ty = {:?}", &ty); + continue; } let predicate = outlives_predicate.subst(tcx, substs); diff --git a/config.toml.example b/config.toml.example index ad48cc881f3e6..466a3a29c4c78 100644 --- a/config.toml.example +++ b/config.toml.example @@ -551,7 +551,9 @@ changelog-seen = 2 # This is an array of the codegen backends that will be compiled for the rustc # that's being compiled. The default is to only build the LLVM codegen backend, -# and currently the only standard options supported are `"llvm"` and `"cranelift"`. +# and currently the only standard options supported are `"llvm"`, `"cranelift"` +# and `"gcc"`. The first backend in this list will be used as default by rustc +# when no explicit backend is specified. #codegen-backends = ["llvm"] # Indicates whether LLD will be compiled and made available in the sysroot for diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index b5c1ae37e5e89..8a99bed6a96ab 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -708,7 +708,10 @@ pub const fn swap(x: &mut T, y: &mut T) { // understanding `mem::replace`, `Option::take`, etc. - a better overall // solution might be to make `ptr::swap_nonoverlapping` into an intrinsic, which // a backend can choose to implement using the block optimization, or not. - #[cfg(not(target_arch = "spirv"))] + // NOTE(scottmcm) MIRI is disabled here as reading in smaller units is a + // pessimization for it. Also, if the type contains any unaligned pointers, + // copying those over multiple reads is difficult to support. + #[cfg(not(any(target_arch = "spirv", miri)))] { // For types that are larger multiples of their alignment, the simple way // tends to copy the whole thing to stack rather than doing it one part @@ -737,12 +740,26 @@ pub const fn swap(x: &mut T, y: &mut T) { #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[inline] pub(crate) const fn swap_simple(x: &mut T, y: &mut T) { + // We arrange for this to typically be called with small types, + // so this reads-and-writes approach is actually better than using + // copy_nonoverlapping as it easily puts things in LLVM registers + // directly and doesn't end up inlining allocas. + // And LLVM actually optimizes it to 3×memcpy if called with + // a type larger than it's willing to keep in a register. + // Having typed reads and writes in MIR here is also good as + // it lets MIRI and CTFE understand them better, including things + // like enforcing type validity for them. + // Importantly, read+copy_nonoverlapping+write introduces confusing + // asymmetry to the behaviour where one value went through read+write + // whereas the other was copied over by the intrinsic (see #94371). + // SAFETY: exclusive references are always valid to read/write, - // are non-overlapping, and nothing here panics so it's drop-safe. + // including being aligned, and nothing here panics so it's drop-safe. unsafe { - let z = ptr::read(x); - ptr::copy_nonoverlapping(y, x, 1); - ptr::write(y, z); + let a = ptr::read(x); + let b = ptr::read(y); + ptr::write(x, b); + ptr::write(y, a); } } diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index ff71fadb61418..59b1b4c136752 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -419,6 +419,7 @@ pub const unsafe fn swap(x: *mut T, y: *mut T) { #[stable(feature = "swap_nonoverlapping", since = "1.27.0")] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { + #[allow(unused)] macro_rules! attempt_swap_as_chunks { ($ChunkTy:ty) => { if mem::align_of::() >= mem::align_of::<$ChunkTy>() @@ -437,15 +438,21 @@ pub const unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { }; } - // Split up the slice into small power-of-two-sized chunks that LLVM is able - // to vectorize (unless it's a special type with more-than-pointer alignment, - // because we don't want to pessimize things like slices of SIMD vectors.) - if mem::align_of::() <= mem::size_of::() - && (!mem::size_of::().is_power_of_two() - || mem::size_of::() > mem::size_of::() * 2) + // NOTE(scottmcm) MIRI is disabled here as reading in smaller units is a + // pessimization for it. Also, if the type contains any unaligned pointers, + // copying those over multiple reads is difficult to support. + #[cfg(not(miri))] { - attempt_swap_as_chunks!(usize); - attempt_swap_as_chunks!(u8); + // Split up the slice into small power-of-two-sized chunks that LLVM is able + // to vectorize (unless it's a special type with more-than-pointer alignment, + // because we don't want to pessimize things like slices of SIMD vectors.) + if mem::align_of::() <= mem::size_of::() + && (!mem::size_of::().is_power_of_two() + || mem::size_of::() > mem::size_of::() * 2) + { + attempt_swap_as_chunks!(usize); + attempt_swap_as_chunks!(u8); + } } // SAFETY: Same preconditions as this function diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index cc4e4fd4fdc77..74f03ecaa2ff8 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -707,10 +707,48 @@ impl fmt::Debug for TcpStream { } impl TcpListener { + /// Default listen backlog. + const DEFAULT_BACKLOG: usize = 128; + /// Creates a new `TcpListener` which will be bound to the specified /// address. /// - /// The returned listener is ready for accepting connections. + /// The given backlog specifies the maximum number of outstanding + /// connections that will be buffered in the OS waiting to be accepted by + /// [`TcpListener::accept`]. The backlog argument overrides the default + /// value of 128; that default is reasonable for most use cases. + /// + /// This function is otherwise [`TcpListener::bind`]: see that + /// documentation for full details of operation. + /// + /// # Examples + /// + /// Creates a TCP listener bound to `127.0.0.1:80` with a backlog of 1000: + /// + /// ```no_run + /// #![feature(bind_with_backlog)] + /// use std::net::TcpListener; + /// + /// let listener = TcpListener::bind_with_backlog("127.0.0.1:80", 1000).unwrap(); + /// ``` + /// + /// # Errors + /// + /// The specified backlog may be larger than supported by the underlying + /// system. In this case an [`io::Error`] with + /// [`io::ErrorKind::InvalidData`] will be returned. + #[unstable(feature = "bind_with_backlog", issue = "94406")] + pub fn bind_with_backlog(addr: A, backlog: usize) -> io::Result { + super::each_addr(addr, move |a| net_imp::TcpListener::bind_with_backlog(a, backlog)) + .map(TcpListener) + } + + /// Creates a new `TcpListener` which will be bound to the specified + /// address. The returned listener is ready for accepting + /// connections. + /// + /// The listener will have a backlog of 128. See the documentation for + /// [`TcpListener::bind_with_backlog`] for further information. /// /// Binding with a port number of 0 will request that the OS assigns a port /// to this listener. The port allocated can be queried via the @@ -748,7 +786,7 @@ impl TcpListener { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn bind(addr: A) -> io::Result { - super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener) + Self::bind_with_backlog(addr, TcpListener::DEFAULT_BACKLOG) } /// Returns the local socket address of this listener. diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs index c2061c1351262..8ead0e31270fe 100644 --- a/library/std/src/net/tcp/tests.rs +++ b/library/std/src/net/tcp/tests.rs @@ -48,7 +48,7 @@ fn connect_error() { #[test] fn listen_localhost() { let socket_addr = next_test_ip4(); - let listener = t!(TcpListener::bind(&socket_addr)); + let listener = t!(TcpListener::bind_with_backlog(&socket_addr, 1)); let _t = thread::spawn(move || { let mut stream = t!(TcpStream::connect(&("localhost", socket_addr.port()))); @@ -64,7 +64,7 @@ fn listen_localhost() { #[test] fn connect_loopback() { each_ip(&mut |addr| { - let acceptor = t!(TcpListener::bind(&addr)); + let acceptor = t!(TcpListener::bind_with_backlog(&addr, 1)); let _t = thread::spawn(move || { let host = match addr { @@ -85,7 +85,7 @@ fn connect_loopback() { #[test] fn smoke_test() { each_ip(&mut |addr| { - let acceptor = t!(TcpListener::bind(&addr)); + let acceptor = t!(TcpListener::bind_with_backlog(&addr, 1)); let (tx, rx) = channel(); let _t = thread::spawn(move || { @@ -172,11 +172,33 @@ fn multiple_connect_serial() { }) } +#[test] +fn multiple_connect_serial_with_backlog() { + each_ip(&mut |addr| { + let max = 10; + let acceptor = t!(TcpListener::bind_with_backlog(&addr, max)); + + let _t = thread::spawn(move || { + for _ in 0..max { + let mut stream = t!(TcpStream::connect(&addr)); + t!(stream.write(&[99])); + } + }); + + for stream in acceptor.incoming().take(max) { + let mut stream = t!(stream); + let mut buf = [0]; + t!(stream.read(&mut buf)); + assert_eq!(buf[0], 99); + } + }) +} + #[test] fn multiple_connect_interleaved_greedy_schedule() { const MAX: usize = 10; each_ip(&mut |addr| { - let acceptor = t!(TcpListener::bind(&addr)); + let acceptor = t!(TcpListener::bind_with_backlog(&addr, MAX)); let _t = thread::spawn(move || { let acceptor = acceptor; @@ -213,7 +235,7 @@ fn multiple_connect_interleaved_greedy_schedule() { fn multiple_connect_interleaved_lazy_schedule() { const MAX: usize = 10; each_ip(&mut |addr| { - let acceptor = t!(TcpListener::bind(&addr)); + let acceptor = t!(TcpListener::bind_with_backlog(&addr, MAX)); let _t = thread::spawn(move || { for stream in acceptor.incoming().take(MAX) { diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index b23dd6062f682..71bea61fbe825 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -5,6 +5,7 @@ use crate::sys::cvt; use crate::sys::net::Socket; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fmt, io, mem}; +use core::convert::TryInto; /// A structure representing a Unix domain socket server. /// @@ -53,8 +54,14 @@ impl fmt::Debug for UnixListener { } impl UnixListener { + /// Default backlog for `bind` and `bind_addr`. + const DEFAULT_BACKLOG: usize = 128; + /// Creates a new `UnixListener` bound to the specified socket. /// + /// The listener will have a backlog of 128. See the documentation for + /// [`UnixListener::bind_with_backlog`] for further information. + /// /// # Examples /// /// ```no_run @@ -70,12 +77,51 @@ impl UnixListener { /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] pub fn bind>(path: P) -> io::Result { + UnixListener::bind_with_backlog(path, UnixListener::DEFAULT_BACKLOG) + } + + /// Creates a new `UnixListener` bound to the specified socket. + /// + /// The given backlog specifies the maximum number of outstanding + /// connections that will be buffered in the OS waiting to be accepted + /// by [`UnixListener::accept`]. The backlog argument overrides the + /// default backlog of 128; that default is reasonable for most use + /// cases. + /// + /// This function is otherwise [`UnixListener::bind`]: see that + /// documentation for full details of operation. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(bind_with_backlog)] + /// use std::os::unix::net::UnixListener; + /// + /// let listener = match UnixListener::bind_with_backlog("/path/to/the/socket", 1000) { + /// Ok(sock) => sock, + /// Err(e) => { + /// println!("Couldn't connect: {:?}", e); + /// return + /// } + /// }; + /// ``` + /// + /// # Errors + /// + /// The specified backlog may be larger than supported by the underlying + /// system. In this case an [`io::Error`] with + /// [`io::ErrorKind::InvalidData`] will be returned. + #[unstable(feature = "bind_with_backlog", issue = "94406")] + pub fn bind_with_backlog>(path: P, backlog: usize) -> io::Result { unsafe { + let backlog = backlog + .try_into() + .map_err(|e| crate::io::Error::new(crate::io::ErrorKind::InvalidData, e))?; let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; let (addr, len) = sockaddr_un(path.as_ref())?; cvt(libc::bind(inner.as_inner().as_raw_fd(), &addr as *const _ as *const _, len as _))?; - cvt(libc::listen(inner.as_inner().as_raw_fd(), 128))?; + cvt(libc::listen(inner.as_inner().as_raw_fd(), backlog))?; Ok(UnixListener(inner)) } @@ -83,6 +129,9 @@ impl UnixListener { /// Creates a new `UnixListener` bound to the specified [`socket address`]. /// + /// The listener will have a backlog of 128. See the documentation for + /// [`UnixListener::bind_addr_with_backlog`] for further information. + /// /// [`socket address`]: crate::os::unix::net::SocketAddr /// /// # Examples @@ -107,14 +156,59 @@ impl UnixListener { /// ``` #[unstable(feature = "unix_socket_abstract", issue = "85410")] pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result { + UnixListener::bind_addr_with_backlog(socket_addr, UnixListener::DEFAULT_BACKLOG) + } + + /// Creates a new `UnixListener` bound to the specified [`socket address`]. + /// + /// The given backlog specifies the maximum number of outstanding + /// connections that will be buffered in the OS waiting to be accepted + /// by [`UnixListener::accept`]. The backlog argument overrides the + /// default of 128; that default is reasonable for most use cases. + /// + /// This function is otherwise [`UnixListener::bind_addr`]: see that + /// documentation for full details of operation. + /// + /// [`socket address`]: crate::os::unix::net::SocketAddr + /// + /// # Examples + /// + /// ```no_run + /// #![feature(unix_socket_abstract)] + /// #![feature(bind_with_backlog)] + /// use std::os::unix::net::{UnixListener}; + /// + /// fn main() -> std::io::Result<()> { + /// let listener1 = UnixListener::bind("path/to/socket")?; + /// let addr = listener1.local_addr()?; + /// + /// let listener2 = match UnixListener::bind_addr_with_backlog(&addr, 1000) { + /// Ok(sock) => sock, + /// Err(err) => { + /// println!("Couldn't bind: {:?}", err); + /// return Err(err); + /// } + /// }; + /// Ok(()) + /// } + /// ``` + //#[unstable(feature = "unix_socket_abstract", issue = "85410")] + #[unstable(feature = "bind_with_backlog", issue = "94406")] + pub fn bind_addr_with_backlog( + socket_addr: &SocketAddr, + backlog: usize, + ) -> io::Result { unsafe { + let backlog = backlog + .try_into() + .map_err(|e| crate::io::Error::new(crate::io::ErrorKind::InvalidData, e))?; let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?; cvt(libc::bind( inner.as_raw_fd(), &socket_addr.addr as *const _ as *const _, socket_addr.len as _, ))?; - cvt(libc::listen(inner.as_raw_fd(), 128))?; + cvt(libc::listen(inner.as_raw_fd(), backlog))?; Ok(UnixListener(inner)) } } diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 7ad4a02611e07..b06cc4abc116c 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -41,7 +41,7 @@ fn basic() { let msg1 = b"hello"; let msg2 = b"world!"; - let listener = or_panic!(UnixListener::bind(&socket_path)); + let listener = or_panic!(UnixListener::bind_with_backlog(&socket_path, 1)); let thread = thread::spawn(move || { let mut stream = or_panic!(listener.accept()).0; let mut buf = [0; 5]; @@ -111,7 +111,7 @@ fn try_clone() { let msg1 = b"hello"; let msg2 = b"world"; - let listener = or_panic!(UnixListener::bind(&socket_path)); + let listener = or_panic!(UnixListener::bind_with_backlog(&socket_path, 1)); let thread = thread::spawn(move || { let mut stream = or_panic!(listener.accept()).0; or_panic!(stream.write_all(msg1)); @@ -135,7 +135,7 @@ fn iter() { let dir = tmpdir(); let socket_path = dir.path().join("sock"); - let listener = or_panic!(UnixListener::bind(&socket_path)); + let listener = or_panic!(UnixListener::bind_with_backlog(&socket_path, 2)); let thread = thread::spawn(move || { for stream in listener.incoming().take(2) { let mut stream = or_panic!(stream); @@ -423,7 +423,7 @@ fn test_abstract_stream_connect() { let msg2 = b"world"; let socket_addr = or_panic!(SocketAddr::from_abstract_namespace(b"namespace")); - let listener = or_panic!(UnixListener::bind_addr(&socket_addr)); + let listener = or_panic!(UnixListener::bind_addr_with_backlog(&socket_addr, 1)); let thread = thread::spawn(move || { let mut stream = or_panic!(listener.accept()).0; @@ -451,7 +451,7 @@ fn test_abstract_stream_connect() { #[test] fn test_abstract_stream_iter() { let addr = or_panic!(SocketAddr::from_abstract_namespace(b"hidden")); - let listener = or_panic!(UnixListener::bind_addr(&addr)); + let listener = or_panic!(UnixListener::bind_addr_with_backlog(&addr, 2)); let thread = thread::spawn(move || { for stream in listener.incoming().take(2) { diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 70b29d4a92ed5..8eaa15af5fb3e 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -363,9 +363,17 @@ pub struct TcpListener { } impl TcpListener { - pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result { + pub fn bind_with_backlog( + addr: io::Result<&SocketAddr>, + backlog: usize, + ) -> io::Result { let addr = addr?; + // Type-convert the backlog + let backlog = backlog + .try_into() + .map_err(|e| crate::io::Error::new(crate::io::ErrorKind::InvalidData, e))?; + init(); let sock = Socket::new(addr, c::SOCK_STREAM)?; @@ -385,7 +393,7 @@ impl TcpListener { cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?; // Start listening - cvt(unsafe { c::listen(sock.as_raw(), 128) })?; + cvt(unsafe { c::listen(sock.as_raw(), backlog) })?; Ok(TcpListener { inner: sock }) } diff --git a/src/bootstrap/build.rs b/src/bootstrap/build.rs index 6e39ea00f808c..8a5bf933d56ec 100644 --- a/src/bootstrap/build.rs +++ b/src/bootstrap/build.rs @@ -4,13 +4,13 @@ use std::path::PathBuf; fn main() { println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-env-changed=RUSTC"); - println!("cargo:rerun-if-env-changed=PATH"); println!("cargo:rustc-env=BUILD_TRIPLE={}", env::var("HOST").unwrap()); // This may not be a canonicalized path. let mut rustc = PathBuf::from(env::var_os("RUSTC").unwrap()); if rustc.is_relative() { + println!("cargo:rerun-if-env-changed=PATH"); for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) { let absolute = dir.join(&rustc); if absolute.exists() { diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index b2805d93b70fc..b4c6210b38814 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -662,6 +662,10 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("CFG_VERSION", builder.rust_version()); + if let Some(backend) = builder.config.rust_codegen_backends.get(0) { + cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend); + } + let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib")); let target_config = builder.config.target_config.get(&target); diff --git a/src/test/codegen/swap-large-types.rs b/src/test/codegen/swap-large-types.rs index 535d301a3d27b..91a1ab7144fd4 100644 --- a/src/test/codegen/swap-large-types.rs +++ b/src/test/codegen/swap-large-types.rs @@ -39,6 +39,9 @@ pub fn swap_std(x: &mut KeccakBuffer, y: &mut KeccakBuffer) { swap(x, y) } +// Verify that types with usize alignment are swapped via vectored usizes, +// not falling back to byte-level code. + // CHECK-LABEL: @swap_slice #[no_mangle] pub fn swap_slice(x: &mut [KeccakBuffer], y: &mut [KeccakBuffer]) { @@ -50,6 +53,8 @@ pub fn swap_slice(x: &mut [KeccakBuffer], y: &mut [KeccakBuffer]) { } } +// But for a large align-1 type, vectorized byte copying is what we want. + type OneKilobyteBuffer = [u8; 1024]; // CHECK-LABEL: @swap_1kb_slices @@ -62,3 +67,25 @@ pub fn swap_1kb_slices(x: &mut [OneKilobyteBuffer], y: &mut [OneKilobyteBuffer]) x.swap_with_slice(y); } } + +// This verifies that the 2×read + 2×write optimizes to just 3 memcpys +// for an unusual type like this. It's not clear whether we should do anything +// smarter in Rust for these, so for now it's fine to leave these up to the backend. +// That's not as bad as it might seem, as for example, LLVM will lower the +// memcpys below to VMOVAPS on YMMs if one enables the AVX target feature. +// Eventually we'll be able to pass `align_of::` to a const generic and +// thus pick a smarter chunk size ourselves without huge code duplication. + +#[repr(align(64))] +pub struct BigButHighlyAligned([u8; 64 * 3]); + +// CHECK-LABEL: @swap_big_aligned +#[no_mangle] +pub fn swap_big_aligned(x: &mut BigButHighlyAligned, y: &mut BigButHighlyAligned) { +// CHECK-NOT: call void @llvm.memcpy +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 64 dereferenceable(192) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 64 dereferenceable(192) +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 64 dereferenceable(192) +// CHECK-NOT: call void @llvm.memcpy + swap(x, y) +} diff --git a/src/test/rustdoc-ui/issue-79465.rs b/src/test/rustdoc-ui/issue-79465.rs new file mode 100644 index 0000000000000..f1a77982fb523 --- /dev/null +++ b/src/test/rustdoc-ui/issue-79465.rs @@ -0,0 +1,3 @@ +pub fn f1(x: T::A) {} +//~^ ERROR +//~^^ ERROR diff --git a/src/test/rustdoc-ui/issue-79465.stderr b/src/test/rustdoc-ui/issue-79465.stderr new file mode 100644 index 0000000000000..489cc14420a4c --- /dev/null +++ b/src/test/rustdoc-ui/issue-79465.stderr @@ -0,0 +1,15 @@ +error[E0220]: associated type `A` not found for `T` + --> $DIR/issue-79465.rs:1:20 + | +LL | pub fn f1(x: T::A) {} + | ^ associated type `A` not found + +error[E0220]: associated type `A` not found for `T` + --> $DIR/issue-79465.rs:1:20 + | +LL | pub fn f1(x: T::A) {} + | ^ associated type `A` not found + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0220`. diff --git a/src/test/ui/error-codes/E0081.rs b/src/test/ui/error-codes/E0081.rs index 255e05ced19f7..6f15b9d2ef95c 100644 --- a/src/test/ui/error-codes/E0081.rs +++ b/src/test/ui/error-codes/E0081.rs @@ -10,10 +10,10 @@ enum Enum { #[repr(u8)] enum EnumOverflowRepr { P = 257, - //~^ NOTE first use of `1` (overflowed from `257`) + //~^ NOTE first use of `255` (overflowed from `257`) X = 513, - //~^ ERROR discriminant value `1` already exists - //~| NOTE enum already has `1` (overflowed from `513`) + //~^ ERROR discriminant value `255` already exists + //~| NOTE enum already has `255` (overflowed from `513`) } fn main() { diff --git a/src/test/ui/error-codes/E0081.stderr b/src/test/ui/error-codes/E0081.stderr index 9b279bb0214c6..68bb0f407b82f 100644 --- a/src/test/ui/error-codes/E0081.stderr +++ b/src/test/ui/error-codes/E0081.stderr @@ -7,14 +7,14 @@ LL | LL | X = 3, | ^ enum already has `3` -error[E0081]: discriminant value `1` already exists +error[E0081]: discriminant value `255` already exists --> $DIR/E0081.rs:14:9 | LL | P = 257, - | --- first use of `1` (overflowed from `257`) + | --- first use of `255` (overflowed from `257`) LL | LL | X = 513, - | ^^^ enum already has `1` (overflowed from `513`) + | ^^^ enum already has `255` (overflowed from `513`) error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-94239.rs b/src/test/ui/issues/issue-94239.rs new file mode 100644 index 0000000000000..a09ae32aa74d6 --- /dev/null +++ b/src/test/ui/issues/issue-94239.rs @@ -0,0 +1,8 @@ +pub const fn test_match_range(len: u64) -> u64 { + match len { + 10000000000000000000..=99999999999999999999 => 0, //~ ERROR literal out of range for `u64` + _ => unreachable!(), + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-94239.stderr b/src/test/ui/issues/issue-94239.stderr new file mode 100644 index 0000000000000..057fbfec64f9b --- /dev/null +++ b/src/test/ui/issues/issue-94239.stderr @@ -0,0 +1,11 @@ +error: literal out of range for `u64` + --> $DIR/issue-94239.rs:3:32 + | +LL | 10000000000000000000..=99999999999999999999 => 0, + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(overflowing_literals)]` on by default + = note: the literal `99999999999999999999` does not fit into the type `u64` whose range is `0..=18446744073709551615` + +error: aborting due to previous error +