1
Fork 0

Auto merge of #100963 - matthiaskrgr:rollup-pjr0lb3, r=matthiaskrgr

Rollup of 15 pull requests

Successful merges:

 - #99993 (linker: Update some outdated comments)
 - #100220 (Properly forward `ByRefSized::fold` to the inner iterator)
 - #100826 (sugg: take into count the debug formatting)
 - #100855 (Extra documentation for new formatting feature)
 - #100888 (Coherence negative impls implied bounds)
 - #100901 (Make some methods private)
 - #100906 (Suggest alternatives when trying to mutate a `HashMap`/`BTreeMap` via indexing)
 - #100912 (Diagnose missing includes in run-make tests)
 - #100919 (Use par_body_owners for liveness)
 - #100922 (Rewrite error index generator to greatly reduce the size of the pages)
 - #100926 (Update README.md)
 - #100930 (Use `--userns=keep-id` when "docker" is really podman)
 - #100938 (rustdoc: remove unused CSS rule)
 - #100940 (Do not suggest adding a bound to a opaque type)
 - #100945 (Add a missing test case for impl generic mismatch)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2022-08-24 19:54:22 +00:00
commit addacb5878
321 changed files with 812 additions and 729 deletions

View file

@ -273,13 +273,17 @@ impl<'tcx> BorrowExplanation<'tcx> {
_ => {}
}
}
pub(crate) fn add_lifetime_bound_suggestion_to_diagnostic(
fn add_lifetime_bound_suggestion_to_diagnostic(
&self,
err: &mut Diagnostic,
category: &ConstraintCategory<'tcx>,
span: Span,
region_name: &RegionName,
) {
if !span.is_desugaring(DesugaringKind::OpaqueTy) {
return;
}
if let ConstraintCategory::OpaqueType = category {
let suggestable_name =
if region_name.was_named() { region_name.name } else { kw::UnderscoreLifetime };

View file

@ -1,3 +1,4 @@
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::Node;
use rustc_middle::hir::map::Map;
@ -12,12 +13,11 @@ use rustc_middle::{
};
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{BytePos, Span};
use rustc_span::{sym, BytePos, Span};
use crate::diagnostics::BorrowedContentSource;
use crate::MirBorrowckCtxt;
use rustc_const_eval::util::collect_writes::FindAssignments;
use rustc_errors::{Applicability, Diagnostic};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum AccessKind {
@ -614,6 +614,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
"trait `IndexMut` is required to modify indexed content, \
but it is not implemented for `{ty}`",
));
self.suggest_map_index_mut_alternatives(ty, &mut err);
}
_ => (),
}
@ -627,6 +628,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
self.buffer_error(err);
}
fn suggest_map_index_mut_alternatives(
&self,
ty: Ty<'_>,
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
) {
let Some(adt) = ty.ty_adt_def() else { return };
let did = adt.did();
if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did)
|| self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did)
{
err.help(format!("to modify a `{ty}`, use `.get_mut()`, `.insert()` or the entry API"));
}
}
/// User cannot make signature of a trait mutable without changing the
/// trait. So we find if this error belongs to a trait and if so we move
/// suggestion to the trait or disable it if it is out of scope of this crate

View file

@ -1958,7 +1958,6 @@ fn linker_with_args<'a>(
// Upstream rust libraries are not supposed to depend on our local native
// libraries as that would violate the structure of the DAG, in that
// scenario they are required to link to them as well in a shared fashion.
// (The current implementation still doesn't prevent it though, see the FIXME below.)
//
// Note that upstream rust libraries may contain native dependencies as
// well, but they also can't depend on what we just started to add to the
@ -1979,15 +1978,16 @@ fn linker_with_args<'a>(
// and move this option back to the top.
cmd.add_as_needed();
// FIXME: Move this below to other native libraries
// (or alternatively link all native libraries after their respective crates).
// This change is somewhat breaking in practice due to local static libraries being linked
// as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
// Local native libraries of all kinds.
//
// If `-Zlink-native-libraries=false` is set, then the assumption is that an
// external build system already has the native dependencies defined, and it
// will provide them to the linker itself.
if sess.opts.unstable_opts.link_native_libraries {
add_local_native_libraries(cmd, sess, codegen_results);
}
// Upstream rust libraries and their non-bundled static libraries
// Upstream rust libraries and their (possibly bundled) static native libraries.
add_upstream_rust_crates(
cmd,
sess,
@ -1997,11 +1997,11 @@ fn linker_with_args<'a>(
tmpdir,
);
// Upstream dynamic native libraries linked with `#[link]` attributes at and `-l`
// command line options.
// If -Zlink-native-libraries=false is set, then the assumption is that an
// external build system already has the native dependencies defined, and it
// will provide them to the linker itself.
// Dynamic native libraries from upstream crates.
//
// FIXME: Merge this to `add_upstream_rust_crates` so that all native libraries are linked
// together with their respective upstream crates, and in their originally specified order.
// This may be slightly breaking due to our use of `--as-needed` and needs a crater run.
if sess.opts.unstable_opts.link_native_libraries {
add_upstream_native_libraries(cmd, sess, codegen_results);
}
@ -2415,7 +2415,7 @@ fn add_upstream_rust_crates<'a>(
// or is an rlib already included via some other dylib crate, the symbols from
// native libs will have already been included in that dylib.
//
// If -Zlink-native-libraries=false is set, then the assumption is that an
// If `-Zlink-native-libraries=false` is set, then the assumption is that an
// external build system already has the native dependencies defined, and it
// will provide them to the linker itself.
if sess.opts.unstable_opts.link_native_libraries {

View file

@ -187,12 +187,12 @@ pub enum MetadataPosition {
Last,
}
// For rlibs we "pack" rustc metadata into a dummy object file. When rustc
// creates a dylib crate type it will pass `--whole-archive` (or the
// platform equivalent) to include all object files from an rlib into the
// final dylib itself. This causes linkers to iterate and try to include all
// files located in an archive, so if metadata is stored in an archive then
// it needs to be of a form that the linker will be able to process.
// For rlibs we "pack" rustc metadata into a dummy object file.
//
// Historically it was needed because rustc linked rlibs as whole-archive in some cases.
// In that case linkers try to include all files located in an archive, so if metadata is stored
// in an archive then it needs to be of a form that the linker is able to process.
// Now it's not clear whether metadata still needs to be wrapped into an object file or not.
//
// Note, though, that we don't actually want this metadata to show up in any
// final output of the compiler. Instead this is purely for rustc's own

View file

@ -911,13 +911,13 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
});
},
{
sess.time("liveness_and_intrinsic_checking", || {
tcx.hir().par_for_each_module(|module| {
sess.time("liveness_checking", || {
tcx.hir().par_body_owners(|def_id| {
// this must run before MIR dump, because
// "not all control paths return a value" is reported here.
//
// maybe move the check to a MIR pass?
tcx.ensure().check_mod_liveness(module);
tcx.ensure().check_liveness(def_id.to_def_id());
});
});
}

View file

@ -865,9 +865,14 @@ pub trait LintContext: Sized {
if let Some(positional_arg_to_replace) = position_sp_to_replace {
let name = if is_formatting_arg { named_arg_name + "$" } else { named_arg_name };
let span_to_replace = if let Ok(positional_arg_content) =
self.sess().source_map().span_to_snippet(positional_arg_to_replace) && positional_arg_content.starts_with(":") {
positional_arg_to_replace.shrink_to_lo()
} else {
positional_arg_to_replace
};
db.span_suggestion_verbose(
positional_arg_to_replace,
span_to_replace,
"use the named argument by name to avoid ambiguity",
name,
Applicability::MaybeIncorrect,

View file

@ -818,8 +818,8 @@ rustc_queries! {
desc { |tcx| "checking privacy in {}", describe_as_module(key, tcx) }
}
query check_mod_liveness(key: LocalDefId) -> () {
desc { |tcx| "checking liveness of variables in {}", describe_as_module(key, tcx) }
query check_liveness(key: DefId) {
desc { |tcx| "checking liveness of variables in {}", tcx.def_path_str(key) }
}
/// Return the live symbols in the crate for dead code check.

View file

@ -89,11 +89,10 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::*;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
use rustc_index::vec::IndexVec;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, DefIdTree, RootVariableMinCaptureList, Ty, TyCtxt};
use rustc_session::lint;
@ -139,12 +138,54 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
}
}
fn check_mod_liveness(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx));
fn check_liveness(tcx: TyCtxt<'_>, def_id: DefId) {
let local_def_id = match def_id.as_local() {
None => return,
Some(def_id) => def_id,
};
// Don't run unused pass for #[derive()]
let parent = tcx.local_parent(local_def_id);
if let DefKind::Impl = tcx.def_kind(parent)
&& tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
{
return;
}
// Don't run unused pass for #[naked]
if tcx.has_attr(def_id, sym::naked) {
return;
}
let mut maps = IrMaps::new(tcx);
let body_id = tcx.hir().body_owned_by(local_def_id);
let hir_id = tcx.hir().body_owner(body_id);
let body = tcx.hir().body(body_id);
if let Some(upvars) = tcx.upvars_mentioned(def_id) {
for &var_hir_id in upvars.keys() {
let var_name = tcx.hir().name(var_hir_id);
maps.add_variable(Upvar(var_hir_id, var_name));
}
}
// gather up the various local variables, significant expressions,
// and so forth:
maps.visit_body(body);
// compute liveness
let mut lsets = Liveness::new(&mut maps, local_def_id);
let entry_ln = lsets.compute(&body, hir_id);
lsets.log_liveness(entry_ln, body_id.hir_id);
// check for various error conditions
lsets.visit_body(body);
lsets.warn_about_unused_upvars(entry_ln);
lsets.warn_about_unused_args(body, entry_ln);
}
pub fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_liveness, ..*providers };
*providers = Providers { check_liveness, ..*providers };
}
// ______________________________________________________________________
@ -316,56 +357,6 @@ impl<'tcx> IrMaps<'tcx> {
}
impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
self.tcx.hir()
}
fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
debug!("visit_body {:?}", body.id());
// swap in a new set of IR maps for this body
let mut maps = IrMaps::new(self.tcx);
let hir_id = maps.tcx.hir().body_owner(body.id());
let local_def_id = maps.tcx.hir().local_def_id(hir_id);
let def_id = local_def_id.to_def_id();
// Don't run unused pass for #[derive()]
let parent = self.tcx.local_parent(local_def_id);
if let DefKind::Impl = self.tcx.def_kind(parent)
&& self.tcx.has_attr(parent.to_def_id(), sym::automatically_derived)
{
return;
}
// Don't run unused pass for #[naked]
if self.tcx.has_attr(def_id, sym::naked) {
return;
}
if let Some(upvars) = maps.tcx.upvars_mentioned(def_id) {
for &var_hir_id in upvars.keys() {
let var_name = maps.tcx.hir().name(var_hir_id);
maps.add_variable(Upvar(var_hir_id, var_name));
}
}
// gather up the various local variables, significant expressions,
// and so forth:
intravisit::walk_body(&mut maps, body);
// compute liveness
let mut lsets = Liveness::new(&mut maps, local_def_id);
let entry_ln = lsets.compute(&body, hir_id);
lsets.log_liveness(entry_ln, body.id().hir_id);
// check for various error conditions
lsets.visit_body(body);
lsets.warn_about_unused_upvars(entry_ln);
lsets.warn_about_unused_args(body, entry_ln);
}
fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) {
self.add_from_pat(&local.pat);
if local.els.is_some() {

View file

@ -2180,7 +2180,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err.emit()
}
pub(crate) fn add_missing_lifetime_specifiers_label(
fn add_missing_lifetime_specifiers_label(
&mut self,
err: &mut Diagnostic,
lifetime_refs: Vec<MissingLifetime>,

View file

@ -20,6 +20,7 @@
#![feature(let_else)]
#![feature(if_let_guard)]
#![feature(never_type)]
#![feature(type_alias_impl_trait)]
#![recursion_limit = "512"] // For rustdoc
#[macro_use]

View file

@ -6,16 +6,18 @@
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{CombinedSnapshot, InferOk};
use crate::traits::outlives_bounds::InferCtxtExt as _;
use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::util::impl_subject_and_oblig;
use crate::traits::SkipLeakCheck;
use crate::traits::{
self, Normalized, Obligation, ObligationCause, PredicateObligation, PredicateObligations,
SelectionContext,
self, Normalized, Obligation, ObligationCause, ObligationCtxt, PredicateObligation,
PredicateObligations, SelectionContext,
};
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::CRATE_HIR_ID;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::util;
use rustc_middle::traits::specialization_graph::OverlapMode;
@ -322,7 +324,7 @@ fn negative_impl<'cx, 'tcx>(
let (subject2, obligations) =
impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
!equate(&infcx, impl_env, subject1, subject2, obligations)
!equate(&infcx, impl_env, subject1, subject2, obligations, impl1_def_id)
})
}
@ -332,6 +334,7 @@ fn equate<'cx, 'tcx>(
subject1: ImplSubject<'tcx>,
subject2: ImplSubject<'tcx>,
obligations: impl Iterator<Item = PredicateObligation<'tcx>>,
body_def_id: DefId,
) -> bool {
// do the impls unify? If not, not disjoint.
let Ok(InferOk { obligations: more_obligations, .. }) =
@ -342,8 +345,10 @@ fn equate<'cx, 'tcx>(
};
let selcx = &mut SelectionContext::new(&infcx);
let opt_failing_obligation =
obligations.into_iter().chain(more_obligations).find(|o| negative_impl_exists(selcx, o));
let opt_failing_obligation = obligations
.into_iter()
.chain(more_obligations)
.find(|o| negative_impl_exists(selcx, o, body_def_id));
if let Some(failing_obligation) = opt_failing_obligation {
debug!("overlap: obligation unsatisfiable {:?}", failing_obligation);
@ -358,14 +363,15 @@ fn equate<'cx, 'tcx>(
fn negative_impl_exists<'cx, 'tcx>(
selcx: &SelectionContext<'cx, 'tcx>,
o: &PredicateObligation<'tcx>,
body_def_id: DefId,
) -> bool {
if resolve_negative_obligation(selcx.infcx().fork(), o) {
if resolve_negative_obligation(selcx.infcx().fork(), o, body_def_id) {
return true;
}
// Try to prove a negative obligation exists for super predicates
for o in util::elaborate_predicates(selcx.tcx(), iter::once(o.predicate)) {
if resolve_negative_obligation(selcx.infcx().fork(), &o) {
if resolve_negative_obligation(selcx.infcx().fork(), &o, body_def_id) {
return true;
}
}
@ -377,6 +383,7 @@ fn negative_impl_exists<'cx, 'tcx>(
fn resolve_negative_obligation<'cx, 'tcx>(
infcx: InferCtxt<'cx, 'tcx>,
o: &PredicateObligation<'tcx>,
body_def_id: DefId,
) -> bool {
let tcx = infcx.tcx;
@ -385,12 +392,24 @@ fn resolve_negative_obligation<'cx, 'tcx>(
};
let param_env = o.param_env;
let errors = super::fully_solve_obligation(&infcx, o);
if !errors.is_empty() {
if !super::fully_solve_obligation(&infcx, o).is_empty() {
return false;
}
let outlives_env = OutlivesEnvironment::new(param_env);
let (body_id, body_def_id) = if let Some(body_def_id) = body_def_id.as_local() {
(tcx.hir().local_def_id_to_hir_id(body_def_id), body_def_id)
} else {
(CRATE_HIR_ID, CRATE_DEF_ID)
};
let ocx = ObligationCtxt::new(&infcx);
let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id);
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
Some(&infcx),
infcx.implied_bounds_tys(param_env, body_id, wf_tys),
);
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
infcx.resolve_regions(&outlives_env).is_empty()

View file

@ -13,6 +13,7 @@ mod fulfill;
pub mod misc;
mod object_safety;
mod on_unimplemented;
pub mod outlives_bounds;
mod project;
pub mod query;
pub(crate) mod relationships;

View file

@ -1,11 +1,11 @@
use crate::infer::InferCtxt;
use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
use crate::traits::query::NoSolution;
use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::HirId;
use rustc_middle::ty::{self, ParamEnv, Ty};
use rustc_trait_selection::infer::InferCtxt;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
use rustc_trait_selection::traits::query::NoSolution;
use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt};
pub use rustc_middle::traits::query::OutlivesBound;

View file

@ -1,6 +1,5 @@
use super::potentially_plural_count;
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
use crate::outlives::outlives_bounds::InferCtxtExt as _;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
use rustc_hir as hir;
@ -17,6 +16,7 @@ use rustc_middle::ty::{self, DefIdTree};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
};

View file

@ -1,5 +1,4 @@
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use crate::outlives::outlives_bounds::InferCtxtExt as _;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@ -22,6 +21,7 @@ use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,

View file

@ -67,7 +67,6 @@
use crate::constrained_generic_params as cgp;
use crate::errors::SubstsOnOverriddenImpl;
use crate::outlives::outlives_bounds::InferCtxtExt as _;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::{DefId, LocalDefId};
@ -79,6 +78,7 @@ use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {

View file

@ -9,7 +9,6 @@ use rustc_span::Span;
mod explicit;
mod implicit_infer;
pub(crate) mod outlives_bounds;
/// Code to write unit test for outlives.
pub mod test;
mod utils;