diff --git a/Cargo.lock b/Cargo.lock index c83763be3d893..325503a0e9564 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2950,9 +2950,9 @@ dependencies = [ [[package]] name = "racer" -version = "2.2.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b4b5faaf07040474e8af74a9e19ff167d5d204df5db5c5c765edecfb900358" +checksum = "64954e44fc0d1dcc64e0b9f2b155249ad62849eba25354b76ae1598d1e8f0fa0" dependencies = [ "bitflags", "clap 2.34.0", diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index a58c788eb57bd..e7fd89c140fc7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -157,14 +157,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Error with the match place LookupResult::Parent(_) => { for ge in &mut *grouped_errors { - if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge { - if match_span == *span { - debug!("appending local({:?}) to list", bind_to); - if !binds_to.is_empty() { - binds_to.push(bind_to); - } - return; + if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge + && match_span == *span + { + debug!("appending local({:?}) to list", bind_to); + if !binds_to.is_empty() { + binds_to.push(bind_to); } + return; } } debug!("found a new move error location"); @@ -353,7 +353,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { None => bug!("closure kind not inferred by borrowck"), }; let capture_description = - format!("captured variable in an `{}` closure", closure_kind); + format!("captured variable in an `{closure_kind}` closure"); let upvar = &self.upvars[upvar_field.unwrap().index()]; let upvar_hir_id = upvar.place.get_root_variable(); @@ -364,9 +364,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let place_description = if self.is_upvar_field_projection(move_place.as_ref()).is_some() { - format!("{}, a {}", place_name, capture_description) + format!("{place_name}, a {capture_description}") } else { - format!("{}, as `{}` is a {}", place_name, upvar_name, capture_description) + format!("{place_name}, as `{upvar_name}` is a {capture_description}") }; debug!( @@ -379,7 +379,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label(upvar_span, "captured outer variable"); diag.span_label( self.body.span, - format!("captured by this `{}` closure", closure_kind), + format!("captured by this `{closure_kind}` closure"), ); diag @@ -390,7 +390,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { (Some(place_desc), Some(source_desc)) => self.cannot_move_out_of( span, - &format!("`{}` which is behind a {}", place_desc, source_desc), + &format!("`{place_desc}` which is behind a {source_desc}"), ), (_, _) => self.cannot_move_out_of( span, @@ -435,7 +435,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.span_suggestion( span, "consider borrowing here", - format!("&{}", snippet), + format!("&{snippet}"), Applicability::Unspecified, ); } @@ -443,7 +443,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if binds_to.is_empty() { let place_ty = move_from.ty(self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(move_from.as_ref()) { - Some(desc) => format!("`{}`", desc), + Some(desc) => format!("`{desc}`"), None => "value".to_string(), }; @@ -472,12 +472,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let span = use_spans.var_or_use(); let place_ty = original_path.ty(self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(original_path.as_ref()) { - Some(desc) => format!("`{}`", desc), + Some(desc) => format!("`{desc}`"), None => "value".to_string(), }; self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), ""); - use_spans.args_span_label(err, format!("move out of {} occurs here", place_desc)); + use_spans.args_span_label(err, format!("move out of {place_desc} occurs here")); } } } @@ -511,7 +511,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { for (span, to_remove, suggestion) in suggestions { err.span_suggestion( span, - &format!("consider removing the `{}`", to_remove), + &format!("consider removing the `{to_remove}`"), suggestion, Applicability::MachineApplicable, ); diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 6e551e95cbb43..8b12db071b6ac 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -55,7 +55,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { reason = ", as it is not declared as mutable".to_string(); } else { let name = self.local_names[local].expect("immutable unnamed local"); - reason = format!(", as `{}` is not declared as mutable", name); + reason = format!(", as `{name}` is not declared as mutable"); } } @@ -88,7 +88,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { reason = ", as it is not declared as mutable".to_string(); } else { let name = self.upvars[upvar_index.index()].place.to_string(self.infcx.tcx); - reason = format!(", as `{}` is not declared as mutable", name); + reason = format!(", as `{name}` is not declared as mutable"); } } } @@ -103,14 +103,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if self.body.local_decls[local].is_ref_to_static() => { if access_place.projection.len() == 1 { - item_msg = format!("immutable static item {}", access_place_desc); + item_msg = format!("immutable static item {access_place_desc}"); reason = String::new(); } else { item_msg = access_place_desc; let local_info = &self.body.local_decls[local].local_info; if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info { let static_name = &self.infcx.tcx.item_name(def_id); - reason = format!(", as `{}` is an immutable static item", static_name); + reason = format!(", as `{static_name}` is an immutable static item"); } else { bug!("is_ref_to_static return true, but not ref to static?"); } @@ -148,15 +148,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let pointer_type = source.describe_for_immutable_place(self.infcx.tcx); opt_source = Some(source); if let Some(desc) = self.describe_place(access_place.as_ref()) { - item_msg = format!("`{}`", desc); + item_msg = format!("`{desc}`"); reason = match error_access { - AccessKind::Mutate => format!(", which is behind {}", pointer_type), + AccessKind::Mutate => format!(", which is behind {pointer_type}"), AccessKind::MutableBorrow => { - format!(", as it is behind {}", pointer_type) + format!(", as it is behind {pointer_type}") } } } else { - item_msg = format!("data in {}", pointer_type); + item_msg = format!("data in {pointer_type}"); reason = String::new(); } } @@ -362,29 +362,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar_hir_id = captured_place.get_root_variable(); - if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_hir_id) { - if let hir::PatKind::Binding( + if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_hir_id) + && let hir::PatKind::Binding( hir::BindingAnnotation::Unannotated, _, upvar_ident, _, ) = pat.kind - { - err.span_suggestion( - upvar_ident.span, - "consider changing this to be mutable", - format!("mut {}", upvar_ident.name), - Applicability::MachineApplicable, - ); - } + { + err.span_suggestion( + upvar_ident.span, + "consider changing this to be mutable", + format!("mut {}", upvar_ident.name), + Applicability::MachineApplicable, + ); } let tcx = self.infcx.tcx; if let ty::Ref(_, ty, Mutability::Mut) = the_place_err.ty(self.body, tcx).ty.kind() + && let ty::Closure(id, _) = *ty.kind() { - if let ty::Closure(id, _) = *ty.kind() { - self.show_mutating_upvar(tcx, id, the_place_err, &mut err); - } + self.show_mutating_upvar(tcx, id, the_place_err, &mut err); } } @@ -544,8 +542,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.span_suggestion( err_help_span, &format!( - "consider changing this to be a mutable {}", - pointer_desc + "consider changing this to be a mutable {pointer_desc}" ), suggested_code, Applicability::MachineApplicable, @@ -554,8 +551,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.span_suggestion( x, &format!( - "consider changing that to be a mutable {}", - pointer_desc + "consider changing that to be a mutable {pointer_desc}" ), suggested_code, Applicability::MachineApplicable, @@ -606,15 +602,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(BorrowedContentSource::OverloadedDeref(ty)) => { err.help(&format!( "trait `DerefMut` is required to modify through a dereference, \ - but it is not implemented for `{}`", - ty, + but it is not implemented for `{ty}`", )); } Some(BorrowedContentSource::OverloadedIndex(ty)) => { err.help(&format!( "trait `IndexMut` is required to modify indexed content, \ - but it is not implemented for `{}`", - ty, + but it is not implemented for `{ty}`", )); } _ => (), @@ -724,18 +718,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ty::UpvarCapture::ByRef( ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow, ) => { - capture_reason = format!("mutable borrow of `{}`", upvar); + capture_reason = format!("mutable borrow of `{upvar}`"); } ty::UpvarCapture::ByValue => { - capture_reason = format!("possible mutation of `{}`", upvar); + capture_reason = format!("possible mutation of `{upvar}`"); } - _ => bug!("upvar `{}` borrowed, but not mutably", upvar), + _ => bug!("upvar `{upvar}` borrowed, but not mutably"), } break; } } if capture_reason.is_empty() { - bug!("upvar `{}` borrowed, but cannot find reason", upvar); + bug!("upvar `{upvar}` borrowed, but cannot find reason"); } capture_reason } else { @@ -829,19 +823,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .as_str() .starts_with(&original_method_ident.name.to_string()) }) - .map(|ident| format!("{}()", ident)) + .map(|ident| format!("{ident}()")) .peekable() }); - if let Some(mut suggestions) = opt_suggestions { - if suggestions.peek().is_some() { - err.span_suggestions( - *span, - "use mutable method", - suggestions, - Applicability::MaybeIncorrect, - ); - } + if let Some(mut suggestions) = opt_suggestions + && suggestions.peek().is_some() + { + err.span_suggestions( + *span, + "use mutable method", + suggestions, + Applicability::MaybeIncorrect, + ); } } }; @@ -849,7 +843,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. fn expected_fn_found_fn_mut_call(&self, err: &mut Diagnostic, sp: Span, act: &str) { - err.span_label(sp, format!("cannot {}", act)); + err.span_label(sp, format!("cannot {act}")); let hir = self.infcx.tcx.hir(); let closure_id = self.mir_hir_id(); @@ -1011,35 +1005,35 @@ fn suggest_ampmut<'tcx>( opt_assignment_rhs_span: Option, opt_ty_info: Option, ) -> (Span, String) { - if let Some(assignment_rhs_span) = opt_assignment_rhs_span { - if let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) { - let is_mutbl = |ty: &str| -> bool { - if let Some(rest) = ty.strip_prefix("mut") { - match rest.chars().next() { - // e.g. `&mut x` - Some(c) if c.is_whitespace() => true, - // e.g. `&mut(x)` - Some('(') => true, - // e.g. `&mut{x}` - Some('{') => true, - // e.g. `&mutablevar` - _ => false, - } - } else { - false - } - }; - if let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(char::is_whitespace)) { - let lt_name = &src[1..ws_pos]; - let ty = src[ws_pos..].trim_start(); - if !is_mutbl(ty) { - return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty)); - } - } else if let Some(stripped) = src.strip_prefix('&') { - let stripped = stripped.trim_start(); - if !is_mutbl(stripped) { - return (assignment_rhs_span, format!("&mut {}", stripped)); + if let Some(assignment_rhs_span) = opt_assignment_rhs_span + && let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span) + { + let is_mutbl = |ty: &str| -> bool { + if let Some(rest) = ty.strip_prefix("mut") { + match rest.chars().next() { + // e.g. `&mut x` + Some(c) if c.is_whitespace() => true, + // e.g. `&mut(x)` + Some('(') => true, + // e.g. `&mut{x}` + Some('{') => true, + // e.g. `&mutablevar` + _ => false, } + } else { + false + } + }; + if let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(char::is_whitespace)) { + let lt_name = &src[1..ws_pos]; + let ty = src[ws_pos..].trim_start(); + if !is_mutbl(ty) { + return (assignment_rhs_span, format!("&{lt_name} mut {ty}")); + } + } else if let Some(stripped) = src.strip_prefix('&') { + let stripped = stripped.trim_start(); + if !is_mutbl(stripped) { + return (assignment_rhs_span, format!("&mut {stripped}")); } } } @@ -1054,12 +1048,12 @@ fn suggest_ampmut<'tcx>( None => local_decl.source_info.span, }; - if let Ok(src) = tcx.sess.source_map().span_to_snippet(highlight_span) { - if let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(char::is_whitespace)) { - let lt_name = &src[1..ws_pos]; - let ty = &src[ws_pos..]; - return (highlight_span, format!("&{} mut{}", lt_name, ty)); - } + if let Ok(src) = tcx.sess.source_map().span_to_snippet(highlight_span) + && let (true, Some(ws_pos)) = (src.starts_with("&'"), src.find(char::is_whitespace)) + { + let lt_name = &src[1..ws_pos]; + let ty = &src[ws_pos..]; + return (highlight_span, format!("&{} mut{}", lt_name, ty)); } let ty_mut = local_decl.ty.builtin_deref(true).unwrap(); diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index c1c325adb7fd1..ab9c206a46f45 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -168,13 +168,12 @@ impl OutlivesSuggestionBuilder { let fr_name = self.region_vid_to_name(mbcx, errci.fr); let outlived_fr_name = self.region_vid_to_name(mbcx, errci.outlived_fr); - if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) { - if !matches!(outlived_fr_name.source, RegionNameSource::Static) { - diag.help(&format!( - "consider adding the following bound: `{}: {}`", - fr_name, outlived_fr_name - )); - } + if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) + && !matches!(outlived_fr_name.source, RegionNameSource::Static) + { + diag.help(&format!( + "consider adding the following bound: `{fr_name}: {outlived_fr_name}`", + )); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 1798c525f6d6c..5fd9ecf451366 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -337,7 +337,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ty::Ref(_, inner_ty, mutbl) => { assert_eq!(*mutbl, rustc_hir::Mutability::Mut); ( - format!("a mutable reference to `{}`", inner_ty), + format!("a mutable reference to `{inner_ty}`"), "mutable references are invariant over their type parameter" .to_string(), ) @@ -523,10 +523,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span { diag.span_label( outlived_fr_span, - format!( - "`{}` declared here, outside of the {} body", - outlived_fr_name, escapes_from - ), + format!("`{outlived_fr_name}` declared here, outside of the {escapes_from} body",), ); } @@ -534,12 +531,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label( fr_span, format!( - "`{}` is a reference that is only valid in the {} body", - fr_name, escapes_from + "`{fr_name}` is a reference that is only valid in the {escapes_from} body", ), ); - diag.span_label(*span, format!("`{}` escapes the {} body here", fr_name, escapes_from)); + diag.span_label(*span, format!("`{fr_name}` escapes the {escapes_from} body here")); } // Only show an extra note if we can find an 'error region' for both of the region @@ -611,9 +607,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label( *span, format!( - "{} was supposed to return data with lifetime `{}` but it is returning \ - data with lifetime `{}`", - mir_def_name, outlived_fr_name, fr_name + "{mir_def_name} was supposed to return data with lifetime `{outlived_fr_name}` but it is returning \ + data with lifetime `{fr_name}`", ), ); } @@ -698,7 +693,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // If there is a static predicate, then the only sensible suggestion is to replace // fr with `'static`. if has_static_predicate { - diag.help(&format!("consider replacing `{}` with `{}`", fr_name, static_str)); + diag.help(&format!("consider replacing `{fr_name}` with `{static_str}`")); } else { // Otherwise, we should suggest adding a constraint on the return type. let span = self.infcx.tcx.def_span(did); @@ -714,14 +709,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else { span }; - let suggestion = format!(" + {}", suggestable_fr_name); + let suggestion = format!(" + {suggestable_fr_name}"); let span = span.shrink_to_hi(); diag.span_suggestion( span, &format!( "to allow this `impl Trait` to capture borrowed data with lifetime \ - `{}`, add `{}` as a bound", - fr_name, suggestable_fr_name, + `{fr_name}`, add `{suggestable_fr_name}` as a bound", ), suggestion, Applicability::MachineApplicable, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 723adb8da1b17..7742813888e53 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -102,27 +102,24 @@ impl RegionName { match &self.source { RegionNameSource::NamedFreeRegion(span) | RegionNameSource::NamedEarlyBoundRegion(span) => { - diag.span_label(*span, format!("lifetime `{}` defined here", self)); + diag.span_label(*span, format!("lifetime `{self}` defined here")); } RegionNameSource::SynthesizedFreeEnvRegion(span, note) => { - diag.span_label( - *span, - format!("lifetime `{}` represents this closure's body", self), - ); + diag.span_label(*span, format!("lifetime `{self}` represents this closure's body")); diag.note(note); } RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::CannotMatchHirTy( span, type_name, )) => { - diag.span_label(*span, format!("has type `{}`", type_name)); + diag.span_label(*span, format!("has type `{type_name}`")); } RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::MatchedHirTy(span)) | RegionNameSource::AnonRegionFromOutput(RegionNameHighlight::MatchedHirTy(span), _) | RegionNameSource::AnonRegionFromAsyncFn(span) => { diag.span_label( *span, - format!("let's call the lifetime of this reference `{}`", self), + format!("let's call the lifetime of this reference `{self}`"), ); } RegionNameSource::AnonRegionFromArgument( @@ -132,7 +129,7 @@ impl RegionName { RegionNameHighlight::MatchedAdtAndSegment(span), _, ) => { - diag.span_label(*span, format!("let's call this `{}`", self)); + diag.span_label(*span, format!("let's call this `{self}`")); } RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::Occluded( span, @@ -140,7 +137,7 @@ impl RegionName { )) => { diag.span_label( *span, - format!("lifetime `{}` appears in the type {}", self, type_name), + format!("lifetime `{self}` appears in the type {type_name}"), ); } RegionNameSource::AnonRegionFromOutput( @@ -150,25 +147,24 @@ impl RegionName { diag.span_label( *span, format!( - "return type{} `{}` contains a lifetime `{}`", - mir_description, type_name, self + "return type{mir_description} `{type_name}` contains a lifetime `{self}`" ), ); } RegionNameSource::AnonRegionFromUpvar(span, upvar_name) => { diag.span_label( *span, - format!("lifetime `{}` appears in the type of `{}`", self, upvar_name), + format!("lifetime `{self}` appears in the type of `{upvar_name}`"), ); } RegionNameSource::AnonRegionFromOutput( RegionNameHighlight::CannotMatchHirTy(span, type_name), mir_description, ) => { - diag.span_label(*span, format!("return type{} is {}", mir_description, type_name)); + diag.span_label(*span, format!("return type{mir_description} is {type_name}")); } RegionNameSource::AnonRegionFromYieldTy(span, type_name) => { - diag.span_label(*span, format!("yield type is {}", type_name)); + diag.span_label(*span, format!("yield type is {type_name}")); } RegionNameSource::Static => {} } @@ -442,7 +438,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { "highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", type_name, needle_fr ); - if type_name.contains(&format!("'{}", counter)) { + if type_name.contains(&format!("'{counter}")) { // Only add a label if we can confirm that a region was labelled. RegionNameHighlight::CannotMatchHirTy(span, type_name) } else { @@ -809,7 +805,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // Note: generators from `async fn` yield `()`, so we don't have to // worry about them here. let yield_ty = self.regioncx.universal_regions().yield_ty?; - debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty,); + debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty); let tcx = self.infcx.tcx; diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index b856d1708abc9..498b2f1b081b3 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -167,17 +167,18 @@ pub(super) fn op_to_const<'tcx>( }, Immediate::ScalarPair(a, b) => { // We know `offset` is relative to the allocation, so we can use `into_parts`. - let (data, start) = match ecx.scalar_to_ptr(a.check_init().unwrap()).into_parts() { - (Some(alloc_id), offset) => { - (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes()) - } - (None, _offset) => ( - ecx.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable( - b"" as &[u8], - )), - 0, - ), - }; + let (data, start) = + match ecx.scalar_to_ptr(a.check_init().unwrap()).unwrap().into_parts() { + (Some(alloc_id), offset) => { + (ecx.tcx.global_alloc(alloc_id).unwrap_memory(), offset.bytes()) + } + (None, _offset) => ( + ecx.tcx.intern_const_alloc( + Allocation::from_bytes_byte_aligned_immutable(b"" as &[u8]), + ), + 0, + ), + }; let len = b.to_machine_usize(ecx).unwrap(); let start = start.try_into().unwrap(); let len: usize = len.try_into().unwrap(); diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index c44e27fc4a098..d57504deeab90 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -197,8 +197,8 @@ impl interpret::MayLeak for ! { } impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { - fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> bool { - match (a, b) { + fn guaranteed_eq(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, bool> { + Ok(match (a, b) { // Comparisons between integers are always known. (Scalar::Int { .. }, Scalar::Int { .. }) => a == b, // Equality with integers can never be known for sure. @@ -207,11 +207,11 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { // some things (like functions and vtables) do not have stable addresses // so we need to be careful around them (see e.g. #73722). (Scalar::Ptr(..), Scalar::Ptr(..)) => false, - } + }) } - fn guaranteed_ne(&mut self, a: Scalar, b: Scalar) -> bool { - match (a, b) { + fn guaranteed_ne(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, bool> { + Ok(match (a, b) { // Comparisons between integers are always known. (Scalar::Int(_), Scalar::Int(_)) => a != b, // Comparisons of abstract pointers with null pointers are known if the pointer @@ -219,13 +219,13 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { // Inequality with integers other than null can never be known for sure. (Scalar::Int(int), ptr @ Scalar::Ptr(..)) | (ptr @ Scalar::Ptr(..), Scalar::Int(int)) => { - int.is_null() && !self.scalar_may_be_null(ptr) + int.is_null() && !self.scalar_may_be_null(ptr)? } // FIXME: return `true` for at least some comparisons where we can reliably // determine the result of runtime inequality tests at compile-time. // Examples include comparison of addresses in different static items. (Scalar::Ptr(..), Scalar::Ptr(..)) => false, - } + }) } } @@ -329,9 +329,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, let a = ecx.read_immediate(&args[0])?.to_scalar()?; let b = ecx.read_immediate(&args[1])?.to_scalar()?; let cmp = if intrinsic_name == sym::ptr_guaranteed_eq { - ecx.guaranteed_eq(a, b) + ecx.guaranteed_eq(a, b)? } else { - ecx.guaranteed_ne(a, b) + ecx.guaranteed_ne(a, b)? }; ecx.write_scalar(Scalar::from_bool(cmp), dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index a244b79ed0754..3ea3729dbcd17 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -283,7 +283,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(entry_idx) = vptr_entry_idx { let entry_idx = u64::try_from(entry_idx).unwrap(); let (old_data, old_vptr) = val.to_scalar_pair()?; - let old_vptr = self.scalar_to_ptr(old_vptr); + let old_vptr = self.scalar_to_ptr(old_vptr)?; let new_vptr = self .read_new_vtable_after_trait_upcasting_from_vtable(old_vptr, entry_idx)?; self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index a2ea0f516bfa4..f0fff602fe4cf 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -640,7 +640,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(Some((size, align))) } ty::Dynamic(..) => { - let vtable = self.scalar_to_ptr(metadata.unwrap_meta()); + let vtable = self.scalar_to_ptr(metadata.unwrap_meta())?; // Read size and align from vtable (already checks size). Ok(Some(self.read_size_and_align_from_vtable(vtable)?)) } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index f1acb9e41c4ce..1fda60c021eed 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -202,7 +202,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory if let ty::Dynamic(..) = tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind() { - let ptr = self.ecx.scalar_to_ptr(mplace.meta.unwrap_meta()); + let ptr = self.ecx.scalar_to_ptr(mplace.meta.unwrap_meta())?; if let Some(alloc_id) = ptr.provenance { // Explicitly choose const mode here, since vtables are immutable, even // if the reference of the fat pointer is mutable. diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a02115a110b7b..556a44a523819 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -1102,30 +1102,38 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Machine pointer introspection. impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - pub fn scalar_to_ptr(&self, scalar: Scalar) -> Pointer> { + pub fn scalar_to_ptr( + &self, + scalar: Scalar, + ) -> InterpResult<'tcx, Pointer>> { // We use `to_bits_or_ptr_internal` since we are just implementing the method people need to // call to force getting out a pointer. - match scalar.to_bits_or_ptr_internal(self.pointer_size()) { - Err(ptr) => ptr.into(), - Ok(bits) => { - let addr = u64::try_from(bits).unwrap(); - let ptr = M::ptr_from_addr(&self, addr); - if addr == 0 { - assert!(ptr.provenance.is_none(), "null pointer can never have an AllocId"); + Ok( + match scalar + .to_bits_or_ptr_internal(self.pointer_size()) + .map_err(|s| err_ub!(ScalarSizeMismatch(s)))? + { + Err(ptr) => ptr.into(), + Ok(bits) => { + let addr = u64::try_from(bits).unwrap(); + let ptr = M::ptr_from_addr(&self, addr); + if addr == 0 { + assert!(ptr.provenance.is_none(), "null pointer can never have an AllocId"); + } + ptr } - ptr - } - } + }, + ) } /// Test if this value might be null. /// If the machine does not support ptr-to-int casts, this is conservative. - pub fn scalar_may_be_null(&self, scalar: Scalar) -> bool { - match scalar.try_to_int() { + pub fn scalar_may_be_null(&self, scalar: Scalar) -> InterpResult<'tcx, bool> { + Ok(match scalar.try_to_int() { Ok(int) => int.is_null(), Err(_) => { // Can only happen during CTFE. - let ptr = self.scalar_to_ptr(scalar); + let ptr = self.scalar_to_ptr(scalar)?; match self.ptr_try_get_alloc_id(ptr) { Ok((alloc_id, offset, _)) => { let (size, _align) = self @@ -1138,7 +1146,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Err(_offset) => bug!("a non-int scalar is always a pointer"), } } - } + }) } /// Turning a "maybe pointer" into a proper pointer (and some information diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index ee1ba60829316..dfc0028e87fcc 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -342,7 +342,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, op: &OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, Pointer>> { - Ok(self.scalar_to_ptr(self.read_scalar(op)?.check_init()?)) + self.scalar_to_ptr(self.read_scalar(op)?.check_init()?) } // Turn the wide MPlace into a string (must already be dereferenced!) @@ -738,7 +738,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // okay. Everything else, we conservatively reject. let ptr_valid = niche_start == 0 && variants_start == variants_end - && !self.scalar_may_be_null(tag_val); + && !self.scalar_may_be_null(tag_val)?; if !ptr_valid { throw_ub!(InvalidTag(dbg_val)) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 5f7f52ef9e9f4..51d47af2f8e24 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -281,7 +281,7 @@ where }; let mplace = MemPlace { - ptr: self.scalar_to_ptr(ptr.check_init()?), + ptr: self.scalar_to_ptr(ptr.check_init()?)?, // We could use the run-time alignment here. For now, we do not, because // the point of tracking the alignment here is to make sure that the *static* // alignment information emitted with the loads is correct. The run-time @@ -1104,7 +1104,7 @@ where &self, mplace: &MPlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, (ty::Instance<'tcx>, MPlaceTy<'tcx, M::PointerTag>)> { - let vtable = self.scalar_to_ptr(mplace.vtable()); // also sanity checks the type + let vtable = self.scalar_to_ptr(mplace.vtable())?; // also sanity checks the type let (instance, ty) = self.read_drop_type_from_vtable(vtable)?; let layout = self.layout_of(ty)?; diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index c2a38c6978bfb..c2664565f15cb 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -519,7 +519,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .kind(), ty::Dynamic(..) )); - let vtable = self.scalar_to_ptr(receiver_place.meta.unwrap_meta()); + let vtable = self.scalar_to_ptr(receiver_place.meta.unwrap_meta())?; let fn_val = self.get_vtable_slot(vtable, u64::try_from(idx).unwrap())?; // `*mut receiver_place.layout.ty` is almost the layout that we diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 5cf3807faaa6d..235938422a893 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -50,7 +50,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let vtable_slot = self .get_ptr_alloc(vtable_slot, ptr_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); - let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?); + let fn_ptr = self.scalar_to_ptr(vtable_slot.read_ptr_sized(Size::ZERO)?.check_init()?)?; self.get_ptr_fn(fn_ptr) } @@ -75,7 +75,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .check_init()?; // We *need* an instance here, no other kind of function value, to be able // to determine the type. - let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn))?.as_instance()?; + let drop_instance = self.get_ptr_fn(self.scalar_to_ptr(drop_fn)?)?.as_instance()?; trace!("Found drop fn: {:?}", drop_instance); let fn_sig = drop_instance.ty(*self.tcx, self.param_env).fn_sig(*self.tcx); let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig); @@ -132,7 +132,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .get_ptr_alloc(vtable_slot, pointer_size, self.tcx.data_layout.pointer_align.abi)? .expect("cannot be a ZST"); - let new_vtable = self.scalar_to_ptr(new_vtable.read_ptr_sized(Size::ZERO)?.check_init()?); + let new_vtable = + self.scalar_to_ptr(new_vtable.read_ptr_sized(Size::ZERO)?.check_init()?)?; Ok(new_vtable) } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 349806d997945..4a0aa41de739b 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -312,7 +312,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); match tail.kind() { ty::Dynamic(..) => { - let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta()); + let vtable = self.ecx.scalar_to_ptr(meta.unwrap_meta())?; // Direct call to `check_ptr_access_align` checks alignment even on CTFE machines. try_validation!( self.ecx.check_ptr_access_align( @@ -577,7 +577,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // If we check references recursively, also check that this points to a function. if let Some(_) = self.ref_tracking { - let ptr = self.ecx.scalar_to_ptr(value); + let ptr = self.ecx.scalar_to_ptr(value)?; let _fn = try_validation!( self.ecx.get_ptr_fn(ptr), self.path, @@ -590,7 +590,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // FIXME: Check if the signature matches } else { // Otherwise (for standalone Miri), we have to still check it to be non-null. - if self.ecx.scalar_may_be_null(value) { + if self.ecx.scalar_may_be_null(value)? { throw_validation_failure!(self.path, { "a null function pointer" }); } } @@ -667,7 +667,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // We support 2 kinds of ranges here: full range, and excluding zero. if start == 1 && end == max_value { // Only null is the niche. So make sure the ptr is NOT null. - if self.ecx.scalar_may_be_null(value) { + if self.ecx.scalar_may_be_null(value)? { throw_validation_failure!(self.path, { "a potentially null pointer" } expected { diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 63f2bc51aeeaa..438f356f072c6 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -15,8 +15,8 @@ use rustc_target::abi::{Align, HasDataLayout, Size}; use super::{ read_target_uint, write_target_uint, AllocId, InterpError, InterpResult, Pointer, Provenance, - ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, UndefinedBehaviorInfo, UninitBytesAccess, - UnsupportedOpInfo, + ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, ScalarSizeMismatch, UndefinedBehaviorInfo, + UninitBytesAccess, UnsupportedOpInfo, }; use crate::ty; @@ -81,6 +81,8 @@ impl<'tcx, Tag, Extra> ConstAllocation<'tcx, Tag, Extra> { /// is added when converting to `InterpError`. #[derive(Debug)] pub enum AllocError { + /// A scalar had the wrong size. + ScalarSizeMismatch(ScalarSizeMismatch), /// Encountered a pointer where we needed raw bytes. ReadPointerAsBytes, /// Partially overwriting a pointer. @@ -90,10 +92,19 @@ pub enum AllocError { } pub type AllocResult = Result; +impl From for AllocError { + fn from(s: ScalarSizeMismatch) -> Self { + AllocError::ScalarSizeMismatch(s) + } +} + impl AllocError { pub fn to_interp_error<'tcx>(self, alloc_id: AllocId) -> InterpError<'tcx> { use AllocError::*; match self { + ScalarSizeMismatch(s) => { + InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ScalarSizeMismatch(s)) + } ReadPointerAsBytes => InterpError::Unsupported(UnsupportedOpInfo::ReadPointerAsBytes), PartialPointerOverwrite(offset) => InterpError::Unsupported( UnsupportedOpInfo::PartialPointerOverwrite(Pointer::new(alloc_id, offset)), @@ -425,7 +436,7 @@ impl Allocation { // `to_bits_or_ptr_internal` is the right method because we just want to store this data // as-is into memory. - let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size) { + let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? { Err(val) => { let (provenance, offset) = val.into_parts(); (u128::from(offset.bytes()), Some(provenance)) diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 492091a4f2540..9afe9523fcab0 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -221,6 +221,13 @@ pub struct UninitBytesAccess { pub uninit_size: Size, } +/// Information about a size mismatch. +#[derive(Debug)] +pub struct ScalarSizeMismatch { + pub target_size: u64, + pub data_size: u64, +} + /// Error information for when the program caused Undefined Behavior. pub enum UndefinedBehaviorInfo<'tcx> { /// Free-form case. Only for errors that are never caught! @@ -298,10 +305,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Working with a local that is not currently live. DeadLocal, /// Data size is not equal to target size. - ScalarSizeMismatch { - target_size: u64, - data_size: u64, - }, + ScalarSizeMismatch(ScalarSizeMismatch), /// A discriminant of an uninhabited enum variant is written. UninhabitedEnumVariantWritten, } @@ -408,7 +412,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { "using uninitialized data, but this operation requires initialized memory" ), DeadLocal => write!(f, "accessing a dead local variable"), - ScalarSizeMismatch { target_size, data_size } => write!( + ScalarSizeMismatch(self::ScalarSizeMismatch { target_size, data_size }) => write!( f, "scalar size mismatch: expected {} bytes but got {} bytes instead", target_size, data_size diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index bce962491b7b1..d8cba39c6d97b 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -120,7 +120,8 @@ use crate::ty::{self, Instance, Ty, TyCtxt}; pub use self::error::{ struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, - ResourceExhaustionInfo, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo, + ResourceExhaustionInfo, ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, + UnsupportedOpInfo, }; pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit}; diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 8e32603a35702..9cffdf2993ed5 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -12,6 +12,7 @@ use crate::ty::{Lift, ParamEnv, ScalarInt, Ty, TyCtxt}; use super::{ AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance, + ScalarSizeMismatch, }; /// Represents the result of const evaluation via the `eval_to_allocation` query. @@ -300,16 +301,29 @@ impl Scalar { /// /// This method only exists for the benefit of low-level operations that truly need to treat the /// scalar in whatever form it is. + /// + /// This throws UB (instead of ICEing) on a size mismatch since size mismatches can arise in + /// Miri when someone declares a function that we shim (such as `malloc`) with a wrong type. #[inline] - pub fn to_bits_or_ptr_internal(self, target_size: Size) -> Result> { + pub fn to_bits_or_ptr_internal( + self, + target_size: Size, + ) -> Result>, ScalarSizeMismatch> { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); - match self { - Scalar::Int(int) => Ok(int.assert_bits(target_size)), + Ok(match self { + Scalar::Int(int) => Ok(int.to_bits(target_size).map_err(|size| { + ScalarSizeMismatch { target_size: target_size.bytes(), data_size: size.bytes() } + })?), Scalar::Ptr(ptr, sz) => { - assert_eq!(target_size.bytes(), u64::from(sz)); + if target_size.bytes() != sz.into() { + return Err(ScalarSizeMismatch { + target_size: target_size.bytes(), + data_size: sz.into(), + }); + } Err(ptr) } - } + }) } } @@ -348,10 +362,10 @@ impl<'tcx, Tag: Provenance> Scalar { assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); self.try_to_int().map_err(|_| err_unsup!(ReadPointerAsBytes))?.to_bits(target_size).map_err( |size| { - err_ub!(ScalarSizeMismatch { + err_ub!(ScalarSizeMismatch(ScalarSizeMismatch { target_size: target_size.bytes(), data_size: size.bytes(), - }) + })) .into() }, ) diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 1fadd0c26fc49..bb3ba3e596d14 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -146,7 +146,7 @@ impl IntRange { // straight to the result, after doing a bit of checking. (We // could remove this branch and just fall through, which // is more general but much slower.) - if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size) { + if let Ok(bits) = scalar.to_bits_or_ptr_internal(target_size).unwrap() { return Some(bits); } } diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index 5c5632a9d0164..2bcb3182a7bf2 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -65,6 +65,7 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe // // Note: this is the same implementation as in libstd's `abort_internal` unsafe fn abort() -> ! { + #[allow(unused)] const FAST_FAIL_FATAL_APP_EXIT: usize = 7; cfg_if::cfg_if! { if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 9e9750eb8de40..cf51d8da16db5 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -2,6 +2,8 @@ use super::*; +use std::marker::PhantomData; + macro_rules! define_handles { ( 'owned: $($oty:ident,)* @@ -45,20 +47,25 @@ macro_rules! define_handles { $( #[repr(C)] - pub(crate) struct $oty(handle::Handle); - impl !Send for $oty {} - impl !Sync for $oty {} + pub(crate) struct $oty { + handle: handle::Handle, + // Prevent Send and Sync impls + _marker: PhantomData<*mut ()>, + } // Forward `Drop::drop` to the inherent `drop` method. impl Drop for $oty { fn drop(&mut self) { - $oty(self.0).drop(); + $oty { + handle: self.handle, + _marker: PhantomData, + }.drop(); } } impl Encode for $oty { fn encode(self, w: &mut Writer, s: &mut S) { - let handle = self.0; + let handle = self.handle; mem::forget(self); handle.encode(w, s); } @@ -74,7 +81,7 @@ macro_rules! define_handles { impl Encode for &$oty { fn encode(self, w: &mut Writer, s: &mut S) { - self.0.encode(w, s); + self.handle.encode(w, s); } } @@ -88,7 +95,7 @@ macro_rules! define_handles { impl Encode for &mut $oty { fn encode(self, w: &mut Writer, s: &mut S) { - self.0.encode(w, s); + self.handle.encode(w, s); } } @@ -113,7 +120,10 @@ macro_rules! define_handles { impl DecodeMut<'_, '_, S> for $oty { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { - $oty(handle::Handle::decode(r, s)) + $oty { + handle: handle::Handle::decode(r, s), + _marker: PhantomData, + } } } )* @@ -121,13 +131,15 @@ macro_rules! define_handles { $( #[repr(C)] #[derive(Copy, Clone, PartialEq, Eq, Hash)] - pub(crate) struct $ity(handle::Handle); - impl !Send for $ity {} - impl !Sync for $ity {} + pub(crate) struct $ity { + handle: handle::Handle, + // Prevent Send and Sync impls + _marker: PhantomData<*mut ()>, + } impl Encode for $ity { fn encode(self, w: &mut Writer, s: &mut S) { - self.0.encode(w, s); + self.handle.encode(w, s); } } @@ -149,7 +161,10 @@ macro_rules! define_handles { impl DecodeMut<'_, '_, S> for $ity { fn decode(r: &mut Reader<'_>, s: &mut S) -> Self { - $ity(handle::Handle::decode(r, s)) + $ity { + handle: handle::Handle::decode(r, s), + _marker: PhantomData, + } } } )* @@ -310,7 +325,8 @@ impl Bridge<'_> { // NB. the server can't do this because it may use a different libstd. static HIDE_PANICS_DURING_EXPANSION: Once = Once::new(); HIDE_PANICS_DURING_EXPANSION.call_once(|| { - panic::update_hook(move |prev, info| { + let prev = panic::take_hook(); + panic::set_hook(Box::new(move |info| { let show = BridgeState::with(|state| match state { BridgeState::NotConnected => true, BridgeState::Connected(_) | BridgeState::InUse => force_show_panics, @@ -318,7 +334,7 @@ impl Bridge<'_> { if show { prev(info) } - }); + })); }); BRIDGE_STATE.with(|state| state.set(BridgeState::Connected(self), f)) diff --git a/library/proc_macro/src/bridge/closure.rs b/library/proc_macro/src/bridge/closure.rs index 5bfe287d33ab7..06f76d2fc9140 100644 --- a/library/proc_macro/src/bridge/closure.rs +++ b/library/proc_macro/src/bridge/closure.rs @@ -1,24 +1,23 @@ //! Closure type (equivalent to `&mut dyn FnMut(A) -> R`) that's `repr(C)`. +use std::marker::PhantomData; + #[repr(C)] pub struct Closure<'a, A, R> { - call: unsafe extern "C" fn(&mut Env, A) -> R, - env: &'a mut Env, -} - -extern "C" { - type Env; + call: unsafe extern "C" fn(*mut Env, A) -> R, + env: *mut Env, + // Ensure Closure is !Send and !Sync + _marker: PhantomData<*mut &'a mut ()>, } -impl<'a, A, R> !Sync for Closure<'a, A, R> {} -impl<'a, A, R> !Send for Closure<'a, A, R> {} +struct Env; impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> { fn from(f: &'a mut F) -> Self { - unsafe extern "C" fn call R>(env: &mut Env, arg: A) -> R { + unsafe extern "C" fn call R>(env: *mut Env, arg: A) -> R { (*(env as *mut _ as *mut F))(arg) } - Closure { call: call::, env: unsafe { &mut *(f as *mut _ as *mut Env) } } + Closure { call: call::, env: f as *mut _ as *mut Env, _marker: PhantomData } } } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index fbeb585095bbb..f7c9df6564f87 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -231,10 +231,10 @@ pub struct Bridge<'a> { /// If 'true', always invoke the default panic hook force_show_panics: bool, -} -impl<'a> !Sync for Bridge<'a> {} -impl<'a> !Send for Bridge<'a> {} + // Prevent Send and Sync impls + _marker: marker::PhantomData<*mut ()>, +} #[forbid(unsafe_code)] #[allow(non_camel_case_types)] diff --git a/library/proc_macro/src/bridge/server.rs b/library/proc_macro/src/bridge/server.rs index 1b3ccf4c18e70..2e0400d32a0af 100644 --- a/library/proc_macro/src/bridge/server.rs +++ b/library/proc_macro/src/bridge/server.rs @@ -153,7 +153,12 @@ impl ExecutionStrategy for SameThread { let mut dispatch = |b| dispatcher.dispatch(b); run_client( - Bridge { cached_buffer: input, dispatch: (&mut dispatch).into(), force_show_panics }, + Bridge { + cached_buffer: input, + dispatch: (&mut dispatch).into(), + force_show_panics, + _marker: marker::PhantomData, + }, client_data, ) } @@ -189,6 +194,7 @@ impl ExecutionStrategy for CrossThread1 { cached_buffer: input, dispatch: (&mut dispatch).into(), force_show_panics, + _marker: marker::PhantomData, }, client_data, ) @@ -241,6 +247,7 @@ impl ExecutionStrategy for CrossThread2 { cached_buffer: input, dispatch: (&mut dispatch).into(), force_show_panics, + _marker: marker::PhantomData, }, client_data, ); diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 4a020e59e9cbe..00b8bb1eb2637 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -17,18 +17,18 @@ test(no_crate_inject, attr(deny(warnings))), test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] +// This library is copied into rust-analyzer to allow loading rustc compiled proc macros. +// Please avoid unstable features where possible to minimize the amount of changes necessary +// to make it compile with rust-analyzer on stable. #![feature(rustc_allow_const_fn_unstable)] #![feature(nll)] #![feature(staged_api)] #![feature(allow_internal_unstable)] #![feature(decl_macro)] -#![feature(extern_types)] #![feature(negative_impls)] -#![feature(auto_traits)] #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(min_specialization)] -#![feature(panic_update_hook)] #![recursion_limit = "256"] #[unstable(feature = "proc_macro_internals", issue = "27812")] diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index 87e3fec6353f9..47917e57b19ed 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -289,6 +289,7 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD { /// that function for more information on `__fastfail` #[allow(unreachable_code)] pub fn abort_internal() -> ! { + #[allow(unused)] const FAST_FAIL_FATAL_APP_EXIT: usize = 7; #[cfg(not(miri))] // inline assembly does not work in Miri unsafe { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 8c19cf973fc86..d06e4fa1cc2f5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -425,13 +425,26 @@ crate fn build_impl( None => ( tcx.associated_items(did) .in_definition_order() - .filter_map(|item| { - if associated_trait.is_some() || item.vis.is_public() { - Some(item.clean(cx)) + .filter(|item| { + // If this is a trait impl, filter out associated items whose corresponding item + // in the associated trait is marked `doc(hidden)`. + // If this is an inherent impl, filter out private associated items. + if let Some(associated_trait) = associated_trait { + let trait_item = tcx + .associated_items(associated_trait.def_id) + .find_by_name_and_kind( + tcx, + item.ident(tcx), + item.kind, + associated_trait.def_id, + ) + .unwrap(); // corresponding associated item has to exist + !tcx.is_doc_hidden(trait_item.def_id) } else { - None + item.vis.is_public() } }) + .map(|item| item.clean(cx)) .collect::>(), clean::enter_impl_trait(cx, |cx| { clean_ty_generics(cx, tcx.generics_of(did), predicates) diff --git a/src/test/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs b/src/test/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs new file mode 100644 index 0000000000000..3baf8a6c07ee8 --- /dev/null +++ b/src/test/rustdoc/auxiliary/cross-crate-hidden-assoc-trait-items.rs @@ -0,0 +1,19 @@ +pub trait Tr { + type VisibleAssoc; + #[doc(hidden)] + type HiddenAssoc; + + const VISIBLE_ASSOC: (); + #[doc(hidden)] + const HIDDEN_ASSOC: (); +} + +pub struct Ty; + +impl Tr for Ty { + type VisibleAssoc = (); + type HiddenAssoc = (); + + const VISIBLE_ASSOC: () = (); + const HIDDEN_ASSOC: () = (); +} diff --git a/src/test/rustdoc/cross-crate-hidden-assoc-trait-items.rs b/src/test/rustdoc/cross-crate-hidden-assoc-trait-items.rs new file mode 100644 index 0000000000000..d02bc4fe71250 --- /dev/null +++ b/src/test/rustdoc/cross-crate-hidden-assoc-trait-items.rs @@ -0,0 +1,23 @@ +// Regression test for issue #95717 +// Hide cross-crate `#[doc(hidden)]` associated items in trait impls. + +#![crate_name = "dependent"] +// edition:2021 +// aux-crate:dependency=cross-crate-hidden-assoc-trait-items.rs + +// The trait `Tr` contains 2 hidden and 2 visisible associated items. +// Instead of checking for the absence of the hidden items, check for the presence of the +// visible items instead and assert that there are *exactly two* associated items +// (by counting the number of `section`s). This is more robust and future-proof. + +// @has dependent/struct.Ty.html +// @has - '//*[@id="associatedtype.VisibleAssoc"]' 'type VisibleAssoc = ()' +// @has - '//*[@id="associatedconstant.VISIBLE_ASSOC"]' 'const VISIBLE_ASSOC: ()' +// @count - '//*[@class="impl-items"]/section' 2 + +// @has dependent/trait.Tr.html +// @has - '//*[@id="associatedtype.VisibleAssoc-1"]' 'type VisibleAssoc = ()' +// @has - '//*[@id="associatedconstant.VISIBLE_ASSOC-1"]' 'const VISIBLE_ASSOC: ()' +// @count - '//*[@class="impl-items"]/section' 2 + +pub use dependency::{Tr, Ty}; diff --git a/src/tools/rls b/src/tools/rls index 3df74381f3761..e6f71c9cadf9b 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 3df74381f37617ec800537c11fb0c3130f5f3616 +Subproject commit e6f71c9cadf9bbd2eff21334d1d51016c7f5e19d