Auto merge of #124015 - GuillaumeGomez:rollup-s46ksxa, r=GuillaumeGomez

Rollup of 14 pull requests

Successful merges:

 - #120781 (Correct usage note on OpenOptions::append())
 - #121694 (sess: stabilize `-Zrelro-level` as `-Crelro-level`)
 - #122521 (doc(bootstrap): add top-level doc-comment to utils/tarball.rs)
 - #123491 (Fix ICE in `eval_body_using_ecx`)
 - #123574 (rustdoc: rename `issue-\d+.rs` tests to have meaningful names (part 6))
 - #123687 (Update ar_archive_writer to 0.2.0)
 - #123721 (Various visionOS fixes)
 - #123797 (Better graphviz output for SCCs and NLL constraints)
 - #123990 (Make `suggest_deref_closure_return` more idiomatic/easier to understand)
 - #123995 (Make `thir_tree` and `thir_flat` into hooks)
 - #123998 (Opaque types have no namespace)
 - #124001 (Fix docs for unstable_features lint.)
 - #124006 (Move size assertions for `mir::syntax` types into the same file)
 - #124011 (rustdoc: update the module-level docs of `rustdoc::clean`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-04-16 13:26:03 +00:00
commit 1dea922ea6
63 changed files with 349 additions and 219 deletions

View File

@ -210,9 +210,9 @@ dependencies = [
[[package]]
name = "ar_archive_writer"
version = "0.1.5"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9792d37ca5173d7e7f4fe453739a0671d0557915a030a383d6b866476bbc3e71"
checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a"
dependencies = [
"object 0.32.2",
]

View File

@ -26,7 +26,6 @@ use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_middle::ty::{Region, TyCtxt};
use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
use rustc_trait_selection::infer::type_variable::TypeVariableOrigin;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
@ -813,7 +812,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
self.suggest_move_on_borrowing_closure(&mut diag);
self.suggest_deref_closure_value(&mut diag);
self.suggest_deref_closure_return(&mut diag);
diag
}
@ -1048,115 +1047,107 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// When encountering a lifetime error caused by the return type of a closure, check the
/// corresponding trait bound and see if dereferencing the closure return value would satisfy
/// them. If so, we produce a structured suggestion.
fn suggest_deref_closure_value(&self, diag: &mut Diag<'_>) {
fn suggest_deref_closure_return(&self, diag: &mut Diag<'_>) {
let tcx = self.infcx.tcx;
let map = tcx.hir();
// Get the closure return value and type.
let body_id = map.body_owned_by(self.mir_def_id());
let body = &map.body(body_id);
let value = &body.value.peel_blocks();
let hir::Node::Expr(closure_expr) = tcx.hir_node_by_def_id(self.mir_def_id()) else {
let closure_def_id = self.mir_def_id();
let hir::Node::Expr(
closure_expr @ hir::Expr {
kind: hir::ExprKind::Closure(hir::Closure { body, .. }), ..
},
) = tcx.hir_node_by_def_id(closure_def_id)
else {
return;
};
let fn_call_id = tcx.parent_hir_id(self.mir_hir_id());
let hir::Node::Expr(expr) = tcx.hir_node(fn_call_id) else { return };
let def_id = map.enclosing_body_owner(fn_call_id);
let tables = tcx.typeck(def_id);
let Some(return_value_ty) = tables.node_type_opt(value.hir_id) else { return };
let return_value_ty = self.infcx.resolve_vars_if_possible(return_value_ty);
let ty::Closure(_, args) = *tcx.type_of(closure_def_id).instantiate_identity().kind()
else {
return;
};
let args = args.as_closure();
// Make sure that the parent expression is a method call.
let parent_expr_id = tcx.parent_hir_id(self.mir_hir_id());
let hir::Node::Expr(
parent_expr @ hir::Expr {
kind: hir::ExprKind::MethodCall(_, rcvr, call_args, _), ..
},
) = tcx.hir_node(parent_expr_id)
else {
return;
};
let typeck_results = tcx.typeck(self.mir_def_id());
// We don't use `ty.peel_refs()` to get the number of `*`s needed to get the root type.
let mut ty = return_value_ty;
let liberated_sig = tcx.liberate_late_bound_regions(closure_def_id.to_def_id(), args.sig());
let mut peeled_ty = liberated_sig.output();
let mut count = 0;
while let ty::Ref(_, t, _) = ty.kind() {
ty = *t;
while let ty::Ref(_, ref_ty, _) = *peeled_ty.kind() {
peeled_ty = ref_ty;
count += 1;
}
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty) {
if !self.infcx.type_is_copy_modulo_regions(self.param_env, peeled_ty) {
return;
}
// Build a new closure where the return type is an owned value, instead of a ref.
let Some(ty::Closure(did, args)) =
tables.node_type_opt(closure_expr.hir_id).as_ref().map(|ty| ty.kind())
else {
return;
};
let sig = args.as_closure().sig();
let closure_sig_as_fn_ptr_ty = Ty::new_fn_ptr(
tcx,
sig.map_bound(|s| {
let unsafety = hir::Unsafety::Normal;
use rustc_target::spec::abi;
tcx.mk_fn_sig(
[s.inputs()[0]],
s.output().peel_refs(),
s.c_variadic,
unsafety,
abi::Abi::Rust,
)
}),
ty::Binder::dummy(tcx.mk_fn_sig(
liberated_sig.inputs().iter().copied(),
peeled_ty,
liberated_sig.c_variadic,
hir::Unsafety::Normal,
rustc_target::spec::abi::Abi::Rust,
)),
);
let parent_args = GenericArgs::identity_for_item(
let closure_ty = Ty::new_closure(
tcx,
tcx.typeck_root_def_id(self.mir_def_id().to_def_id()),
closure_def_id.to_def_id(),
ty::ClosureArgs::new(
tcx,
ty::ClosureArgsParts {
parent_args: args.parent_args(),
closure_kind_ty: args.kind_ty(),
tupled_upvars_ty: args.tupled_upvars_ty(),
closure_sig_as_fn_ptr_ty,
},
)
.args,
);
let closure_kind = args.as_closure().kind();
let closure_kind_ty = Ty::from_closure_kind(tcx, closure_kind);
let tupled_upvars_ty = self
.infcx
.next_ty_var(TypeVariableOrigin { param_def_id: None, span: closure_expr.span });
let closure_args = ty::ClosureArgs::new(
tcx,
ty::ClosureArgsParts {
parent_args,
closure_kind_ty,
closure_sig_as_fn_ptr_ty,
tupled_upvars_ty,
},
);
let closure_ty = Ty::new_closure(tcx, *did, closure_args.args);
let closure_ty = tcx.erase_regions(closure_ty);
let hir::ExprKind::MethodCall(_, rcvr, args, _) = expr.kind else { return };
let Some(pos) = args
.iter()
.enumerate()
.find(|(_, arg)| arg.hir_id == closure_expr.hir_id)
.map(|(i, _)| i)
let Some((closure_arg_pos, _)) =
call_args.iter().enumerate().find(|(_, arg)| arg.hir_id == closure_expr.hir_id)
else {
return;
};
// The found `Self` type of the method call.
let Some(possible_rcvr_ty) = tables.node_type_opt(rcvr.hir_id) else { return };
let Some(method_def_id) = tables.type_dependent_def_id(expr.hir_id) else { return };
// Get the type for the parameter corresponding to the argument the closure with the
// lifetime error we had.
let Some(input) = tcx
let Some(method_def_id) = typeck_results.type_dependent_def_id(parent_expr.hir_id) else {
return;
};
let Some(input_arg) = tcx
.fn_sig(method_def_id)
.instantiate_identity()
.skip_binder()
.inputs()
.skip_binder()
// Methods have a `self` arg, so `pos` is actually `+ 1` to match the method call arg.
.get(pos + 1)
.get(closure_arg_pos + 1)
else {
return;
};
trace!(?input);
let ty::Param(closure_param) = input.kind() else { return };
// If this isn't a param, then we can't substitute a new closure.
let ty::Param(closure_param) = input_arg.kind() else { return };
// Get the arguments for the found method, only specifying that `Self` is the receiver type.
let Some(possible_rcvr_ty) = typeck_results.node_type_opt(rcvr.hir_id) else { return };
let args = GenericArgs::for_item(tcx, method_def_id, |param, _| {
if param.index == 0 {
possible_rcvr_ty.into()
} else if param.index == closure_param.index {
closure_ty.into()
} else {
self.infcx.var_for_def(expr.span, param)
self.infcx.var_for_def(parent_expr.span, param)
}
});
@ -1170,7 +1161,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if ocx.select_all_or_error().is_empty() {
diag.span_suggestion_verbose(
value.span.shrink_to_lo(),
tcx.hir().body(*body).value.peel_blocks().span.shrink_to_lo(),
"dereference the return value",
"*".repeat(count),
Applicability::MachineApplicable,

View File

@ -6,7 +6,38 @@ use std::borrow::Cow;
use std::io::{self, Write};
use super::*;
use itertools::Itertools;
use rustc_graphviz as dot;
use rustc_middle::ty::UniverseIndex;
fn render_outlives_constraint(constraint: &OutlivesConstraint<'_>) -> String {
match constraint.locations {
Locations::All(_) => "All(...)".to_string(),
Locations::Single(loc) => format!("{loc:?}"),
}
}
fn render_universe(u: UniverseIndex) -> String {
if u.is_root() {
return "".to_string();
}
format!("/{:?}", u)
}
fn render_region_vid(rvid: RegionVid, regioncx: &RegionInferenceContext<'_>) -> String {
let universe_str = render_universe(regioncx.region_definition(rvid).universe);
let external_name_str = if let Some(external_name) =
regioncx.region_definition(rvid).external_name.and_then(|e| e.get_name())
{
format!(" ({external_name})")
} else {
"".to_string()
};
format!("{:?}{universe_str}{external_name_str}", rvid)
}
impl<'tcx> RegionInferenceContext<'tcx> {
/// Write out the region constraint graph.
@ -46,10 +77,10 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
}
fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
dot::LabelText::LabelStr(format!("{n:?}").into())
dot::LabelText::LabelStr(render_region_vid(*n, self.regioncx).into())
}
fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> {
dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
dot::LabelText::LabelStr(render_outlives_constraint(e).into())
}
}
@ -96,8 +127,9 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> {
Some(dot::LabelText::LabelStr(Cow::Borrowed("box")))
}
fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> {
let nodes = &self.nodes_per_scc[*n];
dot::LabelText::LabelStr(format!("{n:?} = {nodes:?}").into())
let nodes_str =
self.nodes_per_scc[*n].iter().map(|n| render_region_vid(*n, self.regioncx)).join(", ");
dot::LabelText::LabelStr(format!("SCC({n}) = {{{nodes_str}}}", n = n.as_usize()).into())
}
}

View File

@ -1562,7 +1562,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Because this free region must be in the ROOT universe, we
// know it cannot contain any bound universes.
assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
assert!(self.scc_universes[longer_fr_scc].is_root());
debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
// Only check all of the relations for the main representative of each

View File

@ -213,7 +213,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let scc = self.constraint_sccs.scc(vid);
// Special handling of higher-ranked regions.
if self.scc_universes[scc] != ty::UniverseIndex::ROOT {
if !self.scc_universes[scc].is_root() {
match self.scc_values.placeholders_contained_in(scc).enumerate().last() {
// If the region contains a single placeholder then they're equal.
Some((0, placeholder)) => {

View File

@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
# tidy-alphabetical-start
ar_archive_writer = "0.1.5"
ar_archive_writer = "0.2.0"
bitflags = "2.4.1"
cc = "1.0.90"
itertools = "0.12"

View File

@ -285,14 +285,7 @@ impl<'a> ArArchiveBuilder<'a> {
.tempfile_in(output.parent().unwrap_or_else(|| Path::new("")))
.map_err(|err| io_error_context("couldn't create a temp file", err))?;
write_archive_to_stream(
archive_tmpfile.as_file_mut(),
&entries,
true,
archive_kind,
true,
false,
)?;
write_archive_to_stream(archive_tmpfile.as_file_mut(), &entries, archive_kind, false)?;
let any_entries = !entries.is_empty();
drop(entries);

View File

@ -2059,7 +2059,7 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained:
/// Add options making relocation sections in the produced ELF files read-only
/// and suppressing lazy binding.
fn add_relro_args(cmd: &mut dyn Linker, sess: &Session) {
match sess.opts.unstable_opts.relro_level.unwrap_or(sess.target.relro_level) {
match sess.opts.cg.relro_level.unwrap_or(sess.target.relro_level) {
RelroLevel::Full => cmd.full_relro(),
RelroLevel::Partial => cmd.partial_relro(),
RelroLevel::Off => cmd.no_relro(),
@ -3038,9 +3038,10 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootErro
|| sdkroot.contains("MacOSX.platform") => {}
"watchsimulator"
if sdkroot.contains("WatchOS.platform") || sdkroot.contains("MacOSX.platform") => {}
"visionos"
if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
"visionossimulator"
"xros"
if sdkroot.contains("XRSimulator.platform")
|| sdkroot.contains("MacOSX.platform") => {}
"xrsimulator"
if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
// Ignore `SDKROOT` if it's not a valid path.
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}

View File

@ -207,7 +207,6 @@ impl DefKind {
| DefKind::Enum
| DefKind::Variant
| DefKind::Trait
| DefKind::OpaqueTy
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::TraitAlias
@ -234,7 +233,8 @@ impl DefKind {
| DefKind::Use
| DefKind::ForeignMod
| DefKind::GlobalAsm
| DefKind::Impl { .. } => None,
| DefKind::Impl { .. }
| DefKind::OpaqueTy => None,
}
}

View File

@ -624,6 +624,7 @@ fn test_codegen_options_tracking_hash() {
tracked!(profile_generate, SwitchWithOptPath::Enabled(None));
tracked!(profile_use, Some(PathBuf::from("abc")));
tracked!(relocation_model, Some(RelocModel::Pic));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(soft_float, true);
tracked!(split_debuginfo, Some(SplitDebuginfo::Packed));
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
@ -822,7 +823,6 @@ fn test_unstable_options_tracking_hash() {
tracked!(profile_sample_use, Some(PathBuf::from("abc")));
tracked!(profiler_runtime, "abc".to_string());
tracked!(relax_elf_relocations, Some(true));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
tracked!(sanitizer, SanitizerSet::ADDRESS);
tracked!(sanitizer_cfi_canonical_jump_tables, None);

View File

@ -102,4 +102,10 @@ declare_hooks! {
/// turn a deserialized `DefPathHash` into its current `DefId`.
/// Will fetch a DefId from a DefPathHash for a foreign crate.
hook def_path_hash_to_def_id_extern(hash: DefPathHash, stable_crate_id: StableCrateId) -> DefId;
/// Create a THIR tree for debugging.
hook thir_tree(key: LocalDefId) -> String;
/// Create a list-like THIR representation for debugging.
hook thir_flat(key: LocalDefId) -> String;
}

View File

@ -1823,9 +1823,7 @@ mod size_asserts {
static_assert_size!(LocalDecl<'_>, 40);
static_assert_size!(SourceScopeData<'_>, 64);
static_assert_size!(Statement<'_>, 32);
static_assert_size!(StatementKind<'_>, 16);
static_assert_size!(Terminator<'_>, 112);
static_assert_size!(TerminatorKind<'_>, 96);
static_assert_size!(VarDebugInfo<'_>, 88);
// tidy-alphabetical-end
}

View File

@ -1463,5 +1463,6 @@ mod size_asserts {
static_assert_size!(PlaceElem<'_>, 24);
static_assert_size!(Rvalue<'_>, 40);
static_assert_size!(StatementKind<'_>, 16);
static_assert_size!(TerminatorKind<'_>, 96);
// tidy-alphabetical-end
}

View File

@ -474,20 +474,6 @@ rustc_queries! {
desc { |tcx| "building THIR for `{}`", tcx.def_path_str(key) }
}
/// Create a THIR tree for debugging.
query thir_tree(key: LocalDefId) -> &'tcx String {
no_hash
arena_cache
desc { |tcx| "constructing THIR tree for `{}`", tcx.def_path_str(key) }
}
/// Create a list-like THIR representation for debugging.
query thir_flat(key: LocalDefId) -> &'tcx String {
no_hash
arena_cache
desc { |tcx| "constructing flat THIR representation for `{}`", tcx.def_path_str(key) }
}
/// Set of all the `DefId`s in this crate that have MIR associated with
/// them. This includes all the body owners, but also things like struct
/// constructors.

View File

@ -34,6 +34,6 @@ pub fn provide(providers: &mut Providers) {
build::closure_saved_names_of_captured_variables;
providers.check_unsafety = check_unsafety::check_unsafety;
providers.thir_body = thir::cx::thir_body;
providers.thir_tree = thir::print::thir_tree;
providers.thir_flat = thir::print::thir_flat;
providers.hooks.thir_tree = thir::print::thir_tree;
providers.hooks.thir_flat = thir::print::thir_flat;
}

View File

@ -1,10 +1,11 @@
use rustc_middle::query::TyCtxtAt;
use rustc_middle::thir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty;
use rustc_span::def_id::LocalDefId;
use std::fmt::{self, Write};
pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(tcx, owner_def) {
pub(crate) fn thir_tree(tcx: TyCtxtAt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(*tcx, owner_def) {
Ok((thir, _)) => {
let thir = thir.steal();
let mut printer = ThirPrinter::new(&thir);
@ -15,8 +16,8 @@ pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
}
}
pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(tcx, owner_def) {
pub(crate) fn thir_flat(tcx: TyCtxtAt<'_>, owner_def: LocalDefId) -> String {
match super::cx::thir_body(*tcx, owner_def) {
Ok((thir, _)) => format!("{:#?}", thir.steal()),
Err(_) => "error".into(),
}

View File

@ -1534,6 +1534,8 @@ options! {
relocation_model: Option<RelocModel> = (None, parse_relocation_model, [TRACKED],
"control generation of position-independent code (PIC) \
(`rustc --print relocation-models` for details)"),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
"choose which RELRO level to use"),
remark: Passes = (Passes::Some(Vec::new()), parse_passes, [UNTRACKED],
"output remarks for these optimization passes (space separated, or \"all\")"),
rpath: bool = (false, parse_bool, [UNTRACKED],
@ -1881,8 +1883,6 @@ options! {
"randomize the layout of types (default: no)"),
relax_elf_relocations: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether ELF relocations can be relaxed"),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
"choose which RELRO level to use"),
remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"remap paths under the current working directory to this path prefix"),
remap_path_scope: RemapPathScopeComponents = (RemapPathScopeComponents::all(), parse_remap_path_scope, [TRACKED],

View File

@ -573,7 +573,7 @@ impl Session {
let dbg_opts = &self.opts.unstable_opts;
let relro_level = dbg_opts.relro_level.unwrap_or(self.target.relro_level);
let relro_level = self.opts.cg.relro_level.unwrap_or(self.target.relro_level);
// Only enable this optimization by default if full relro is also enabled.
// In this case, lazy binding was already unavailable, so nothing is lost.

View File

@ -298,6 +298,7 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> {
|| sdkroot.contains("WatchOS.platform")
|| sdkroot.contains("WatchSimulator.platform")
|| sdkroot.contains("XROS.platform")
|| sdkroot.contains("XRSimulator.platform")
{
env_remove.push("SDKROOT".into())
}

View File

@ -984,7 +984,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
// Already reported in the query.
SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(guar)) |
// Already reported.
Overflow(OverflowError::Error(guar)) => return guar,
Overflow(OverflowError::Error(guar)) => {
self.set_tainted_by_errors(guar);
return guar
},
Overflow(_) => {
bug!("overflow should be handled before the `report_selection_error` path");

View File

@ -87,6 +87,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} else if lang_items.sized_trait() == Some(def_id) {
// Sized is never implementable by end-users, it is
// always automatically computed.
// FIXME: Consider moving this check to the top level as it
// may also be useful for predicates other than `Sized`
// Error type cannot possibly implement `Sized` (fixes #123154)
if let Err(e) = obligation.predicate.skip_binder().self_ty().error_reported() {
return Err(SelectionError::Overflow(e.into()));
}
let sized_conditions = self.sized_conditions(obligation);
self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
} else if lang_items.unsize_trait() == Some(def_id) {

View File

@ -91,8 +91,8 @@ fn adt_sized_constraint<'tcx>(
let tail_ty = tcx.type_of(tail_def.did).instantiate_identity();
let constraint_ty = sized_constraint_for_ty(tcx, tail_ty)?;
if constraint_ty.references_error() {
return None;
if let Err(guar) = constraint_ty.error_reported() {
return Some(ty::EarlyBinder::bind(Ty::new_error(tcx, guar)));
}
// perf hack: if there is a `constraint_ty: Sized` bound, then we know

View File

@ -346,6 +346,11 @@ impl UniverseIndex {
pub fn cannot_name(self, other: UniverseIndex) -> bool {
self < other
}
/// Returns `true` if `self` is the root universe, otherwise false.
pub fn is_root(self) -> bool {
self == Self::ROOT
}
}
impl Default for UniverseIndex {

View File

@ -980,15 +980,21 @@ impl OpenOptions {
/// Note that setting `.write(true).append(true)` has the same effect as
/// setting only `.append(true)`.
///
/// For most filesystems, the operating system guarantees that all writes are
/// atomic: no writes get mangled because another process writes at the same
/// time.
/// Append mode guarantees that writes will be positioned at the current end of file,
/// even when there are other processes or threads appending to the same file. This is
/// unlike <code>[seek]\([SeekFrom]::[End]\(0))</code> followed by `write()`, which
/// has a race between seeking and writing during which another writer can write, with
/// our `write()` overwriting their data.
///
/// One maybe obvious note when using append-mode: make sure that all data
/// that belongs together is written to the file in one operation. This
/// can be done by concatenating strings before passing them to [`write()`],
/// or using a buffered writer (with a buffer of adequate size),
/// and calling [`flush()`] when the message is complete.
/// Keep in mind that this does not necessarily guarantee that data appended by
/// different processes or threads does not interleave. The amount of data accepted a
/// single `write()` call depends on the operating system and file system. A
/// successful `write()` is allowed to write only part of the given data, so even if
/// you're careful to provide the whole message in a single call to `write()`, there
/// is no guarantee that it will be written out in full. If you rely on the filesystem
/// accepting the message in a single write, make sure that all data that belongs
/// together is written in one operation. This can be done by concatenating strings
/// before passing them to [`write()`].
///
/// If a file is opened with both read and append access, beware that after
/// opening, and after every write, the position for reading may be set at the
@ -1003,6 +1009,9 @@ impl OpenOptions {
/// [`write()`]: Write::write "io::Write::write"
/// [`flush()`]: Write::flush "io::Write::flush"
/// [stream_position]: Seek::stream_position "io::Seek::stream_position"
/// [seek]: Seek::seek "io::Seek::seek"
/// [Current]: SeekFrom::Current "io::SeekFrom::Current"
/// [End]: SeekFrom::End "io::SeekFrom::End"
///
/// # Examples
///

View File

@ -11,18 +11,6 @@ use crate::os::linux::process::PidFd;
#[cfg(target_os = "linux")]
use crate::os::unix::io::AsRawFd;
#[cfg(any(
target_os = "macos",
target_os = "watchos",
target_os = "visionos",
target_os = "tvos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
target_os = "nto",
))]
use crate::sys::weak::weak;
#[cfg(target_os = "vxworks")]
use libc::RTP_ID as pid_t;
@ -466,6 +454,7 @@ impl Command {
envp: Option<&CStringArray>,
) -> io::Result<Option<Process>> {
use crate::mem::MaybeUninit;
use crate::sys::weak::weak;
use crate::sys::{self, cvt_nz, unix_sigpipe_attr_specified};
if self.get_gid().is_some()

View File

@ -1,3 +1,10 @@
//! Facilitates the management and generation of tarballs.
//!
//! Tarballs efficiently hold Rust compiler build artifacts and
//! capture a snapshot of each boostrap stage.
//! In uplifting, a tarball from Stage N captures essential components
//! to assemble Stage N + 1 compiler.
use std::{
path::{Path, PathBuf},
process::Command,

View File

@ -479,6 +479,26 @@ then `-C target-feature=+crt-static` "wins" over `-C relocation-model=pic`,
and the linker is instructed (`-static`) to produce a statically linked
but not position-independent executable.
## relro-level
This flag controls what level of RELRO (Relocation Read-Only) is enabled. RELRO is an exploit
mitigation which makes the Global Offset Table (GOT) read-only.
Supported values for this option are:
- `off`: Dynamically linked functions are resolved lazily and the GOT is writable.
- `partial`: Dynamically linked functions are resolved lazily and written into the Procedure
Linking Table (PLT) part of the GOT (`.got.plt`). The non-PLT part of the GOT (`.got`) is made
read-only and both are moved to prevent writing from buffer overflows.
- `full`: Dynamically linked functions are resolved at the start of program execution and the
Global Offset Table (`.got`/`.got.plt`) is populated eagerly and then made read-only. The GOT is
also moved to prevent writing from buffer overflows. Full RELRO uses more memory and increases
process startup time.
This flag is ignored on platforms where RELRO is not supported (targets which do not use the ELF
binary format), such as Windows or macOS. Each rustc target has its own default for RELRO. rustc
enables Full RELRO by default on platforms where it is supported.
## remark
This flag lets you print remarks for optimization passes.

View File

@ -1,5 +1,25 @@
//! This module contains the "cleaned" pieces of the AST, and the functions
//! that clean them.
//! This module defines the primary IR[^1] used in rustdoc together with the procedures that
//! transform rustc data types into it.
//!
//! This IR — commonly referred to as the *cleaned AST* — is modeled after the [AST][ast].
//!
//! There are two kinds of transformation — *cleaning* — procedures:
//!
//! 1. Cleans [HIR][hir] types. Used for user-written code and inlined local re-exports
//! both found in the local crate.
//! 2. Cleans [`rustc_middle::ty`] types. Used for inlined cross-crate re-exports and anything
//! output by the trait solver (e.g., when synthesizing blanket and auto-trait impls).
//! They usually have `ty` or `middle` in their name.
//!
//! Their name is prefixed by `clean_`.
//!
//! Both the HIR and the `rustc_middle::ty` IR are quite removed from the source code.
//! The cleaned AST on the other hand is closer to it which simplifies the rendering process.
//! Furthermore, operating on a single IR instead of two avoids duplicating efforts down the line.
//!
//! This IR is consumed by both the HTML and the JSON backend.
//!
//! [^1]: Intermediate representation.
mod auto_trait;
mod blanket_impl;

View File

@ -270,7 +270,6 @@ impl<'a> LintExtractor<'a> {
if matches!(
lint.name.as_str(),
"unused_features" // broken lint
| "unstable_features" // deprecated
) {
return Ok(());
}

View File

@ -1,12 +0,0 @@
//@ known-bug: #123154
struct AA {
pub data: [&usize]
}
impl AA {
const fn new() -> Self { }
}
static AA = AA::new();
fn main() { }

View File

@ -3,20 +3,20 @@ include ../tools.mk
# only-linux
#
# This tests the different -Zrelro-level values, and makes sure that they work properly.
# This tests the different -Crelro-level values, and makes sure that they work properly.
all:
# Ensure that binaries built with the full relro level links them with both
# RELRO and BIND_NOW for doing eager symbol resolving.
$(RUSTC) -Zrelro-level=full hello.rs
$(RUSTC) -Crelro-level=full hello.rs
readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO
readelf -d $(TMPDIR)/hello | grep -q BIND_NOW
$(RUSTC) -Zrelro-level=partial hello.rs
$(RUSTC) -Crelro-level=partial hello.rs
readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO
# Ensure that we're *not* built with RELRO when setting it to off. We do
# not want to check for BIND_NOW however, as the linker might have that
# enabled by default.
$(RUSTC) -Zrelro-level=off hello.rs
$(RUSTC) -Crelro-level=off hello.rs
! readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO

View File

@ -1,4 +1,6 @@
//@ check-pass
// This shouldn't cause a stack overflow when rustdoc is run
// https://github.com/rust-lang/rust/issues/56701
use std::ops::Deref;
use std::ops::DerefMut;

View File

@ -1,5 +1,6 @@
// Regression test for ICE #73061
// Regression test for ICE https://github.com/rust-lang/rust/issues/73061
//@ check-pass
//@ aux-build:issue-73061.rs
extern crate issue_73061;

View File

@ -1,3 +1,4 @@
// https://github.com/rust-lang/rust/issues/78673
#![crate_name = "issue_78673"]
pub trait Something {}

View File

@ -1,4 +1,7 @@
// @has 'issue_76501/fn.bloop.html' '//pre' 'pub const fn bloop() -> i32'
// https://github.com/rust-lang/rust/issues/76501
#![crate_name="foo"]
// @has 'foo/fn.bloop.html' '//pre' 'pub const fn bloop() -> i32'
/// A useless function that always returns 1.
pub const fn bloop() -> i32 {
1
@ -8,7 +11,7 @@ pub const fn bloop() -> i32 {
pub struct Struct {}
impl Struct {
// @has 'issue_76501/struct.Struct.html' '//*[@class="method"]' \
// @has 'foo/struct.Struct.html' '//*[@class="method"]' \
// 'pub const fn blurp() -> i32'
/// A useless function that always returns 1.
pub const fn blurp() -> i32 {

View File

@ -1,6 +1,9 @@
// https://github.com/rust-lang/rust/issues/79201
#![crate_name="foo"]
#![feature(doc_cfg)]
// @has 'issue_79201/trait.Foo.html'
// @has 'foo/trait.Foo.html'
// @count - '//*[@class="stab portability"]' 6
// @matches - '//*[@class="stab portability"]' 'crate feature foo-root'
// @matches - '//*[@class="stab portability"]' 'crate feature foo-public-mod'

View File

@ -1,8 +1,10 @@
//@ compile-flags: -Zunstable-options --document-private-items --document-hidden-items
// https://github.com/rust-lang/rust/issues/67851
#![crate_name="foo"]
// @has issue_67851_both/struct.Hidden.html
// @has foo/struct.Hidden.html
#[doc(hidden)]
pub struct Hidden;
// @has issue_67851_both/struct.Private.html
// @has foo/struct.Private.html
struct Private;

View File

@ -0,0 +1,10 @@
//@ compile-flags: -Zunstable-options --document-hidden-items
// https://github.com/rust-lang/rust/issues/67851
#![crate_name="foo"]
// @has foo/struct.Hidden.html
#[doc(hidden)]
pub struct Hidden;
// @!has foo/struct.Private.html
struct Private;

View File

@ -0,0 +1,9 @@
// https://github.com/rust-lang/rust/issues/67851
#![crate_name="foo"]
// @!has foo/struct.Hidden.html
#[doc(hidden)]
pub struct Hidden;
// @!has foo/struct.Private.html
struct Private;

View File

@ -0,0 +1,10 @@
//@ compile-flags: --document-private-items
// https://github.com/rust-lang/rust/issues/67851
#![crate_name="foo"]
// @!has foo/struct.Hidden.html
#[doc(hidden)]
pub struct Hidden;
// @has foo/struct.Private.html
struct Private;

View File

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/issues/74083
#![crate_name="foo"]
use std::ops::Deref;
pub struct Foo;
@ -6,7 +9,7 @@ impl Foo {
pub fn foo(&mut self) {}
}
// @has issue_74083/struct.Bar.html
// @has foo/struct.Bar.html
// @!has - '//div[@class="sidebar-links"]/a[@href="#method.foo"]' 'foo'
pub struct Bar {
foo: Foo,

View File

@ -2,6 +2,7 @@
//@ aux-build:real_gimli.rs
// Ensure unstably exported traits have their Implementors sections.
// https://github.com/rust-lang/rust/issues/75588
#![crate_name = "foo"]
#![feature(extremely_unstable_foo)]

View File

@ -1,4 +1,5 @@
//@ aux-build:issue-57180.rs
// https://github.com/rust-lang/rust/issues/57180
extern crate issue_57180;
use issue_57180::Trait;

View File

@ -1,3 +1,5 @@
// https://github.com/rust-lang/rust/issues/72340
#![crate_name = "foo"]
pub struct Body;

View File

@ -1,8 +0,0 @@
//@ compile-flags: -Zunstable-options --document-hidden-items
// @has issue_67851_hidden/struct.Hidden.html
#[doc(hidden)]
pub struct Hidden;
// @!has issue_67851_hidden/struct.Private.html
struct Private;

View File

@ -1,6 +0,0 @@
// @!has issue_67851_neither/struct.Hidden.html
#[doc(hidden)]
pub struct Hidden;
// @!has issue_67851_neither/struct.Private.html
struct Private;

View File

@ -1,8 +0,0 @@
//@ compile-flags: --document-private-items
// @!has issue_67851_private/struct.Hidden.html
#[doc(hidden)]
pub struct Hidden;
// @has issue_67851_private/struct.Private.html
struct Private;

View File

@ -1,4 +1,5 @@
// This code caused a panic in `pulldown-cmark` 0.4.1.
// https://github.com/rust-lang/rust/issues/60482
pub const BASIC_UNICODE: bool = true;

View File

@ -1,3 +1,4 @@
// https://github.com/rust-lang/rust/issues/78701
#![crate_name = "foo"]
// This test ensures that if a blanket impl has the same ID as another impl, it'll

View File

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/issues/56822
#![crate_name="foo"]
struct Wrapper<T>(T);
trait MyTrait {
@ -16,7 +19,7 @@ impl<'a, T> MyTrait for Inner<'a, T> {
type Output = &'a T;
}
// @has issue_56822/struct.Parser.html
// @has foo/struct.Parser.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<'a> Send for Parser<'a>"
pub struct Parser<'a> {

View File

@ -1,3 +1,6 @@
// https://github.com/rust-lang/rust/issues/60726
#![crate_name="foo"]
use std::marker::PhantomData;
pub struct True;
@ -25,7 +28,7 @@ where
I:InterfaceType<Send=True>
{}
// @has issue_60726/struct.IntoIter.html
// @has foo/struct.IntoIter.html
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \
// "impl<T> !Send for IntoIter<T>"
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//h3[@class="code-header"]' \

View File

@ -1,14 +1,16 @@
//@ aux-build:issue-61592.rs
// https://github.com/rust-lang/rust/issues/61592
#![crate_name="bar"]
extern crate foo;
// @has issue_61592/index.html
// @has bar/index.html
// @has - '//a[@href="#reexports"]' 'Re-exports'
// @has - '//code' 'pub use foo::FooTrait as _;'
// @!has - '//a[@href="trait._.html"]' ''
pub use foo::FooTrait as _;
// @has issue_61592/index.html
// @has bar/index.html
// @has - '//a[@href="#reexports"]' 'Re-exports'
// @has - '//code' 'pub use foo::FooStruct as _;'
// @!has - '//a[@href="struct._.html"]' ''

View File

@ -1,6 +1,5 @@
fn server() -> impl {
//~^ ERROR at least one trait must be specified
//~| ERROR type annotations needed
().map2(|| "")
}

View File

@ -5,7 +5,7 @@ LL | fn server() -> impl {
| ^^^^
error[E0412]: cannot find type `F` in this scope
--> $DIR/issue-78720.rs:14:12
--> $DIR/issue-78720.rs:13:12
|
LL | _func: F,
| ^
@ -22,14 +22,8 @@ help: you might be missing a type parameter
LL | struct Map2<Segment2, F> {
| +++
error[E0282]: type annotations needed
--> $DIR/issue-78720.rs:1:16
|
LL | fn server() -> impl {
| ^^^^ cannot infer type
error[E0308]: mismatched types
--> $DIR/issue-78720.rs:8:39
--> $DIR/issue-78720.rs:7:39
|
LL | fn map2<F>(self, f: F) -> Map2<F> {}
| ^^ expected `Map2<F>`, found `()`
@ -38,7 +32,7 @@ LL | fn map2<F>(self, f: F) -> Map2<F> {}
found unit type `()`
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/issue-78720.rs:8:16
--> $DIR/issue-78720.rs:7:16
|
LL | fn map2<F>(self, f: F) -> Map2<F> {}
| ^^^^ doesn't have a size known at compile-time
@ -53,7 +47,7 @@ help: function arguments must have a statically known size, borrowed types alway
LL | fn map2<F>(&self, f: F) -> Map2<F> {}
| +
error: aborting due to 5 previous errors
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0277, E0282, E0308, E0412.
Some errors have detailed explanations: E0277, E0308, E0412.
For more information about an error, try `rustc --explain E0277`.

View File

@ -13,7 +13,6 @@ impl Opcode2 {
pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
move |i| match msg_type {
Opcode2::OP2 => unimplemented!(),
//~^ ERROR could not evaluate constant pattern
}
}

View File

@ -17,13 +17,7 @@ help: you might be missing a type parameter
LL | pub struct Opcode2<S>(&'a S);
| +++
error: could not evaluate constant pattern
--> $DIR/ice-type-mismatch-when-copying-112824.rs:15:9
|
LL | Opcode2::OP2 => unimplemented!(),
| ^^^^^^^^^^^^
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0261, E0412.
For more information about an error, try `rustc --explain E0261`.

View File

@ -0,0 +1,15 @@
// Regression test for #123154
struct AA {
pub data: [&usize]
//~^ ERROR missing lifetime specifier
}
impl AA {
const fn new() -> Self { }
//~^ ERROR mismatched types
}
static ST: AA = AA::new();
fn main() {}

View File

@ -0,0 +1,24 @@
error[E0106]: missing lifetime specifier
--> $DIR/ice-unsized-struct-const-eval-123154.rs:4:16
|
LL | pub data: [&usize]
| ^ expected named lifetime parameter
|
help: consider introducing a named lifetime parameter
|
LL ~ struct AA<'a> {
LL ~ pub data: [&'a usize]
|
error[E0308]: mismatched types
--> $DIR/ice-unsized-struct-const-eval-123154.rs:9:23
|
LL | const fn new() -> Self { }
| --- ^^^^ expected `AA`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0106, E0308.
For more information about an error, try `rustc --explain E0106`.

View File

@ -17,6 +17,7 @@ impl<T, D> MyTrait<T> for D {
}
impl<T> MyTrait<T> for BadStruct {
//~^ ERROR: conflicting implementations of trait `MyTrait<_>` for type `BadStruct`
fn foo() {}
}

View File

@ -4,6 +4,16 @@ error[E0412]: cannot find type `MissingType` in this scope
LL | err: MissingType
| ^^^^^^^^^^^ not found in this scope
error: aborting due to 1 previous error
error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `BadStruct`
--> $DIR/issue-68830-spurious-diagnostics.rs:19:1
|
LL | impl<T, D> MyTrait<T> for D {
| --------------------------- first implementation here
...
LL | impl<T> MyTrait<T> for BadStruct {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `BadStruct`
For more information about this error, try `rustc --explain E0412`.
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0119, E0412.
For more information about an error, try `rustc --explain E0119`.