Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #113468

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
39c3ef7
Fix comment of `fn_can_unwind`
nbdd0121 Jun 30, 2023
142075a
Make `UsageMap::get_user_items` infallible.
nnethercote Jul 4, 2023
22d4c79
Use `iter()` instead of `iter_mut()` in one place.
nnethercote Jul 4, 2023
b51169c
Remove the field name from `MonoItemPlacement::SingleCgu`.
nnethercote Jul 5, 2023
3078e4d
Minor comment fix.
nnethercote Jul 6, 2023
a118ce2
Add needs-triage to all new issues
Noratrieb Jul 6, 2023
7a83ef8
miri: check that assignments do not self-overlap
RalfJung Jul 7, 2023
d03b0f5
If re-export is private, get the next item until a public one is foun…
GuillaumeGomez Jul 5, 2023
e3b7035
Add regression test for #81141
GuillaumeGomez Jul 5, 2023
52a7615
Improve code readability
GuillaumeGomez Jul 7, 2023
f37a6b0
Extend issue-81141-private-reexport-in-public-api test to cover more …
GuillaumeGomez Jul 7, 2023
1d1951b
Rename `first_not_private` into `first_non_private`
GuillaumeGomez Jul 7, 2023
4a1e06b
Correctly handle `super` and `::`
GuillaumeGomez Jul 7, 2023
3aec8d4
Remove unused from_method symbol
spastorino Jul 7, 2023
6d80879
Add regression test for RPITITs
spastorino Jul 7, 2023
24326ee
Avoid calling report_forbidden_specialization for RPITITs
spastorino Jul 7, 2023
b9a4cfe
Update cargo
weihanglo Jul 7, 2023
5b58ad9
Rollup merge of #113374 - GuillaumeGomez:private-to-public-path, r=no…
matthiaskrgr Jul 8, 2023
0807ebd
Rollup merge of #113390 - nnethercote:cgu-tweaks, r=wesleywiser
matthiaskrgr Jul 8, 2023
ea84be6
Rollup merge of #113413 - Nilstrieb:this-needs-some-triaging, r=alber…
matthiaskrgr Jul 8, 2023
98cab44
Rollup merge of #113441 - RalfJung:assign-no-overlap, r=oli-obk
matthiaskrgr Jul 8, 2023
cd28d83
Rollup merge of #113453 - spastorino:new-rpitit-30, r=compiler-errors
matthiaskrgr Jul 8, 2023
95387b1
Rollup merge of #113456 - spastorino:new-rpitit-31, r=compiler-errors
matthiaskrgr Jul 8, 2023
9b878e3
Rollup merge of #113466 - weihanglo:update-cargo, r=weihanglo
matthiaskrgr Jul 8, 2023
c5563b8
Rollup merge of #113467 - nbdd0121:unwind, r=compiler-errors
matthiaskrgr Jul 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,8 +700,13 @@ where
assert_eq!(src.layout.size, dest.layout.size);
}

// Setting `nonoverlapping` here only has an effect when we don't hit the fast-path above,
// but that should at least match what LLVM does where `memcpy` is also only used when the
// type does not have Scalar/ScalarPair layout.
// (Or as the `Assign` docs put it, assignments "not producing primitives" must be
// non-overlapping.)
self.mem_copy(
src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ false,
src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ true,
)
}

Expand Down
13 changes: 11 additions & 2 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,14 @@ pub(super) fn check_specialization_validity<'tcx>(
let result = opt_result.unwrap_or(Ok(()));

if let Err(parent_impl) = result {
report_forbidden_specialization(tcx, impl_item, parent_impl);
if !tcx.is_impl_trait_in_trait(impl_item) {
report_forbidden_specialization(tcx, impl_item, parent_impl);
} else {
tcx.sess.delay_span_bug(
DUMMY_SP,
format!("parent item: {:?} not marked as default", parent_impl),
);
}
}
}

Expand Down Expand Up @@ -1485,7 +1492,9 @@ fn opaque_type_cycle_error(
}

for closure_def_id in visitor.closures {
let Some(closure_local_did) = closure_def_id.as_local() else { continue; };
let Some(closure_local_did) = closure_def_id.as_local() else {
continue;
};
let typeck_results = tcx.typeck(closure_local_did);

let mut label_match = |ty: Ty<'_>, span| {
Expand Down
16 changes: 5 additions & 11 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1110,12 +1110,11 @@ where
///
/// This takes two primary parameters:
///
/// * `codegen_fn_attr_flags` - these are flags calculated as part of the
/// codegen attrs for a defined function. For function pointers this set of
/// flags is the empty set. This is only applicable for Rust-defined
/// functions, and generally isn't needed except for small optimizations where
/// we try to say a function which otherwise might look like it could unwind
/// doesn't actually unwind (such as for intrinsics and such).
/// * `fn_def_id` - the `DefId` of the function. If this is provided then we can
/// determine more precisely if the function can unwind. If this is not provided
/// then we will only infer whether the function can unwind or not based on the
/// ABI of the function. For example, a function marked with `#[rustc_nounwind]`
/// is known to not unwind even if it's using Rust ABI.
///
/// * `abi` - this is the ABI that the function is defined with. This is the
/// primary factor for determining whether a function can unwind or not.
Expand Down Expand Up @@ -1147,11 +1146,6 @@ where
/// aborts the process.
/// * This affects whether functions have the LLVM `nounwind` attribute, which
/// affects various optimizations and codegen.
///
/// FIXME: this is actually buggy with respect to Rust functions. Rust functions
/// compiled with `-Cpanic=unwind` and referenced from another crate compiled
/// with `-Cpanic=abort` will look like they can't unwind when in fact they
/// might (from a foreign exception or similar).
#[inline]
#[tracing::instrument(level = "debug", skip(tcx))]
pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) -> bool {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,8 @@ impl<'tcx> UsageMap<'tcx> {
assert!(self.used_map.insert(user_item, used_items).is_none());
}

pub fn get_user_items(&self, item: MonoItem<'tcx>) -> Option<&[MonoItem<'tcx>]> {
self.user_map.get(&item).map(|items| items.as_slice())
pub fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] {
self.user_map.get(&item).map(|items| items.as_slice()).unwrap_or(&[])
}

/// Internally iterate over all inlined items used by `item`.
Expand Down
44 changes: 22 additions & 22 deletions compiler/rustc_monomorphize/src/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,9 +427,9 @@ fn merge_codegen_units<'tcx>(
// zero-padded suffixes, which means they are automatically sorted by
// names. The numeric suffix width depends on the number of CGUs, which
// is always greater than zero:
// - [1,9] CGUS: `0`, `1`, `2`, ...
// - [10,99] CGUS: `00`, `01`, `02`, ...
// - [100,999] CGUS: `000`, `001`, `002`, ...
// - [1,9] CGUs: `0`, `1`, `2`, ...
// - [10,99] CGUs: `00`, `01`, `02`, ...
// - [100,999] CGUs: `000`, `001`, `002`, ...
// - etc.
//
// If we didn't zero-pad the sorted-by-name order would be `XYZ-cgu.0`,
Expand Down Expand Up @@ -458,29 +458,29 @@ fn internalize_symbols<'tcx>(
/// used to keep track of that.
#[derive(Clone, PartialEq, Eq, Debug)]
enum MonoItemPlacement {
SingleCgu { cgu_name: Symbol },
SingleCgu(Symbol),
MultipleCgus,
}

let mut mono_item_placements = FxHashMap::default();
let single_codegen_unit = codegen_units.len() == 1;

if !single_codegen_unit {
for cgu in codegen_units.iter_mut() {
for cgu in codegen_units.iter() {
for item in cgu.items().keys() {
// If there is more than one codegen unit, we need to keep track
// in which codegen units each monomorphization is placed.
match mono_item_placements.entry(*item) {
Entry::Occupied(e) => {
let placement = e.into_mut();
debug_assert!(match *placement {
MonoItemPlacement::SingleCgu { cgu_name } => cgu_name != cgu.name(),
MonoItemPlacement::SingleCgu(cgu_name) => cgu_name != cgu.name(),
MonoItemPlacement::MultipleCgus => true,
});
*placement = MonoItemPlacement::MultipleCgus;
}
Entry::Vacant(e) => {
e.insert(MonoItemPlacement::SingleCgu { cgu_name: cgu.name() });
e.insert(MonoItemPlacement::SingleCgu(cgu.name()));
}
}
}
Expand All @@ -490,7 +490,7 @@ fn internalize_symbols<'tcx>(
// For each internalization candidates in each codegen unit, check if it is
// used from outside its defining codegen unit.
for cgu in codegen_units {
let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
let home_cgu = MonoItemPlacement::SingleCgu(cgu.name());

for (item, linkage_and_visibility) in cgu.items_mut() {
if !internalization_candidates.contains(item) {
Expand All @@ -501,20 +501,20 @@ fn internalize_symbols<'tcx>(
if !single_codegen_unit {
debug_assert_eq!(mono_item_placements[item], home_cgu);

if let Some(user_items) = cx.usage_map.get_user_items(*item) {
if user_items
.iter()
.filter_map(|user_item| {
// Some user mono items might not have been
// instantiated. We can safely ignore those.
mono_item_placements.get(user_item)
})
.any(|placement| *placement != home_cgu)
{
// Found a user from another CGU, so skip to the next item
// without marking this one as internal.
continue;
}
if cx
.usage_map
.get_user_items(*item)
.iter()
.filter_map(|user_item| {
// Some user mono items might not have been
// instantiated. We can safely ignore those.
mono_item_placements.get(user_item)
})
.any(|placement| *placement != home_cgu)
{
// Found a user from another CGU, so skip to the next item
// without marking this one as internal.
continue;
}
}

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,6 @@ symbols! {
from_desugaring,
from_fn,
from_iter,
from_method,
from_output,
from_residual,
from_size_align_unchecked,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ pub trait TypeErrCtxtExt<'tcx> {
static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
kw::SelfUpper,
sym::ItemContext,
sym::from_method,
sym::from_desugaring,
sym::direct,
sym::cause,
Expand Down Expand Up @@ -172,23 +171,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}

if let ObligationCauseCode::ItemObligation(item)
| ObligationCauseCode::BindingObligation(item, _)
| ObligationCauseCode::ExprItemObligation(item, ..)
| ObligationCauseCode::ExprBindingObligation(item, ..) = *obligation.cause.code()
{
// FIXME: maybe also have some way of handling methods
// from other traits? That would require name resolution,
// which we might want to be some sort of hygienic.
//
// Currently I'm leaving it for what I need for `try`.
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
let method = self.tcx.item_name(item);
flags.push((sym::from_method, None));
flags.push((sym::from_method, Some(method.to_string())));
}
}

if let Some(k) = obligation.cause.span.desugaring_kind() {
flags.push((sym::from_desugaring, None));
flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
Expand Down Expand Up @@ -672,7 +654,7 @@ impl<'tcx> OnUnimplementedFormatString {
None => {
if let Some(val) = options.get(&s) {
val
} else if s == sym::from_desugaring || s == sym::from_method {
} else if s == sym::from_desugaring {
// don't break messages using these two arguments incorrectly
&empty_string
} else if s == sym::ItemContext {
Expand Down
100 changes: 97 additions & 3 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1479,8 +1479,97 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name), kind, cx)
}

/// The goal of this function is to return the first `Path` which is not private (ie not private
/// or `doc(hidden)`). If it's not possible, it'll return the "end type".
///
/// If the path is not a re-export or is public, it'll return `None`.
fn first_non_private(
cx: &mut DocContext<'_>,
hir_id: hir::HirId,
path: &hir::Path<'_>,
) -> Option<Path> {
let (parent_def_id, mut ident) = match &path.segments[..] {
[] => return None,
// Relative paths are available in the same scope as the owner.
[leaf] => (cx.tcx.local_parent(hir_id.owner.def_id), leaf.ident),
// So are self paths.
[parent, leaf] if parent.ident.name == kw::SelfLower => {
(cx.tcx.local_parent(hir_id.owner.def_id), leaf.ident)
}
// Crate paths are not. We start from the crate root.
[parent, leaf] if matches!(parent.ident.name, kw::Crate | kw::PathRoot) => {
(LOCAL_CRATE.as_def_id().as_local()?, leaf.ident)
}
[parent, leaf] if parent.ident.name == kw::Super => {
let parent_mod = cx.tcx.parent_module(hir_id);
if let Some(super_parent) = cx.tcx.opt_local_parent(parent_mod) {
(super_parent, leaf.ident)
} else {
// If we can't find the parent of the parent, then the parent is already the crate.
(LOCAL_CRATE.as_def_id().as_local()?, leaf.ident)
}
}
// Absolute paths are not. We start from the parent of the item.
[.., parent, leaf] => (parent.res.opt_def_id()?.as_local()?, leaf.ident),
};
let target_def_id = path.res.opt_def_id()?;
// First we try to get the `DefId` of the item.
for child in
cx.tcx.module_children_local(parent_def_id).iter().filter(move |c| c.ident == ident)
{
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = child.res {
continue;
}

if let Some(def_id) = child.res.opt_def_id() && target_def_id == def_id {
let mut last_path_res = None;
'reexps: for reexp in child.reexport_chain.iter() {
if let Some(use_def_id) = reexp.id() &&
let Some(local_use_def_id) = use_def_id.as_local()
{
let hir = cx.tcx.hir();
for item_id in hir.module_items(cx.tcx.local_parent(local_use_def_id)) {
let item = hir.item(item_id);
if item.ident == ident && let hir::ItemKind::Use(path, _) = item.kind {
for res in &path.res {
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
continue;
}
if !cx.tcx.is_doc_hidden(use_def_id) &&
cx.tcx.local_visibility(local_use_def_id).is_public() {
break 'reexps;
}
ident = path.segments.last().unwrap().ident;
last_path_res = Some((path, res));
continue 'reexps;
}
}
}
}
}
if !child.reexport_chain.is_empty() {
// So in here, we use the data we gathered from iterating the reexports. If
// `last_path_res` is set, it can mean two things:
//
// 1. We found a public reexport.
// 2. We didn't find a public reexport so it's the "end type" path.
if let Some((path, res)) = last_path_res {
let path = hir::Path { segments: path.segments, res: *res, span: path.span };
return Some(clean_path(&path, cx));
}
// If `last_path_res` is `None`, it can mean two things:
//
// 1. The re-export is public, no need to change anything, just use the path as is.
// 2. Nothing was found, so let's just return the original path.
return None;
}
}
}
None
}

fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
let hir::Ty { hir_id, span, ref kind } = *hir_ty;
let hir::TyKind::Path(qpath) = kind else { unreachable!() };

match qpath {
Expand All @@ -1497,7 +1586,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
expanded
} else {
let path = clean_path(path, cx);
// First we check if it's a private re-export.
let path = if let Some(path) = first_non_private(cx, hir_id, &path) {
path
} else {
clean_path(path, cx)
};
resolve_type(cx, path)
}
}
Expand Down Expand Up @@ -1649,7 +1743,7 @@ fn maybe_expand_private_type_alias<'tcx>(
}
}

Some(cx.enter_alias(substs, def_id.to_def_id(), |cx| clean_ty(ty, cx)))
Some(cx.enter_alias(substs, def_id.to_def_id(), |cx| clean_ty(&ty, cx)))
}

pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type {
Expand Down
2 changes: 1 addition & 1 deletion src/tools/cargo
23 changes: 23 additions & 0 deletions src/tools/miri/tests/fail/overlapping_assignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#![feature(core_intrinsics)]
#![feature(custom_mir)]

use std::intrinsics::mir::*;

// It's not that easy to fool the MIR validity check
// which wants to prevent overlapping assignments...
// So we use two separate pointer arguments, and then arrange for them to alias.
#[custom_mir(dialect = "runtime", phase = "optimized")]
pub fn self_copy(ptr1: *mut [i32; 4], ptr2: *mut [i32; 4]) {
mir! {
{
*ptr1 = *ptr2; //~ERROR: overlapping ranges
Return()
}
}
}

pub fn main() {
let mut x = [0; 4];
let ptr = std::ptr::addr_of_mut!(x);
self_copy(ptr, ptr);
}
20 changes: 20 additions & 0 deletions src/tools/miri/tests/fail/overlapping_assignment.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
--> $DIR/overlapping_assignment.rs:LL:CC
|
LL | *ptr1 = *ptr2;
| ^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `self_copy` at $DIR/overlapping_assignment.rs:LL:CC
note: inside `main`
--> $DIR/overlapping_assignment.rs:LL:CC
|
LL | self_copy(ptr, ptr);
| ^^^^^^^^^^^^^^^^^^^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to previous error

Loading
Loading