Auto merge of #138532 - matthiaskrgr:rollup-mgcynqu, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #138283 (Enforce type of const param correctly in MIR typeck) - #138439 (feat: check ARG_MAX on Unix platforms) - #138502 (resolve: Avoid some unstable iteration) - #138514 (Remove fake borrows of refs that are converted into non-refs in `MakeByMoveBody`) - #138524 (Mark myself as unavailable for reviews temporarily) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4d30011f6c
21 changed files with 394 additions and 49 deletions
|
@ -1771,6 +1771,22 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||
{
|
||||
span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
|
||||
}
|
||||
} else if let Const::Ty(_, ct) = constant.const_
|
||||
&& let ty::ConstKind::Param(p) = ct.kind()
|
||||
{
|
||||
let body_def_id = self.universal_regions.defining_ty.def_id();
|
||||
let const_param = tcx.generics_of(body_def_id).const_param(p, tcx);
|
||||
self.ascribe_user_type(
|
||||
constant.const_.ty(),
|
||||
ty::UserType::new(ty::UserTypeKind::TypeOf(
|
||||
const_param.def_id,
|
||||
UserArgs {
|
||||
args: self.universal_regions.defining_ty.args(),
|
||||
user_self_ty: None,
|
||||
},
|
||||
)),
|
||||
locations.span(self.body),
|
||||
);
|
||||
}
|
||||
|
||||
if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
|
||||
|
|
|
@ -183,6 +183,20 @@ impl<'tcx> DefiningTy<'tcx> {
|
|||
| DefiningTy::GlobalAsm(def_id) => def_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the args of the `DefiningTy`. These are equivalent to the identity
|
||||
/// substs of the body, but replaced with region vids.
|
||||
pub(crate) fn args(&self) -> ty::GenericArgsRef<'tcx> {
|
||||
match *self {
|
||||
DefiningTy::Closure(_, args)
|
||||
| DefiningTy::Coroutine(_, args)
|
||||
| DefiningTy::CoroutineClosure(_, args)
|
||||
| DefiningTy::FnDef(_, args)
|
||||
| DefiningTy::Const(_, args)
|
||||
| DefiningTy::InlineConst(_, args) => args,
|
||||
DefiningTy::GlobalAsm(_) => ty::List::empty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -137,12 +137,42 @@ impl Command {
|
|||
/// Returns a `true` if we're pretty sure that this'll blow OS spawn limits,
|
||||
/// or `false` if we should attempt to spawn and see what the OS says.
|
||||
pub(crate) fn very_likely_to_exceed_some_spawn_limit(&self) -> bool {
|
||||
// We mostly only care about Windows in this method, on Unix the limits
|
||||
// can be gargantuan anyway so we're pretty unlikely to hit them
|
||||
if cfg!(unix) {
|
||||
#[cfg(not(any(windows, unix)))]
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// On Unix the limits can be gargantuan anyway so we're pretty
|
||||
// unlikely to hit them, but might still exceed it.
|
||||
// We consult ARG_MAX here to get an estimate.
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let ptr_size = mem::size_of::<usize>();
|
||||
// arg + \0 + pointer
|
||||
let args_size = self.args.iter().fold(0usize, |acc, a| {
|
||||
let arg = a.as_encoded_bytes().len();
|
||||
let nul = 1;
|
||||
acc.saturating_add(arg).saturating_add(nul).saturating_add(ptr_size)
|
||||
});
|
||||
// key + `=` + value + \0 + pointer
|
||||
let envs_size = self.env.iter().fold(0usize, |acc, (k, v)| {
|
||||
let k = k.as_encoded_bytes().len();
|
||||
let eq = 1;
|
||||
let v = v.as_encoded_bytes().len();
|
||||
let nul = 1;
|
||||
acc.saturating_add(k)
|
||||
.saturating_add(eq)
|
||||
.saturating_add(v)
|
||||
.saturating_add(nul)
|
||||
.saturating_add(ptr_size)
|
||||
});
|
||||
let arg_max = match unsafe { libc::sysconf(libc::_SC_ARG_MAX) } {
|
||||
-1 => return false, // Go to OS anyway.
|
||||
max => max as usize,
|
||||
};
|
||||
return args_size.saturating_add(envs_size) > arg_max;
|
||||
}
|
||||
|
||||
// Ok so on Windows to spawn a process is 32,768 characters in its
|
||||
// command line [1]. Unfortunately we don't actually have access to that
|
||||
// as it's calculated just before spawning. Instead we perform a
|
||||
|
@ -165,9 +195,14 @@ impl Command {
|
|||
//
|
||||
// [1]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
|
||||
// [2]: https://devblogs.microsoft.com/oldnewthing/?p=41553
|
||||
|
||||
let estimated_command_line_len = self.args.iter().map(|a| a.len()).sum::<usize>();
|
||||
estimated_command_line_len > 1024 * 6
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let estimated_command_line_len = self
|
||||
.args
|
||||
.iter()
|
||||
.fold(0usize, |acc, a| acc.saturating_add(a.as_encoded_bytes().len()));
|
||||
return estimated_command_line_len > 1024 * 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -259,6 +259,12 @@ impl<V: Eq + Hash> UnordSet<V> {
|
|||
self.inner.is_empty()
|
||||
}
|
||||
|
||||
/// If the set has only one element, returns it, otherwise returns `None`.
|
||||
#[inline]
|
||||
pub fn get_only(&self) -> Option<&V> {
|
||||
if self.inner.len() == 1 { self.inner.iter().next() } else { None }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn insert(&mut self, v: V) -> bool {
|
||||
self.inner.insert(v)
|
||||
|
|
|
@ -33,6 +33,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
|||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
|
||||
|
@ -169,7 +170,7 @@ pub struct ResolverGlobalCtxt {
|
|||
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
|
||||
pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
|
||||
pub effective_visibilities: EffectiveVisibilities,
|
||||
pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
|
||||
pub extern_crate_map: UnordMap<LocalDefId, CrateNum>,
|
||||
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
|
||||
pub module_children: LocalDefIdMap<Vec<ModChild>>,
|
||||
pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
|
||||
|
|
|
@ -178,7 +178,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
|
|||
),
|
||||
};
|
||||
|
||||
(
|
||||
Some((
|
||||
FieldIdx::from_usize(child_field_idx + num_args),
|
||||
(
|
||||
FieldIdx::from_usize(parent_field_idx + num_args),
|
||||
|
@ -186,9 +186,10 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>(
|
|||
peel_deref,
|
||||
child_precise_captures,
|
||||
),
|
||||
)
|
||||
))
|
||||
},
|
||||
)
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
if coroutine_kind == ty::ClosureKind::FnOnce {
|
||||
|
@ -312,10 +313,46 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
|
|||
self.super_place(place, context, location);
|
||||
}
|
||||
|
||||
fn visit_statement(&mut self, statement: &mut mir::Statement<'tcx>, location: mir::Location) {
|
||||
// Remove fake borrows of closure captures if that capture has been
|
||||
// replaced with a by-move version of that capture.
|
||||
//
|
||||
// For example, imagine we capture `Foo` in the parent and `&Foo`
|
||||
// in the child. We will emit two fake borrows like:
|
||||
//
|
||||
// ```
|
||||
// _2 = &fake shallow (*(_1.0: &Foo));
|
||||
// _3 = &fake shallow (_1.0: &Foo);
|
||||
// ```
|
||||
//
|
||||
// However, since this transform is responsible for replacing
|
||||
// `_1.0: &Foo` with `_1.0: Foo`, that makes the second fake borrow
|
||||
// obsolete, and we should replace it with a nop.
|
||||
//
|
||||
// As a side-note, we don't actually even care about fake borrows
|
||||
// here at all since they're fully a MIR borrowck artifact, and we
|
||||
// don't need to borrowck by-move MIR bodies. But it's best to preserve
|
||||
// as much as we can between these two bodies :)
|
||||
if let mir::StatementKind::Assign(box (_, rvalue)) = &statement.kind
|
||||
&& let mir::Rvalue::Ref(_, mir::BorrowKind::Fake(mir::FakeBorrowKind::Shallow), place) =
|
||||
rvalue
|
||||
&& let mir::PlaceRef {
|
||||
local: ty::CAPTURE_STRUCT_LOCAL,
|
||||
projection: [mir::ProjectionElem::Field(idx, _)],
|
||||
} = place.as_ref()
|
||||
&& let Some(&(_, _, true, _)) = self.field_remapping.get(&idx)
|
||||
{
|
||||
statement.kind = mir::StatementKind::Nop;
|
||||
}
|
||||
|
||||
self.super_statement(statement, location);
|
||||
}
|
||||
|
||||
fn visit_local_decl(&mut self, local: mir::Local, local_decl: &mut mir::LocalDecl<'tcx>) {
|
||||
// Replace the type of the self arg.
|
||||
if local == ty::CAPTURE_STRUCT_LOCAL {
|
||||
local_decl.ty = self.by_move_coroutine_ty;
|
||||
}
|
||||
self.super_local_decl(local, local_decl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1115,6 +1115,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
for ident in single_imports.iter().cloned() {
|
||||
let result = self.r.maybe_resolve_ident_in_module(
|
||||
ModuleOrUniformRoot::Module(module),
|
||||
|
|
|
@ -6,6 +6,7 @@ use rustc_ast::{
|
|||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, MultiSpan, SuggestionStyle,
|
||||
|
@ -1467,6 +1468,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
|
||||
if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
|
||||
});
|
||||
|
@ -2863,18 +2865,11 @@ fn show_candidates(
|
|||
} else {
|
||||
// Get the unique item kinds and if there's only one, we use the right kind name
|
||||
// instead of the more generic "items".
|
||||
let mut kinds = accessible_path_strings
|
||||
let kinds = accessible_path_strings
|
||||
.iter()
|
||||
.map(|(_, descr, _, _, _)| *descr)
|
||||
.collect::<FxHashSet<&str>>()
|
||||
.into_iter();
|
||||
let kind = if let Some(kind) = kinds.next()
|
||||
&& let None = kinds.next()
|
||||
{
|
||||
kind
|
||||
} else {
|
||||
"item"
|
||||
};
|
||||
.collect::<UnordSet<&str>>();
|
||||
let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
|
||||
let s = if kind.ends_with('s') { "es" } else { "s" };
|
||||
|
||||
("one of these", kind, s, String::new(), "")
|
||||
|
|
|
@ -946,6 +946,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
|
||||
// Check if one of single imports can still define the name,
|
||||
// if it can then our result is not determined and can be invalidated.
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
for single_import in &resolution.single_imports {
|
||||
if ignore_import == Some(*single_import) {
|
||||
// This branch handles a cycle in single imports.
|
||||
|
|
|
@ -18,6 +18,7 @@ use rustc_ast::visit::{
|
|||
};
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
use rustc_data_structures::unord::{UnordMap, UnordSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{
|
||||
Applicability, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions,
|
||||
|
@ -47,8 +48,6 @@ mod diagnostics;
|
|||
|
||||
type Res = def::Res<NodeId>;
|
||||
|
||||
type IdentMap<T> = FxHashMap<Ident, T>;
|
||||
|
||||
use diagnostics::{ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -273,8 +272,8 @@ impl RibKind<'_> {
|
|||
/// resolving, the name is looked up from inside out.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Rib<'ra, R = Res> {
|
||||
pub bindings: IdentMap<R>,
|
||||
pub patterns_with_skipped_bindings: FxHashMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>,
|
||||
pub bindings: FxHashMap<Ident, R>,
|
||||
pub patterns_with_skipped_bindings: UnordMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>,
|
||||
pub kind: RibKind<'ra>,
|
||||
}
|
||||
|
||||
|
@ -1605,12 +1604,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
// for better diagnostics.
|
||||
let mut forward_ty_ban_rib_const_param_ty = Rib {
|
||||
bindings: forward_ty_ban_rib.bindings.clone(),
|
||||
patterns_with_skipped_bindings: FxHashMap::default(),
|
||||
patterns_with_skipped_bindings: Default::default(),
|
||||
kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy),
|
||||
};
|
||||
let mut forward_const_ban_rib_const_param_ty = Rib {
|
||||
bindings: forward_const_ban_rib.bindings.clone(),
|
||||
patterns_with_skipped_bindings: FxHashMap::default(),
|
||||
patterns_with_skipped_bindings: Default::default(),
|
||||
kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy),
|
||||
};
|
||||
// We'll ban these with a `ConstParamTy` rib, so just clear these ribs for better
|
||||
|
@ -2334,7 +2333,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
let local_candidates = self.lifetime_elision_candidates.take();
|
||||
|
||||
if let Some(candidates) = local_candidates {
|
||||
let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect();
|
||||
let distinct: UnordSet<_> = candidates.iter().map(|(res, _)| *res).collect();
|
||||
let lifetime_count = distinct.len();
|
||||
if lifetime_count != 0 {
|
||||
parameter_info.push(ElisionFnParameter {
|
||||
|
@ -2358,14 +2357,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
}
|
||||
}));
|
||||
}
|
||||
let mut distinct_iter = distinct.into_iter();
|
||||
if let Some(res) = distinct_iter.next() {
|
||||
if !distinct.is_empty() {
|
||||
match elision_lifetime {
|
||||
// We are the first parameter to bind lifetimes.
|
||||
Elision::None => {
|
||||
if distinct_iter.next().is_none() {
|
||||
if let Some(res) = distinct.get_only() {
|
||||
// We have a single lifetime => success.
|
||||
elision_lifetime = Elision::Param(res)
|
||||
elision_lifetime = Elision::Param(*res)
|
||||
} else {
|
||||
// We have multiple lifetimes => error.
|
||||
elision_lifetime = Elision::Err;
|
||||
|
@ -2890,6 +2888,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
break;
|
||||
}
|
||||
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
seen_bindings
|
||||
.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
|
||||
}
|
||||
|
@ -4004,7 +4003,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> {
|
||||
fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxHashMap<Ident, Res> {
|
||||
&mut self.ribs[ns].last_mut().unwrap().bindings
|
||||
}
|
||||
|
||||
|
@ -5202,6 +5201,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
let mut late_resolution_visitor = LateResolutionVisitor::new(self);
|
||||
late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
|
||||
visit::walk_crate(&mut late_resolution_visitor, krate);
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
|
||||
self.lint_buffer.buffer_lint(
|
||||
lint::builtin::UNUSED_LABELS,
|
||||
|
|
|
@ -830,6 +830,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
if let Some(rib) = &self.last_block_rib
|
||||
&& let RibKind::Normal = rib.kind
|
||||
{
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
for (ident, &res) in &rib.bindings {
|
||||
if let Res::Local(_) = res
|
||||
&& path.len() == 1
|
||||
|
@ -1018,6 +1019,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
if let Some(err_code) = err.code {
|
||||
if err_code == E0425 {
|
||||
for label_rib in &self.label_ribs {
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
for (label_ident, node_id) in &label_rib.bindings {
|
||||
let ident = path.last().unwrap().ident;
|
||||
if format!("'{ident}") == label_ident.to_string() {
|
||||
|
@ -1177,7 +1179,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
let [segment] = path else { return };
|
||||
let None = following_seg else { return };
|
||||
for rib in self.ribs[ValueNS].iter().rev() {
|
||||
for (def_id, spans) in &rib.patterns_with_skipped_bindings {
|
||||
let patterns_with_skipped_bindings = self.r.tcx.with_stable_hashing_context(|hcx| {
|
||||
rib.patterns_with_skipped_bindings.to_sorted(&hcx, true)
|
||||
});
|
||||
for (def_id, spans) in patterns_with_skipped_bindings {
|
||||
if let DefKind::Struct | DefKind::Variant = self.r.tcx.def_kind(*def_id)
|
||||
&& let Some(fields) = self.r.field_idents(*def_id)
|
||||
{
|
||||
|
@ -2052,7 +2057,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
if self
|
||||
.r
|
||||
.extern_crate_map
|
||||
.iter()
|
||||
.items()
|
||||
// FIXME: This doesn't include impls like `impl Default for String`.
|
||||
.flat_map(|(_, crate_)| self.r.tcx.implementations_of_trait((*crate_, default_trait)))
|
||||
.filter_map(|(_, simplified_self_ty)| *simplified_self_ty)
|
||||
|
@ -2261,6 +2266,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
};
|
||||
|
||||
// Locals and type parameters
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
for (ident, &res) in &rib.bindings {
|
||||
if filter_fn(res) && ident.span.ctxt() == rib_ctxt {
|
||||
names.push(TypoSuggestion::typo_from_ident(*ident, res));
|
||||
|
@ -2788,6 +2794,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
let within_scope = self.is_label_valid_from_rib(rib_index);
|
||||
|
||||
let rib = &self.label_ribs[rib_index];
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
let names = rib
|
||||
.bindings
|
||||
.iter()
|
||||
|
@ -2799,6 +2806,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
// Upon finding a similar name, get the ident that it was from - the span
|
||||
// contained within helps make a useful diagnostic. In addition, determine
|
||||
// whether this candidate is within scope.
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
let (ident, _) = rib.bindings.iter().find(|(ident, _)| ident.name == symbol).unwrap();
|
||||
(*ident, within_scope)
|
||||
})
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![doc(rust_logo)]
|
||||
|
@ -47,6 +46,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
|||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::FreezeReadGuard;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed};
|
||||
use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind};
|
||||
use rustc_feature::BUILTIN_ATTRIBUTES;
|
||||
|
@ -1046,7 +1046,7 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
graph_root: Module<'ra>,
|
||||
|
||||
prelude: Option<Module<'ra>>,
|
||||
extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'ra>>,
|
||||
extern_prelude: FxIndexMap<Ident, ExternPreludeEntry<'ra>>,
|
||||
|
||||
/// N.B., this is used only for better diagnostics, not name resolution itself.
|
||||
field_names: LocalDefIdMap<Vec<Ident>>,
|
||||
|
@ -1079,7 +1079,7 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>,
|
||||
|
||||
/// `CrateNum` resolutions of `extern crate` items.
|
||||
extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
|
||||
extern_crate_map: UnordMap<LocalDefId, CrateNum>,
|
||||
module_children: LocalDefIdMap<Vec<ModChild>>,
|
||||
trait_map: NodeMap<Vec<TraitCandidate>>,
|
||||
|
||||
|
@ -1102,7 +1102,7 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
/// some AST passes can generate identifiers that only resolve to local or
|
||||
/// lang items.
|
||||
empty_module: Module<'ra>,
|
||||
module_map: FxHashMap<DefId, Module<'ra>>,
|
||||
module_map: FxIndexMap<DefId, Module<'ra>>,
|
||||
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
|
||||
|
||||
underscore_disambiguator: u32,
|
||||
|
@ -1136,7 +1136,7 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
macro_names: FxHashSet<Ident>,
|
||||
builtin_macros: FxHashMap<Symbol, BuiltinMacroState>,
|
||||
registered_tools: &'tcx RegisteredTools,
|
||||
macro_use_prelude: FxHashMap<Symbol, NameBinding<'ra>>,
|
||||
macro_use_prelude: FxIndexMap<Symbol, NameBinding<'ra>>,
|
||||
macro_map: FxHashMap<DefId, MacroData>,
|
||||
dummy_ext_bang: Arc<SyntaxExtension>,
|
||||
dummy_ext_derive: Arc<SyntaxExtension>,
|
||||
|
@ -1145,7 +1145,7 @@ pub struct Resolver<'ra, 'tcx> {
|
|||
ast_transform_scopes: FxHashMap<LocalExpnId, Module<'ra>>,
|
||||
unused_macros: FxHashMap<LocalDefId, (NodeId, Ident)>,
|
||||
/// A map from the macro to all its potentially unused arms.
|
||||
unused_macro_rules: FxIndexMap<LocalDefId, FxHashMap<usize, (Ident, Span)>>,
|
||||
unused_macro_rules: FxIndexMap<LocalDefId, UnordMap<usize, (Ident, Span)>>,
|
||||
proc_macro_stubs: FxHashSet<LocalDefId>,
|
||||
/// Traces collected during macro resolution and validated when it's complete.
|
||||
single_segment_macro_resolutions:
|
||||
|
@ -1259,7 +1259,7 @@ impl<'ra> ResolverArenas<'ra> {
|
|||
expn_id: ExpnId,
|
||||
span: Span,
|
||||
no_implicit_prelude: bool,
|
||||
module_map: &mut FxHashMap<DefId, Module<'ra>>,
|
||||
module_map: &mut FxIndexMap<DefId, Module<'ra>>,
|
||||
module_self_bindings: &mut FxHashMap<Module<'ra>, NameBinding<'ra>>,
|
||||
) -> Module<'ra> {
|
||||
let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new(
|
||||
|
@ -1404,7 +1404,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
arenas: &'ra ResolverArenas<'ra>,
|
||||
) -> Resolver<'ra, 'tcx> {
|
||||
let root_def_id = CRATE_DEF_ID.to_def_id();
|
||||
let mut module_map = FxHashMap::default();
|
||||
let mut module_map = FxIndexMap::default();
|
||||
let mut module_self_bindings = FxHashMap::default();
|
||||
let graph_root = arenas.new_module(
|
||||
None,
|
||||
|
@ -1421,8 +1421,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
ExpnId::root(),
|
||||
DUMMY_SP,
|
||||
true,
|
||||
&mut FxHashMap::default(),
|
||||
&mut FxHashMap::default(),
|
||||
&mut Default::default(),
|
||||
&mut Default::default(),
|
||||
);
|
||||
|
||||
let mut def_id_to_node_id = IndexVec::default();
|
||||
|
@ -1437,7 +1437,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
let mut invocation_parents = FxHashMap::default();
|
||||
invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT);
|
||||
|
||||
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = tcx
|
||||
let mut extern_prelude: FxIndexMap<Ident, ExternPreludeEntry<'_>> = tcx
|
||||
.sess
|
||||
.opts
|
||||
.externs
|
||||
|
@ -1536,7 +1536,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
macro_names: FxHashSet::default(),
|
||||
builtin_macros: Default::default(),
|
||||
registered_tools,
|
||||
macro_use_prelude: FxHashMap::default(),
|
||||
macro_use_prelude: Default::default(),
|
||||
macro_map: FxHashMap::default(),
|
||||
dummy_ext_bang: Arc::new(SyntaxExtension::dummy_bang(edition)),
|
||||
dummy_ext_derive: Arc::new(SyntaxExtension::dummy_derive(edition)),
|
||||
|
|
|
@ -323,6 +323,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
|
|||
}
|
||||
|
||||
fn check_unused_macros(&mut self) {
|
||||
#[allow(rustc::potential_query_instability)] // FIXME
|
||||
for (_, &(node_id, ident)) in self.unused_macros.iter() {
|
||||
self.lint_buffer.buffer_lint(
|
||||
UNUSED_MACROS,
|
||||
|
@ -333,10 +334,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
|
|||
}
|
||||
|
||||
for (&def_id, unused_arms) in self.unused_macro_rules.iter() {
|
||||
let mut unused_arms = unused_arms.iter().collect::<Vec<_>>();
|
||||
unused_arms.sort_by_key(|&(&arm_i, _)| arm_i);
|
||||
|
||||
for (&arm_i, &(ident, rule_span)) in unused_arms {
|
||||
for (&arm_i, &(ident, rule_span)) in unused_arms.to_sorted_stable_ord() {
|
||||
if self.unused_macros.contains_key(&def_id) {
|
||||
// We already lint the entire macro as unused
|
||||
continue;
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
// MIR for `foo::{closure#0}::{closure#0}` after built
|
||||
|
||||
fn foo::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
|
||||
yields ()
|
||||
{
|
||||
debug _task_context => _2;
|
||||
debug f => (*(_1.0: &&Foo));
|
||||
let mut _0: ();
|
||||
let mut _3: &Foo;
|
||||
let mut _4: &&Foo;
|
||||
let mut _5: &&&Foo;
|
||||
let mut _6: isize;
|
||||
let mut _7: bool;
|
||||
|
||||
bb0: {
|
||||
PlaceMention((*(_1.0: &&Foo)));
|
||||
_6 = discriminant((*(*(_1.0: &&Foo))));
|
||||
switchInt(move _6) -> [0: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = const ();
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
falseEdge -> [real: bb5, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
goto -> bb1;
|
||||
}
|
||||
|
||||
bb4: {
|
||||
FakeRead(ForMatchedPlace(None), (*(_1.0: &&Foo)));
|
||||
unreachable;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
_3 = &fake shallow (*(*(_1.0: &&Foo)));
|
||||
_4 = &fake shallow (*(_1.0: &&Foo));
|
||||
_5 = &fake shallow (_1.0: &&Foo);
|
||||
StorageLive(_7);
|
||||
_7 = const true;
|
||||
switchInt(move _7) -> [0: bb8, otherwise: bb7];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
falseEdge -> [real: bb3, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_7);
|
||||
FakeRead(ForMatchGuard, _3);
|
||||
FakeRead(ForMatchGuard, _4);
|
||||
FakeRead(ForMatchGuard, _5);
|
||||
_0 = const ();
|
||||
goto -> bb10;
|
||||
}
|
||||
|
||||
bb8: {
|
||||
goto -> bb9;
|
||||
}
|
||||
|
||||
bb9: {
|
||||
StorageDead(_7);
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb10: {
|
||||
drop(_1) -> [return: bb11, unwind: bb12];
|
||||
}
|
||||
|
||||
bb11: {
|
||||
return;
|
||||
}
|
||||
|
||||
bb12 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
// MIR for `foo::{closure#0}::{closure#1}` after built
|
||||
|
||||
fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
|
||||
yields ()
|
||||
{
|
||||
debug _task_context => _2;
|
||||
debug f => (_1.0: &Foo);
|
||||
let mut _0: ();
|
||||
let mut _3: &Foo;
|
||||
let mut _4: &&Foo;
|
||||
let mut _5: &&&Foo;
|
||||
let mut _6: isize;
|
||||
let mut _7: bool;
|
||||
|
||||
bb0: {
|
||||
PlaceMention((_1.0: &Foo));
|
||||
_6 = discriminant((*(_1.0: &Foo)));
|
||||
switchInt(move _6) -> [0: bb2, otherwise: bb1];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = const ();
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
falseEdge -> [real: bb3, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
_3 = &fake shallow (*(_1.0: &Foo));
|
||||
_4 = &fake shallow (_1.0: &Foo);
|
||||
nop;
|
||||
StorageLive(_7);
|
||||
_7 = const true;
|
||||
switchInt(move _7) -> [0: bb5, otherwise: bb4];
|
||||
}
|
||||
|
||||
bb4: {
|
||||
StorageDead(_7);
|
||||
FakeRead(ForMatchGuard, _3);
|
||||
FakeRead(ForMatchGuard, _4);
|
||||
FakeRead(ForMatchGuard, _5);
|
||||
_0 = const ();
|
||||
goto -> bb6;
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_7);
|
||||
falseEdge -> [real: bb1, imaginary: bb1];
|
||||
}
|
||||
|
||||
bb6: {
|
||||
drop(_1) -> [return: bb7, unwind: bb8];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
return;
|
||||
}
|
||||
|
||||
bb8 (cleanup): {
|
||||
resume;
|
||||
}
|
||||
}
|
18
tests/mir-opt/async_closure_fake_read_for_by_move.rs
Normal file
18
tests/mir-opt/async_closure_fake_read_for_by_move.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
//@ edition:2021
|
||||
// skip-filecheck
|
||||
|
||||
enum Foo {
|
||||
Bar,
|
||||
Baz,
|
||||
}
|
||||
|
||||
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
|
||||
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir
|
||||
fn foo(f: &Foo) {
|
||||
let x = async move || match f {
|
||||
Foo::Bar if true => {}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,16 @@
|
|||
// Ensure that we actually treat `N`'s type as `Invariant<'static>` in MIR typeck.
|
||||
|
||||
#![feature(adt_const_params)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
use std::ops::Deref;
|
||||
|
||||
#[derive(ConstParamTy, PartialEq, Eq)]
|
||||
struct Invariant<'a>(<&'a () as Deref>::Target);
|
||||
|
||||
fn test<'a, const N: Invariant<'static>>() {
|
||||
let x: Invariant<'a> = N;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,14 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/check-type-in-mir.rs:12:28
|
||||
|
|
||||
LL | fn test<'a, const N: Invariant<'static>>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let x: Invariant<'a> = N;
|
||||
| ^ assignment requires that `'a` must outlive `'static`
|
||||
|
|
||||
= note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
|
||||
= note: the struct `Invariant<'a>` is invariant over the parameter `'a`
|
||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Ensure that we actually treat `N`'s type as `&'a u32` in MIR typeck.
|
||||
|
||||
#![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
|
||||
//~^ WARN the feature `unsized_const_params` is incomplete
|
||||
//~| WARN the feature `generic_const_parameter_types` is incomplete
|
||||
|
||||
fn foo<'a, const N: &'a u32>() {
|
||||
let b: &'static u32 = N;
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,27 @@
|
|||
warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/check-type-in-mir.rs:3:12
|
||||
|
|
||||
LL | #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/check-type-in-mir.rs:3:52
|
||||
|
|
||||
LL | #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #137626 <https://github.com/rust-lang/rust/issues/137626> for more information
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/check-type-in-mir.rs:8:12
|
||||
|
|
||||
LL | fn foo<'a, const N: &'a u32>() {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | let b: &'static u32 = N;
|
||||
| ^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
|
||||
error: aborting due to 1 previous error; 2 warnings emitted
|
||||
|
|
@ -1082,6 +1082,7 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
|
|||
users_on_vacation = [
|
||||
"jyn514",
|
||||
"ChrisDenton",
|
||||
"jieyouxu",
|
||||
]
|
||||
|
||||
[[assign.warn_non_default_branch.exceptions]]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue