Auto merge of #3419 - RalfJung:rustup, r=RalfJung
Rustup https://github.com/rust-lang/rust/pull/123081 landed so hopefully this works now.
This commit is contained in:
commit
2e198d04ee
169 changed files with 2339 additions and 672 deletions
|
|
@ -3784,6 +3784,7 @@ dependencies = [
|
|||
name = "rustc_driver_impl"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ctrlc",
|
||||
"libc",
|
||||
"rustc_ast",
|
||||
"rustc_ast_lowering",
|
||||
|
|
|
|||
|
|
@ -95,9 +95,11 @@ pub struct RegionInferenceContext<'tcx> {
|
|||
/// visible from this index.
|
||||
scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
|
||||
|
||||
/// Contains a "representative" from each SCC. This will be the
|
||||
/// minimal RegionVid belonging to that universe. It is used as a
|
||||
/// kind of hacky way to manage checking outlives relationships,
|
||||
/// Contains the "representative" region of each SCC.
|
||||
/// It is defined as the one with the minimal RegionVid, favoring
|
||||
/// free regions, then placeholders, then existential regions.
|
||||
///
|
||||
/// It is a hacky way to manage checking regions for equality,
|
||||
/// since we can 'canonicalize' each region to the representative
|
||||
/// of its SCC and be sure that -- if they have the same repr --
|
||||
/// they *must* be equal (though not having the same repr does not
|
||||
|
|
@ -481,8 +483,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
scc_universes
|
||||
}
|
||||
|
||||
/// For each SCC, we compute a unique `RegionVid` (in fact, the
|
||||
/// minimal one that belongs to the SCC). See
|
||||
/// For each SCC, we compute a unique `RegionVid`. See the
|
||||
/// `scc_representatives` field of `RegionInferenceContext` for
|
||||
/// more details.
|
||||
fn compute_scc_representatives(
|
||||
|
|
@ -490,13 +491,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
definitions: &IndexSlice<RegionVid, RegionDefinition<'tcx>>,
|
||||
) -> IndexVec<ConstraintSccIndex, ty::RegionVid> {
|
||||
let num_sccs = constraints_scc.num_sccs();
|
||||
let next_region_vid = definitions.next_index();
|
||||
let mut scc_representatives = IndexVec::from_elem_n(next_region_vid, num_sccs);
|
||||
let mut scc_representatives = IndexVec::from_elem_n(RegionVid::MAX, num_sccs);
|
||||
|
||||
for region_vid in definitions.indices() {
|
||||
let scc = constraints_scc.scc(region_vid);
|
||||
let prev_min = scc_representatives[scc];
|
||||
scc_representatives[scc] = region_vid.min(prev_min);
|
||||
// Iterate over all RegionVids *in-order* and pick the least RegionVid as the
|
||||
// representative of its SCC. This naturally prefers free regions over others.
|
||||
for (vid, def) in definitions.iter_enumerated() {
|
||||
let repr = &mut scc_representatives[constraints_scc.scc(vid)];
|
||||
if *repr == ty::RegionVid::MAX {
|
||||
*repr = vid;
|
||||
} else if matches!(def.origin, NllRegionVariableOrigin::Placeholder(_))
|
||||
&& matches!(definitions[*repr].origin, NllRegionVariableOrigin::Existential { .. })
|
||||
{
|
||||
// Pick placeholders over existentials even if they have a greater RegionVid.
|
||||
*repr = vid;
|
||||
}
|
||||
}
|
||||
|
||||
scc_representatives
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::OpaqueTyOrigin;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::infer::TyCtxtInferExt as _;
|
||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
|
||||
use rustc_infer::traits::{Obligation, ObligationCause};
|
||||
use rustc_macros::extension;
|
||||
use rustc_middle::traits::DefiningAnchor;
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::RegionVid;
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgs};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -18,76 +17,19 @@ use rustc_trait_selection::traits::ObligationCtxt;
|
|||
|
||||
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
|
||||
use crate::session_diagnostics::NonGenericOpaqueTypeParam;
|
||||
use crate::universal_regions::RegionClassification;
|
||||
|
||||
use super::RegionInferenceContext;
|
||||
|
||||
impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
fn universal_name(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
|
||||
let scc = self.constraint_sccs.scc(vid);
|
||||
self.scc_values
|
||||
.universal_regions_outlived_by(scc)
|
||||
.find_map(|lb| self.eval_equal(vid, lb).then_some(self.definitions[lb].external_name?))
|
||||
}
|
||||
|
||||
fn generic_arg_to_region(&self, arg: ty::GenericArg<'tcx>) -> Option<RegionVid> {
|
||||
let region = arg.as_region()?;
|
||||
|
||||
if let ty::RePlaceholder(..) = region.kind() {
|
||||
None
|
||||
} else {
|
||||
Some(self.to_region_vid(region))
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that all opaque types have the same region parameters if they have the same
|
||||
/// non-region parameters. This is necessary because within the new solver we perform various query operations
|
||||
/// modulo regions, and thus could unsoundly select some impls that don't hold.
|
||||
fn check_unique(
|
||||
&self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_ty_decls: &FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
) {
|
||||
for (i, (a, a_ty)) in opaque_ty_decls.iter().enumerate() {
|
||||
for (b, b_ty) in opaque_ty_decls.iter().skip(i + 1) {
|
||||
if a.def_id != b.def_id {
|
||||
continue;
|
||||
}
|
||||
// Non-lifetime params differ -> ok
|
||||
if infcx.tcx.erase_regions(a.args) != infcx.tcx.erase_regions(b.args) {
|
||||
continue;
|
||||
}
|
||||
trace!(?a, ?b);
|
||||
for (a, b) in a.args.iter().zip(b.args) {
|
||||
trace!(?a, ?b);
|
||||
let Some(r1) = self.generic_arg_to_region(a) else {
|
||||
continue;
|
||||
};
|
||||
let Some(r2) = self.generic_arg_to_region(b) else {
|
||||
continue;
|
||||
};
|
||||
if self.eval_equal(r1, r2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
|
||||
arg: self.universal_name(r1).unwrap().into(),
|
||||
prev: self.universal_name(r2).unwrap().into(),
|
||||
span: a_ty.span,
|
||||
prev_span: b_ty.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve any opaque types that were encountered while borrow checking
|
||||
/// this item. This is then used to get the type in the `type_of` query.
|
||||
///
|
||||
/// For example consider `fn f<'a>(x: &'a i32) -> impl Sized + 'a { x }`.
|
||||
/// This is lowered to give HIR something like
|
||||
///
|
||||
/// type f<'a>::_Return<'_a> = impl Sized + '_a;
|
||||
/// fn f<'a>(x: &'a i32) -> f<'static>::_Return<'a> { x }
|
||||
/// type f<'a>::_Return<'_x> = impl Sized + '_x;
|
||||
/// fn f<'a>(x: &'a i32) -> f<'a>::_Return<'a> { x }
|
||||
///
|
||||
/// When checking the return type record the type from the return and the
|
||||
/// type used in the return value. In this case they might be `_Return<'1>`
|
||||
|
|
@ -95,118 +37,102 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
///
|
||||
/// Once we to this method, we have completed region inference and want to
|
||||
/// call `infer_opaque_definition_from_instantiation` to get the inferred
|
||||
/// type of `_Return<'_a>`. `infer_opaque_definition_from_instantiation`
|
||||
/// type of `_Return<'_x>`. `infer_opaque_definition_from_instantiation`
|
||||
/// compares lifetimes directly, so we need to map the inference variables
|
||||
/// back to concrete lifetimes: `'static`, `ReEarlyParam` or `ReLateParam`.
|
||||
///
|
||||
/// First we map all the lifetimes in the concrete type to an equal
|
||||
/// universal region that occurs in the concrete type's args, in this case
|
||||
/// this would result in `&'1 i32`. We only consider regions in the args
|
||||
/// First we map the regions in the the generic parameters `_Return<'1>` to
|
||||
/// their `external_name` giving `_Return<'a>`. This step is a bit involved.
|
||||
/// See the [rustc-dev-guide chapter] for more info.
|
||||
///
|
||||
/// Then we map all the lifetimes in the concrete type to an equal
|
||||
/// universal region that occurs in the opaque type's args, in this case
|
||||
/// this would result in `&'a i32`. We only consider regions in the args
|
||||
/// in case there is an equal region that does not. For example, this should
|
||||
/// be allowed:
|
||||
/// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }`
|
||||
///
|
||||
/// Then we map the regions in both the type and the generic parameters to their
|
||||
/// `external_name` giving `concrete_type = &'a i32`,
|
||||
/// `args = ['static, 'a]`. This will then allow
|
||||
/// `infer_opaque_definition_from_instantiation` to determine that
|
||||
/// `_Return<'_a> = &'_a i32`.
|
||||
/// This will then allow `infer_opaque_definition_from_instantiation` to
|
||||
/// determine that `_Return<'_x> = &'_x i32`.
|
||||
///
|
||||
/// There's a slight complication around closures. Given
|
||||
/// `fn f<'a: 'a>() { || {} }` the closure's type is something like
|
||||
/// `f::<'a>::{{closure}}`. The region parameter from f is essentially
|
||||
/// ignored by type checking so ends up being inferred to an empty region.
|
||||
/// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
|
||||
/// which has no `external_name` in which case we use `'empty` as the
|
||||
/// which has no `external_name` in which case we use `'{erased}` as the
|
||||
/// region to pass to `infer_opaque_definition_from_instantiation`.
|
||||
///
|
||||
/// [rustc-dev-guide chapter]:
|
||||
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
|
||||
#[instrument(level = "debug", skip(self, infcx), ret)]
|
||||
pub(crate) fn infer_opaque_types(
|
||||
&self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
|
||||
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
|
||||
self.check_unique(infcx, &opaque_ty_decls);
|
||||
|
||||
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
|
||||
|
||||
let member_constraints: FxIndexMap<_, _> = self
|
||||
.member_constraints
|
||||
.all_indices()
|
||||
.map(|ci| (self.member_constraints[ci].key, ci))
|
||||
.collect();
|
||||
debug!(?member_constraints);
|
||||
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
|
||||
FxIndexMap::default();
|
||||
|
||||
for (opaque_type_key, concrete_type) in opaque_ty_decls {
|
||||
let args = opaque_type_key.args;
|
||||
debug!(?concrete_type, ?args);
|
||||
debug!(?opaque_type_key, ?concrete_type);
|
||||
|
||||
let mut arg_regions = vec![self.universal_regions.fr_static];
|
||||
|
||||
let to_universal_region = |vid, arg_regions: &mut Vec<_>| match self.universal_name(vid)
|
||||
{
|
||||
Some(region) => {
|
||||
let vid = self.universal_regions.to_region_vid(region);
|
||||
arg_regions.push(vid);
|
||||
region
|
||||
}
|
||||
None => {
|
||||
arg_regions.push(vid);
|
||||
ty::Region::new_error_with_message(
|
||||
infcx.tcx,
|
||||
concrete_type.span,
|
||||
"opaque type with non-universal region args",
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
// Start by inserting universal regions from the member_constraint choice regions.
|
||||
// This will ensure they get precedence when folding the regions in the concrete type.
|
||||
if let Some(&ci) = member_constraints.get(&opaque_type_key) {
|
||||
for &vid in self.member_constraints.choice_regions(ci) {
|
||||
to_universal_region(vid, &mut arg_regions);
|
||||
}
|
||||
}
|
||||
debug!(?arg_regions);
|
||||
|
||||
// Next, insert universal regions from args, so we can translate regions that appear
|
||||
// in them but are not subject to member constraints, for instance closure args.
|
||||
let universal_args = infcx.tcx.fold_regions(args, |region, _| {
|
||||
if let ty::RePlaceholder(..) = region.kind() {
|
||||
// Higher kinded regions don't need remapping, they don't refer to anything outside of this the args.
|
||||
return region;
|
||||
}
|
||||
let vid = self.to_region_vid(region);
|
||||
to_universal_region(vid, &mut arg_regions)
|
||||
});
|
||||
debug!(?universal_args);
|
||||
debug!(?arg_regions);
|
||||
|
||||
// Deduplicate the set of regions while keeping the chosen order.
|
||||
let arg_regions = arg_regions.into_iter().collect::<FxIndexSet<_>>();
|
||||
debug!(?arg_regions);
|
||||
|
||||
let universal_concrete_type =
|
||||
infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
|
||||
ty::ReVar(vid) => arg_regions
|
||||
.iter()
|
||||
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
|
||||
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
|
||||
.unwrap_or(infcx.tcx.lifetimes.re_erased),
|
||||
ty::RePlaceholder(_) => ty::Region::new_error_with_message(
|
||||
infcx.tcx,
|
||||
concrete_type.span,
|
||||
"hidden type contains placeholders, we don't support higher kinded opaques yet",
|
||||
),
|
||||
_ => region,
|
||||
});
|
||||
debug!(?universal_concrete_type);
|
||||
let mut arg_regions: Vec<(ty::RegionVid, ty::Region<'_>)> =
|
||||
vec![(self.universal_regions.fr_static, infcx.tcx.lifetimes.re_static)];
|
||||
|
||||
let opaque_type_key =
|
||||
OpaqueTypeKey { def_id: opaque_type_key.def_id, args: universal_args };
|
||||
let ty = infcx.infer_opaque_definition_from_instantiation(
|
||||
opaque_type_key,
|
||||
universal_concrete_type,
|
||||
);
|
||||
opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |region| {
|
||||
// Use the SCC representative instead of directly using `region`.
|
||||
// See [rustc-dev-guide chapter] § "Strict lifetime equality".
|
||||
let scc = self.constraint_sccs.scc(region.as_var());
|
||||
let vid = self.scc_representatives[scc];
|
||||
let named = match self.definitions[vid].origin {
|
||||
// Iterate over all universal regions in a consistent order and find the
|
||||
// *first* equal region. This makes sure that equal lifetimes will have
|
||||
// the same name and simplifies subsequent handling.
|
||||
// See [rustc-dev-guide chapter] § "Semantic lifetime equality".
|
||||
NllRegionVariableOrigin::FreeRegion => self
|
||||
.universal_regions
|
||||
.universal_regions()
|
||||
.filter(|&ur| {
|
||||
// See [rustc-dev-guide chapter] § "Closure restrictions".
|
||||
!matches!(
|
||||
self.universal_regions.region_classification(ur),
|
||||
Some(RegionClassification::External)
|
||||
)
|
||||
})
|
||||
.find(|&ur| self.universal_region_relations.equal(vid, ur))
|
||||
.map(|ur| self.definitions[ur].external_name.unwrap()),
|
||||
NllRegionVariableOrigin::Placeholder(placeholder) => {
|
||||
Some(ty::Region::new_placeholder(infcx.tcx, placeholder))
|
||||
}
|
||||
NllRegionVariableOrigin::Existential { .. } => None,
|
||||
}
|
||||
.unwrap_or_else(|| {
|
||||
ty::Region::new_error_with_message(
|
||||
infcx.tcx,
|
||||
concrete_type.span,
|
||||
"opaque type with non-universal region args",
|
||||
)
|
||||
});
|
||||
|
||||
arg_regions.push((vid, named));
|
||||
named
|
||||
});
|
||||
debug!(?opaque_type_key, ?arg_regions);
|
||||
|
||||
let concrete_type = infcx.tcx.fold_regions(concrete_type, |region, _| {
|
||||
arg_regions
|
||||
.iter()
|
||||
.find(|&&(arg_vid, _)| self.eval_equal(region.as_var(), arg_vid))
|
||||
.map(|&(_, arg_named)| arg_named)
|
||||
.unwrap_or(infcx.tcx.lifetimes.re_erased)
|
||||
});
|
||||
debug!(?concrete_type);
|
||||
|
||||
let ty =
|
||||
infcx.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type);
|
||||
// Sometimes two opaque types are the same only after we remap the generic parameters
|
||||
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
|
||||
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
|
||||
|
|
@ -234,6 +160,29 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
OpaqueHiddenType { ty, span: concrete_type.span },
|
||||
);
|
||||
}
|
||||
|
||||
// Check that all opaque types have the same region parameters if they have the same
|
||||
// non-region parameters. This is necessary because within the new solver we perform
|
||||
// various query operations modulo regions, and thus could unsoundly select some impls
|
||||
// that don't hold.
|
||||
if !ty.references_error()
|
||||
&& let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
|
||||
infcx.tcx.erase_regions(opaque_type_key),
|
||||
(opaque_type_key, concrete_type.span),
|
||||
)
|
||||
&& let Some((arg1, arg2)) = std::iter::zip(
|
||||
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
|
||||
)
|
||||
.find(|(arg1, arg2)| arg1 != arg2)
|
||||
{
|
||||
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
|
||||
arg: arg1,
|
||||
prev: arg2,
|
||||
span: prev_span,
|
||||
prev_span: concrete_type.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
|
@ -422,42 +371,46 @@ fn check_opaque_type_well_formed<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
fn check_opaque_type_parameter_valid(
|
||||
tcx: TyCtxt<'_>,
|
||||
opaque_type_key: OpaqueTypeKey<'_>,
|
||||
/// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
|
||||
///
|
||||
/// [rustc-dev-guide chapter]:
|
||||
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
|
||||
fn check_opaque_type_parameter_valid<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
opaque_type_key: OpaqueTypeKey<'tcx>,
|
||||
span: Span,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
|
||||
let (parent, is_ty_alias) = match opaque_ty_hir.expect_opaque_ty().origin {
|
||||
OpaqueTyOrigin::TyAlias { parent, .. } => (parent, true),
|
||||
OpaqueTyOrigin::AsyncFn(parent) | OpaqueTyOrigin::FnReturn(parent) => (parent, false),
|
||||
};
|
||||
|
||||
let parent_generics = tcx.generics_of(parent);
|
||||
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
|
||||
let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
|
||||
let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
|
||||
|
||||
// Only check the parent generics, which will ignore any of the
|
||||
// duplicated lifetime args that come from reifying late-bounds.
|
||||
for (i, arg) in opaque_type_key.args.iter().take(parent_generics.count()).enumerate() {
|
||||
for (i, arg) in opaque_type_key.iter_captured_args(tcx) {
|
||||
let arg_is_param = match arg.unpack() {
|
||||
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
|
||||
GenericArgKind::Lifetime(lt) if is_ty_alias => {
|
||||
GenericArgKind::Lifetime(lt) => {
|
||||
matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
|
||||
|| (lt.is_static() && opaque_env.param_equal_static(i))
|
||||
}
|
||||
// FIXME(#113916): we can't currently check for unique lifetime params,
|
||||
// see that issue for more. We will also have to ignore unused lifetime
|
||||
// params for RPIT, but that's comparatively trivial ✨
|
||||
GenericArgKind::Lifetime(_) => continue,
|
||||
GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)),
|
||||
};
|
||||
|
||||
if arg_is_param {
|
||||
seen_params.entry(arg).or_default().push(i);
|
||||
// Register if the same lifetime appears multiple times in the generic args.
|
||||
// There is an exception when the opaque type *requires* the lifetimes to be equal.
|
||||
// See [rustc-dev-guide chapter] § "An exception to uniqueness rule".
|
||||
let seen_where = seen_params.entry(arg).or_default();
|
||||
if !seen_where.first().is_some_and(|&prev_i| opaque_env.params_equal(i, prev_i)) {
|
||||
seen_where.push(i);
|
||||
}
|
||||
} else {
|
||||
// Prevent `fn foo() -> Foo<u32>` from being defining.
|
||||
let opaque_param = parent_generics.param_at(i, tcx);
|
||||
let opaque_param = opaque_generics.param_at(i, tcx);
|
||||
let kind = opaque_param.kind.descr();
|
||||
|
||||
if let Err(guar) = opaque_env.param_is_error(i) {
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
|
||||
ty: arg,
|
||||
kind,
|
||||
|
|
@ -469,10 +422,10 @@ fn check_opaque_type_parameter_valid(
|
|||
|
||||
for (_, indices) in seen_params {
|
||||
if indices.len() > 1 {
|
||||
let descr = parent_generics.param_at(indices[0], tcx).kind.descr();
|
||||
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
|
||||
let spans: Vec<_> = indices
|
||||
.into_iter()
|
||||
.map(|i| tcx.def_span(parent_generics.param_at(i, tcx).def_id))
|
||||
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
|
||||
.collect();
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
|
|
@ -486,3 +439,91 @@ fn check_opaque_type_parameter_valid(
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Computes if an opaque type requires a lifetime parameter to be equal to
|
||||
/// another one or to the `'static` lifetime.
|
||||
/// These requirements are derived from the explicit and implied bounds.
|
||||
struct LazyOpaqueTyEnv<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
|
||||
/// Equal parameters will have the same name. Computed Lazily.
|
||||
/// Example:
|
||||
/// `type Opaque<'a: 'static, 'b: 'c, 'c: 'b> = impl Sized;`
|
||||
/// Identity args: `['a, 'b, 'c]`
|
||||
/// Canonical args: `['static, 'b, 'b]`
|
||||
canonical_args: std::cell::OnceCell<ty::GenericArgsRef<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> LazyOpaqueTyEnv<'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
||||
Self { tcx, def_id, canonical_args: std::cell::OnceCell::new() }
|
||||
}
|
||||
|
||||
pub fn param_equal_static(&self, param_index: usize) -> bool {
|
||||
self.get_canonical_args()[param_index].expect_region().is_static()
|
||||
}
|
||||
|
||||
pub fn params_equal(&self, param1: usize, param2: usize) -> bool {
|
||||
let canonical_args = self.get_canonical_args();
|
||||
canonical_args[param1] == canonical_args[param2]
|
||||
}
|
||||
|
||||
pub fn param_is_error(&self, param_index: usize) -> Result<(), ErrorGuaranteed> {
|
||||
self.get_canonical_args()[param_index].error_reported()
|
||||
}
|
||||
|
||||
fn get_canonical_args(&self) -> ty::GenericArgsRef<'tcx> {
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
|
||||
if let Some(&canonical_args) = self.canonical_args.get() {
|
||||
return canonical_args;
|
||||
}
|
||||
|
||||
let &Self { tcx, def_id, .. } = self;
|
||||
let origin = tcx.opaque_type_origin(def_id);
|
||||
let parent = match origin {
|
||||
hir::OpaqueTyOrigin::FnReturn(parent)
|
||||
| hir::OpaqueTyOrigin::AsyncFn(parent)
|
||||
| hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
|
||||
};
|
||||
let param_env = tcx.param_env(parent);
|
||||
let args = GenericArgs::identity_for_item(tcx, parent).extend_to(
|
||||
tcx,
|
||||
def_id.to_def_id(),
|
||||
|param, _| {
|
||||
tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
|
||||
},
|
||||
);
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
|
||||
let wf_tys = ocx.assumed_wf_types(param_env, parent).unwrap_or_else(|_| {
|
||||
tcx.dcx().span_delayed_bug(tcx.def_span(def_id), "error getting implied bounds");
|
||||
Default::default()
|
||||
});
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, parent, &wf_tys);
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
|
||||
let mut seen = vec![tcx.lifetimes.re_static];
|
||||
let canonical_args = tcx.fold_regions(args, |r1, _| {
|
||||
if r1.is_error() {
|
||||
r1
|
||||
} else if let Some(&r2) = seen.iter().find(|&&r2| {
|
||||
let free_regions = outlives_env.free_region_map();
|
||||
free_regions.sub_free_regions(tcx, r1, r2)
|
||||
&& free_regions.sub_free_regions(tcx, r2, r1)
|
||||
}) {
|
||||
r2
|
||||
} else {
|
||||
seen.push(r1);
|
||||
r1
|
||||
}
|
||||
});
|
||||
self.canonical_args.set(canonical_args).unwrap();
|
||||
canonical_args
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use crate::constraints::ConstraintSccIndex;
|
||||
use crate::RegionInferenceContext;
|
||||
use itertools::Itertools;
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::graph::vec_graph::VecGraph;
|
||||
use rustc_data_structures::graph::WithSuccessors;
|
||||
|
|
@ -48,16 +47,16 @@ impl RegionInferenceContext<'_> {
|
|||
.universal_regions
|
||||
.universal_regions()
|
||||
.map(|region| (self.constraint_sccs.scc(region), region))
|
||||
.collect_vec();
|
||||
.collect::<Vec<_>>();
|
||||
paired_scc_regions.sort();
|
||||
let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect();
|
||||
|
||||
let mut scc_regions = FxIndexMap::default();
|
||||
let mut start = 0;
|
||||
for (scc, group) in &paired_scc_regions.into_iter().group_by(|(scc, _)| *scc) {
|
||||
let group_size = group.count();
|
||||
scc_regions.insert(scc, start..start + group_size);
|
||||
start += group_size;
|
||||
for chunk in paired_scc_regions.chunk_by(|&(scc1, _), &(scc2, _)| scc1 == scc2) {
|
||||
let (scc, _) = chunk[0];
|
||||
scc_regions.insert(scc, start..start + chunk.len());
|
||||
start += chunk.len();
|
||||
}
|
||||
|
||||
self.rev_scc_graph = Some(ReverseSccGraph { graph, scc_regions, universal_regions });
|
||||
|
|
|
|||
|
|
@ -164,6 +164,13 @@ impl UniversalRegionRelations<'_> {
|
|||
self.outlives.contains(fr1, fr2)
|
||||
}
|
||||
|
||||
/// Returns `true` if fr1 is known to equal fr2.
|
||||
///
|
||||
/// This will only ever be true for universally quantified regions.
|
||||
pub(crate) fn equal(&self, fr1: RegionVid, fr2: RegionVid) -> bool {
|
||||
self.outlives.contains(fr1, fr2) && self.outlives.contains(fr2, fr1)
|
||||
}
|
||||
|
||||
/// Returns a vector of free regions `x` such that `fr1: x` is
|
||||
/// known to hold.
|
||||
pub(crate) fn regions_outlived_by(&self, fr1: RegionVid) -> Vec<RegionVid> {
|
||||
|
|
|
|||
|
|
@ -229,6 +229,22 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
|||
);
|
||||
}
|
||||
|
||||
// Convert all regions to nll vars.
|
||||
let (opaque_type_key, hidden_type) =
|
||||
infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| {
|
||||
match region.kind() {
|
||||
ty::ReVar(_) => region,
|
||||
ty::RePlaceholder(placeholder) => checker
|
||||
.borrowck_context
|
||||
.constraints
|
||||
.placeholder_region(infcx, placeholder),
|
||||
_ => ty::Region::new_var(
|
||||
infcx.tcx,
|
||||
checker.borrowck_context.universal_regions.to_region_vid(region),
|
||||
),
|
||||
}
|
||||
});
|
||||
|
||||
(opaque_type_key, hidden_type)
|
||||
})
|
||||
.collect();
|
||||
|
|
|
|||
|
|
@ -41,21 +41,6 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR
|
|||
# missing features
|
||||
# ================
|
||||
|
||||
# requires stack unwinding
|
||||
# FIXME add needs-unwind to these tests
|
||||
rm -r tests/run-make/libtest-junit
|
||||
rm tests/ui/asm/may_unwind.rs
|
||||
rm tests/ui/stable-mir-print/basic_function.rs
|
||||
|
||||
# extra warning about -Cpanic=abort for proc macros
|
||||
rm tests/ui/proc-macro/crt-static.rs
|
||||
rm tests/ui/proc-macro/proc-macro-deprecated-attr.rs
|
||||
rm tests/ui/proc-macro/quote-debug.rs
|
||||
rm tests/ui/proc-macro/no-missing-docs.rs
|
||||
rm tests/ui/rust-2018/proc-macro-crate-in-paths.rs
|
||||
rm tests/ui/proc-macro/allowed-signatures.rs
|
||||
rm tests/ui/proc-macro/no-mangle-in-proc-macro-issue-111888.rs
|
||||
|
||||
# vendor intrinsics
|
||||
rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant"
|
||||
rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic
|
||||
|
|
@ -154,7 +139,6 @@ rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug
|
|||
# ======================
|
||||
rm tests/ui/backtrace.rs # TODO warning
|
||||
rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
|
||||
rm tests/ui/async-await/async-closures/once.rs # FIXME bug in the rustc FnAbi calculation code
|
||||
|
||||
rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use rustc_middle::ty::layout::{
|
|||
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
|
||||
};
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::Span;
|
||||
use rustc_symbol_mangling::typeid::{
|
||||
kcfi_typeid_for_fnabi, kcfi_typeid_for_instance, typeid_for_fnabi, typeid_for_instance,
|
||||
|
|
@ -551,6 +552,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
layout: TyAndLayout<'tcx>,
|
||||
offset: Size,
|
||||
) {
|
||||
if bx.cx.sess().opts.optimize == OptLevel::No {
|
||||
// Don't emit metadata we're not going to use
|
||||
return;
|
||||
}
|
||||
|
||||
if !scalar.is_uninit_valid() {
|
||||
bx.noundef_metadata(load);
|
||||
}
|
||||
|
|
@ -667,6 +673,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
if self.cx.sess().opts.optimize == OptLevel::No {
|
||||
// Don't emit metadata we're not going to use
|
||||
return;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let llty = self.cx.val_ty(load);
|
||||
let v = [
|
||||
|
|
@ -1630,7 +1641,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
let typeid = if let Some(instance) = instance {
|
||||
typeid_for_instance(self.tcx, &instance, options)
|
||||
typeid_for_instance(self.tcx, instance, options)
|
||||
} else {
|
||||
typeid_for_fnabi(self.tcx, fn_abi, options)
|
||||
};
|
||||
|
|
@ -1678,7 +1689,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
let kcfi_typeid = if let Some(instance) = instance {
|
||||
kcfi_typeid_for_instance(self.tcx, &instance, options)
|
||||
kcfi_typeid_for_instance(self.tcx, instance, options)
|
||||
} else {
|
||||
kcfi_typeid_for_fnabi(self.tcx, fn_abi, options)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -141,17 +141,17 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
|
||||
if self.tcx.sess.is_sanitizer_cfi_enabled() {
|
||||
if let Some(instance) = instance {
|
||||
let typeid = typeid_for_instance(self.tcx, &instance, TypeIdOptions::empty());
|
||||
let typeid = typeid_for_instance(self.tcx, instance, TypeIdOptions::empty());
|
||||
self.set_type_metadata(llfn, typeid);
|
||||
let typeid =
|
||||
typeid_for_instance(self.tcx, &instance, TypeIdOptions::GENERALIZE_POINTERS);
|
||||
typeid_for_instance(self.tcx, instance, TypeIdOptions::GENERALIZE_POINTERS);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
let typeid =
|
||||
typeid_for_instance(self.tcx, &instance, TypeIdOptions::NORMALIZE_INTEGERS);
|
||||
typeid_for_instance(self.tcx, instance, TypeIdOptions::NORMALIZE_INTEGERS);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
let typeid = typeid_for_instance(
|
||||
self.tcx,
|
||||
&instance,
|
||||
instance,
|
||||
TypeIdOptions::GENERALIZE_POINTERS | TypeIdOptions::NORMALIZE_INTEGERS,
|
||||
);
|
||||
self.add_type_metadata(llfn, typeid);
|
||||
|
|
@ -182,7 +182,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
|
||||
if let Some(instance) = instance {
|
||||
let kcfi_typeid = kcfi_typeid_for_instance(self.tcx, &instance, options);
|
||||
let kcfi_typeid = kcfi_typeid_for_instance(self.tcx, instance, options);
|
||||
self.set_kcfi_type_metadata(llfn, kcfi_typeid);
|
||||
} else {
|
||||
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi, options);
|
||||
|
|
|
|||
|
|
@ -592,7 +592,7 @@ fn produce_final_output_artifacts(
|
|||
.unwrap()
|
||||
.to_owned();
|
||||
|
||||
if crate_output.outputs.contains_key(&output_type) {
|
||||
if crate_output.outputs.contains_explicit_name(&output_type) {
|
||||
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
|
||||
// no good solution for this case, so warn the user.
|
||||
sess.dcx().emit_warn(errors::IgnoringEmitPath { extension });
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ const_eval_intern_kind = {$kind ->
|
|||
*[other] {""}
|
||||
}
|
||||
|
||||
const_eval_interrupted = compilation was interrupted
|
||||
|
||||
const_eval_invalid_align_details =
|
||||
invalid align passed to `{$name}`: {$align} is {$err_kind ->
|
||||
[not_power_of_two] not a power of 2
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::sync::atomic::Ordering::Relaxed;
|
||||
|
||||
use either::{Left, Right};
|
||||
|
||||
use rustc_hir::def::DefKind;
|
||||
|
|
@ -22,6 +24,7 @@ use crate::interpret::{
|
|||
InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking,
|
||||
StackPopCleanup,
|
||||
};
|
||||
use crate::CTRL_C_RECEIVED;
|
||||
|
||||
// Returns a pointer to where the result lives
|
||||
#[instrument(level = "trace", skip(ecx, body))]
|
||||
|
|
@ -79,7 +82,11 @@ fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>(
|
|||
ecx.storage_live_for_always_live_locals()?;
|
||||
|
||||
// The main interpreter loop.
|
||||
while ecx.step()? {}
|
||||
while ecx.step()? {
|
||||
if CTRL_C_RECEIVED.load(Relaxed) {
|
||||
throw_exhaust!(Interrupted);
|
||||
}
|
||||
}
|
||||
|
||||
// Intern the result
|
||||
intern_const_alloc_recursive(ecx, intern_kind, &ret)?;
|
||||
|
|
|
|||
|
|
@ -884,6 +884,7 @@ impl ReportErrorExt for ResourceExhaustionInfo {
|
|||
ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
|
||||
ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted,
|
||||
ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full,
|
||||
ResourceExhaustionInfo::Interrupted => const_eval_interrupted,
|
||||
}
|
||||
}
|
||||
fn add_args<G: EmissionGuarantee>(self, _: &mut Diag<'_, G>) {}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ pub mod interpret;
|
|||
pub mod transform;
|
||||
pub mod util;
|
||||
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
pub use errors::ReportErrorExt;
|
||||
|
||||
use rustc_middle::{ty, util::Providers};
|
||||
|
|
@ -58,3 +60,8 @@ pub fn provide(providers: &mut Providers) {
|
|||
util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
|
||||
};
|
||||
}
|
||||
|
||||
/// `rustc_driver::main` installs a handler that will set this to `true` if
|
||||
/// the compiler has been sent a request to shut down, such as by a Ctrl-C.
|
||||
/// This static lives here because it is only read by the interpreter.
|
||||
pub static CTRL_C_RECEIVED: AtomicBool = AtomicBool::new(false);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
ctrlc = "3.4.4"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_lowering = { path = "../rustc_ast_lowering" }
|
||||
rustc_ast_passes = { path = "../rustc_ast_passes" }
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ extern crate tracing;
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
|
||||
use rustc_const_eval::CTRL_C_RECEIVED;
|
||||
use rustc_data_structures::profiling::{
|
||||
get_resident_set_size, print_time_passes_entry, TimePassesFormat,
|
||||
};
|
||||
|
|
@ -1518,6 +1519,22 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Install our usual `ctrlc` handler, which sets [`rustc_const_eval::CTRL_C_RECEIVED`].
|
||||
/// Making this handler optional lets tools can install a different handler, if they wish.
|
||||
pub fn install_ctrlc_handler() {
|
||||
ctrlc::set_handler(move || {
|
||||
// Indicate that we have been signaled to stop. If we were already signaled, exit
|
||||
// immediately. In our interpreter loop we try to consult this value often, but if for
|
||||
// whatever reason we don't get to that check or the cleanup we do upon finding that
|
||||
// this bool has become true takes a long time, the exit here will promptly exit the
|
||||
// process on the second Ctrl-C.
|
||||
if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
})
|
||||
.expect("Unable to install ctrlc handler");
|
||||
}
|
||||
|
||||
pub fn main() -> ! {
|
||||
let start_time = Instant::now();
|
||||
let start_rss = get_resident_set_size();
|
||||
|
|
@ -1528,6 +1545,8 @@ pub fn main() -> ! {
|
|||
signal_handler::install();
|
||||
let mut callbacks = TimePassesCallbacks::default();
|
||||
let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ());
|
||||
install_ctrlc_handler();
|
||||
|
||||
let exit_code = catch_with_exit_code(|| {
|
||||
RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks)
|
||||
.set_using_internal_features(using_internal_features)
|
||||
|
|
|
|||
|
|
@ -793,12 +793,20 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
fd: &'tcx hir::FnDecl<'tcx>,
|
||||
body_id: hir::BodyId,
|
||||
_: Span,
|
||||
_: LocalDefId,
|
||||
def_id: LocalDefId,
|
||||
) {
|
||||
let output = match fd.output {
|
||||
hir::FnRetTy::DefaultReturn(_) => None,
|
||||
hir::FnRetTy::Return(ty) => Some(ty),
|
||||
};
|
||||
if let Some(ty) = output
|
||||
&& let hir::TyKind::InferDelegation(sig_id, _) = ty.kind
|
||||
{
|
||||
let bound_vars: Vec<_> =
|
||||
self.tcx.fn_sig(sig_id).skip_binder().bound_vars().iter().collect();
|
||||
let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
|
||||
self.map.late_bound_vars.insert(hir_id, bound_vars);
|
||||
}
|
||||
self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure));
|
||||
intravisit::walk_fn_kind(self, fk);
|
||||
self.visit_nested_body(body_id)
|
||||
|
|
|
|||
|
|
@ -2492,13 +2492,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
hir_ty: Option<&hir::Ty<'_>>,
|
||||
) -> ty::PolyFnSig<'tcx> {
|
||||
let tcx = self.tcx();
|
||||
let bound_vars = if let hir::FnRetTy::Return(ret_ty) = decl.output
|
||||
&& let hir::TyKind::InferDelegation(sig_id, _) = ret_ty.kind
|
||||
{
|
||||
tcx.fn_sig(sig_id).skip_binder().bound_vars()
|
||||
} else {
|
||||
tcx.late_bound_vars(hir_id)
|
||||
};
|
||||
let bound_vars = tcx.late_bound_vars(hir_id);
|
||||
debug!(?bound_vars);
|
||||
|
||||
// We proactively collect all the inferred type params to emit a single error per fn def.
|
||||
|
|
|
|||
|
|
@ -919,8 +919,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0533, expected);
|
||||
return Ty::new_error(tcx, e);
|
||||
}
|
||||
Res::SelfCtor(..)
|
||||
| Res::Def(
|
||||
Res::SelfCtor(def_id) => {
|
||||
if let ty::Adt(adt_def, _) = *tcx.type_of(def_id).skip_binder().kind()
|
||||
&& adt_def.is_struct()
|
||||
&& let Some((CtorKind::Const, _)) = adt_def.non_enum_variant().ctor
|
||||
{
|
||||
// Ok, we allow unit struct ctors in patterns only.
|
||||
} else {
|
||||
let e = report_unexpected_variant_res(
|
||||
tcx,
|
||||
res,
|
||||
qpath,
|
||||
pat.span,
|
||||
E0533,
|
||||
"unit struct",
|
||||
);
|
||||
return Ty::new_error(tcx, e);
|
||||
}
|
||||
}
|
||||
Res::Def(
|
||||
DefKind::Ctor(_, CtorKind::Const)
|
||||
| DefKind::Const
|
||||
| DefKind::AssocConst
|
||||
|
|
|
|||
|
|
@ -73,10 +73,10 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
|
|||
|
||||
self.inlined_check_id(id);
|
||||
debug!("early context: enter_attrs({:?})", attrs);
|
||||
lint_callback!(self, enter_lint_attrs, attrs);
|
||||
lint_callback!(self, check_attributes, attrs);
|
||||
ensure_sufficient_stack(|| f(self));
|
||||
debug!("early context: exit_attrs({:?})", attrs);
|
||||
lint_callback!(self, exit_lint_attrs, attrs);
|
||||
lint_callback!(self, check_attributes_post, attrs);
|
||||
self.context.builder.pop(push);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
//! for all lint attributes.
|
||||
|
||||
use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::sync::{join, Lrc};
|
||||
use rustc_hir as hir;
|
||||
|
|
@ -62,13 +61,13 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> {
|
|||
let prev = self.context.last_node_with_lint_attrs;
|
||||
self.context.last_node_with_lint_attrs = id;
|
||||
debug!("late context: enter_attrs({:?})", attrs);
|
||||
lint_callback!(self, enter_lint_attrs, attrs);
|
||||
lint_callback!(self, check_attributes, attrs);
|
||||
for attr in attrs {
|
||||
lint_callback!(self, check_attribute, attr);
|
||||
}
|
||||
f(self);
|
||||
debug!("late context: exit_attrs({:?})", attrs);
|
||||
lint_callback!(self, exit_lint_attrs, attrs);
|
||||
lint_callback!(self, check_attributes_post, attrs);
|
||||
self.context.last_node_with_lint_attrs = prev;
|
||||
}
|
||||
|
||||
|
|
@ -310,10 +309,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas
|
|||
lint_callback!(self, check_path, p, id);
|
||||
hir_visit::walk_path(self, p);
|
||||
}
|
||||
|
||||
fn visit_attribute(&mut self, attr: &'tcx ast::Attribute) {
|
||||
lint_callback!(self, check_attribute, attr);
|
||||
}
|
||||
}
|
||||
|
||||
// Combines multiple lint passes into a single pass, at runtime. Each
|
||||
|
|
|
|||
|
|
@ -41,13 +41,8 @@ macro_rules! late_lint_methods {
|
|||
fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>);
|
||||
fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId);
|
||||
fn check_attribute(a: &'tcx rustc_ast::Attribute);
|
||||
|
||||
/// Called when entering a syntax node that can have lint attributes such
|
||||
/// as `#[allow(...)]`. Called with *all* the attributes of that node.
|
||||
fn enter_lint_attrs(a: &'tcx [rustc_ast::Attribute]);
|
||||
|
||||
/// Counterpart to `enter_lint_attrs`.
|
||||
fn exit_lint_attrs(a: &'tcx [rustc_ast::Attribute]);
|
||||
fn check_attributes(a: &'tcx [rustc_ast::Attribute]);
|
||||
fn check_attributes_post(a: &'tcx [rustc_ast::Attribute]);
|
||||
]);
|
||||
)
|
||||
}
|
||||
|
|
@ -162,16 +157,11 @@ macro_rules! early_lint_methods {
|
|||
fn check_impl_item(a: &rustc_ast::AssocItem);
|
||||
fn check_variant(a: &rustc_ast::Variant);
|
||||
fn check_attribute(a: &rustc_ast::Attribute);
|
||||
fn check_attributes(a: &[rustc_ast::Attribute]);
|
||||
fn check_attributes_post(a: &[rustc_ast::Attribute]);
|
||||
fn check_mac_def(a: &rustc_ast::MacroDef);
|
||||
fn check_mac(a: &rustc_ast::MacCall);
|
||||
|
||||
/// Called when entering a syntax node that can have lint attributes such
|
||||
/// as `#[allow(...)]`. Called with *all* the attributes of that node.
|
||||
fn enter_lint_attrs(a: &[rustc_ast::Attribute]);
|
||||
|
||||
/// Counterpart to `enter_lint_attrs`.
|
||||
fn exit_lint_attrs(a: &[rustc_ast::Attribute]);
|
||||
|
||||
fn enter_where_predicate(a: &rustc_ast::WherePredicate);
|
||||
fn exit_where_predicate(a: &rustc_ast::WherePredicate);
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -482,6 +482,8 @@ pub enum ResourceExhaustionInfo {
|
|||
MemoryExhausted,
|
||||
/// The address space (of the target) is full.
|
||||
AddressSpaceFull,
|
||||
/// The compiler got an interrupt signal (a user ran out of patience).
|
||||
Interrupted,
|
||||
}
|
||||
|
||||
/// A trait for machine-specific errors (or other "machine stop" conditions).
|
||||
|
|
|
|||
|
|
@ -335,7 +335,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
|||
|
||||
fn fmt_instance(
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
instance: &Instance<'_>,
|
||||
instance: Instance<'_>,
|
||||
type_length: Option<rustc_session::Limit>,
|
||||
) -> fmt::Result {
|
||||
ty::tls::with(|tcx| {
|
||||
|
|
@ -369,9 +369,9 @@ fn fmt_instance(
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ShortInstance<'a, 'tcx>(pub &'a Instance<'tcx>, pub usize);
|
||||
pub struct ShortInstance<'tcx>(pub Instance<'tcx>, pub usize);
|
||||
|
||||
impl<'a, 'tcx> fmt::Display for ShortInstance<'a, 'tcx> {
|
||||
impl<'tcx> fmt::Display for ShortInstance<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt_instance(f, self.0, Some(rustc_session::Limit(self.1)))
|
||||
}
|
||||
|
|
@ -379,7 +379,7 @@ impl<'a, 'tcx> fmt::Display for ShortInstance<'a, 'tcx> {
|
|||
|
||||
impl<'tcx> fmt::Display for Instance<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt_instance(f, self, None)
|
||||
fmt_instance(f, *self, None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -832,6 +832,38 @@ pub struct OpaqueTypeKey<'tcx> {
|
|||
pub args: GenericArgsRef<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeKey<'tcx> {
|
||||
pub fn iter_captured_args(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> impl Iterator<Item = (usize, GenericArg<'tcx>)> {
|
||||
std::iter::zip(self.args, tcx.variances_of(self.def_id)).enumerate().filter_map(
|
||||
|(i, (arg, v))| match (arg.unpack(), v) {
|
||||
(_, ty::Invariant) => Some((i, arg)),
|
||||
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => None,
|
||||
_ => bug!("unexpected opaque type arg variance"),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn fold_captured_lifetime_args(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut f: impl FnMut(Region<'tcx>) -> Region<'tcx>,
|
||||
) -> Self {
|
||||
let Self { def_id, args } = self;
|
||||
let args = std::iter::zip(args, tcx.variances_of(def_id)).map(|(arg, v)| {
|
||||
match (arg.unpack(), v) {
|
||||
(ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
|
||||
(ty::GenericArgKind::Lifetime(lt), _) => f(lt).into(),
|
||||
_ => arg,
|
||||
}
|
||||
});
|
||||
let args = tcx.mk_args_from_iter(args);
|
||||
Self { def_id, args }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
|
||||
pub struct OpaqueHiddenType<'tcx> {
|
||||
/// The span of this particular definition of the opaque type. So
|
||||
|
|
|
|||
|
|
@ -804,7 +804,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
}
|
||||
ty::Str => p!("str"),
|
||||
ty::Coroutine(did, args) => {
|
||||
p!(write("{{"));
|
||||
p!("{{");
|
||||
let coroutine_kind = self.tcx().coroutine_kind(did).unwrap();
|
||||
let should_print_movability = self.should_print_verbose()
|
||||
|| matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
|
||||
|
|
@ -818,9 +818,17 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
|
||||
if !self.should_print_verbose() {
|
||||
p!(write("{}", coroutine_kind));
|
||||
// FIXME(eddyb) should use `def_span`.
|
||||
if let Some(did) = did.as_local() {
|
||||
let span = self.tcx().def_span(did);
|
||||
if coroutine_kind.is_fn_like() {
|
||||
// If we are printing an `async fn` coroutine type, then give the path
|
||||
// of the fn, instead of its span, because that will in most cases be
|
||||
// more helpful for the reader than just a source location.
|
||||
//
|
||||
// This will look like:
|
||||
// {async fn body of some_fn()}
|
||||
let did_of_the_fn_item = self.tcx().parent(did);
|
||||
p!(" of ", print_def_path(did_of_the_fn_item, args), "()");
|
||||
} else if let Some(local_did) = did.as_local() {
|
||||
let span = self.tcx().def_span(local_did);
|
||||
p!(write(
|
||||
"@{}",
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
|
|
@ -828,7 +836,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
self.tcx().sess.source_map().span_to_embeddable_string(span)
|
||||
));
|
||||
} else {
|
||||
p!(write("@"), print_def_path(did, args));
|
||||
p!("@", print_def_path(did, args));
|
||||
}
|
||||
} else {
|
||||
p!(print_def_path(did, args));
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
caller_body: &mut Body<'tcx>,
|
||||
callsite: &CallSite<'tcx>,
|
||||
) -> Result<std::ops::Range<BasicBlock>, &'static str> {
|
||||
self.check_mir_is_available(caller_body, &callsite.callee)?;
|
||||
self.check_mir_is_available(caller_body, callsite.callee)?;
|
||||
|
||||
let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id());
|
||||
let cross_crate_inlinable = self.tcx.cross_crate_inlinable(callsite.callee.def_id());
|
||||
|
|
@ -298,7 +298,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
fn check_mir_is_available(
|
||||
&self,
|
||||
caller_body: &Body<'tcx>,
|
||||
callee: &Instance<'tcx>,
|
||||
callee: Instance<'tcx>,
|
||||
) -> Result<(), &'static str> {
|
||||
let caller_def_id = caller_body.source.def_id();
|
||||
let callee_def_id = callee.def_id();
|
||||
|
|
@ -354,7 +354,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
|
||||
// If we know for sure that the function we're calling will itself try to
|
||||
// call us, then we avoid inlining that function.
|
||||
if self.tcx.mir_callgraph_reachable((*callee, caller_def_id.expect_local())) {
|
||||
if self.tcx.mir_callgraph_reachable((callee, caller_def_id.expect_local())) {
|
||||
return Err("caller might be reachable from callee (query cycle avoidance)");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ fn collect_items_rec<'tcx>(
|
|||
let instance = Instance::mono(tcx, def_id);
|
||||
|
||||
// Sanity check whether this ended up being collected accidentally
|
||||
debug_assert!(should_codegen_locally(tcx, &instance));
|
||||
debug_assert!(should_codegen_locally(tcx, instance));
|
||||
|
||||
let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
|
||||
// Nested statics have no type.
|
||||
|
|
@ -429,7 +429,7 @@ fn collect_items_rec<'tcx>(
|
|||
}
|
||||
MonoItem::Fn(instance) => {
|
||||
// Sanity check whether this ended up being collected accidentally
|
||||
debug_assert!(should_codegen_locally(tcx, &instance));
|
||||
debug_assert!(should_codegen_locally(tcx, instance));
|
||||
|
||||
// Keep track of the monomorphization recursion depth
|
||||
recursion_depth_reset = Some(check_recursion_limit(
|
||||
|
|
@ -474,7 +474,7 @@ fn collect_items_rec<'tcx>(
|
|||
}
|
||||
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
|
||||
let instance = Instance::mono(tcx, *def_id);
|
||||
if should_codegen_locally(tcx, &instance) {
|
||||
if should_codegen_locally(tcx, instance) {
|
||||
trace!("collecting static {:?}", def_id);
|
||||
used_items.push(dummy_spanned(MonoItem::Static(*def_id)));
|
||||
}
|
||||
|
|
@ -557,7 +557,7 @@ fn collect_items_rec<'tcx>(
|
|||
/// If the type name is longer than before+after, it will be written to a file.
|
||||
fn shrunk_instance_name<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: &Instance<'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
) -> (String, Option<PathBuf>) {
|
||||
let s = instance.to_string();
|
||||
|
||||
|
|
@ -603,7 +603,7 @@ fn check_recursion_limit<'tcx>(
|
|||
if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
|
||||
let def_span = tcx.def_span(def_id);
|
||||
let def_path_str = tcx.def_path_str(def_id);
|
||||
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance);
|
||||
let (shrunk, written_to_path) = shrunk_instance_name(tcx, instance);
|
||||
let mut path = PathBuf::new();
|
||||
let was_written = if let Some(written_to_path) = written_to_path {
|
||||
path = written_to_path;
|
||||
|
|
@ -645,7 +645,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
|
|||
//
|
||||
// Bail out in these cases to avoid that bad user experience.
|
||||
if !tcx.type_length_limit().value_within_limit(type_length) {
|
||||
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance);
|
||||
let (shrunk, written_to_path) = shrunk_instance_name(tcx, instance);
|
||||
let span = tcx.def_span(instance.def_id());
|
||||
let mut path = PathBuf::new();
|
||||
let was_written = if let Some(path2) = written_to_path {
|
||||
|
|
@ -892,7 +892,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
if let ty::Closure(def_id, args) = *source_ty.kind() {
|
||||
let instance =
|
||||
Instance::resolve_closure(self.tcx, def_id, args, ty::ClosureKind::FnOnce);
|
||||
if should_codegen_locally(self.tcx, &instance) {
|
||||
if should_codegen_locally(self.tcx, instance) {
|
||||
self.used_items.push(create_fn_mono_item(self.tcx, instance, span));
|
||||
}
|
||||
} else {
|
||||
|
|
@ -902,7 +902,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
mir::Rvalue::ThreadLocalRef(def_id) => {
|
||||
assert!(self.tcx.is_thread_local_static(def_id));
|
||||
let instance = Instance::mono(self.tcx, def_id);
|
||||
if should_codegen_locally(self.tcx, &instance) {
|
||||
if should_codegen_locally(self.tcx, instance) {
|
||||
trace!("collecting thread-local static {:?}", def_id);
|
||||
self.used_items.push(respan(span, MonoItem::Static(def_id)));
|
||||
}
|
||||
|
|
@ -929,7 +929,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
let tcx = self.tcx;
|
||||
let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| {
|
||||
let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
|
||||
if should_codegen_locally(tcx, &instance) {
|
||||
if should_codegen_locally(tcx, instance) {
|
||||
this.used_items.push(create_fn_mono_item(tcx, instance, source));
|
||||
}
|
||||
};
|
||||
|
|
@ -962,7 +962,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
}
|
||||
mir::InlineAsmOperand::SymStatic { def_id } => {
|
||||
let instance = Instance::mono(self.tcx, def_id);
|
||||
if should_codegen_locally(self.tcx, &instance) {
|
||||
if should_codegen_locally(self.tcx, instance) {
|
||||
trace!("collecting asm sym static {:?}", def_id);
|
||||
self.used_items.push(respan(source, MonoItem::Static(def_id)));
|
||||
}
|
||||
|
|
@ -1051,7 +1051,7 @@ fn visit_instance_use<'tcx>(
|
|||
output: &mut MonoItems<'tcx>,
|
||||
) {
|
||||
debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
|
||||
if !should_codegen_locally(tcx, &instance) {
|
||||
if !should_codegen_locally(tcx, instance) {
|
||||
return;
|
||||
}
|
||||
if let ty::InstanceDef::Intrinsic(def_id) = instance.def {
|
||||
|
|
@ -1063,13 +1063,13 @@ fn visit_instance_use<'tcx>(
|
|||
// codegen a call to that function without generating code for the function itself.
|
||||
let def_id = tcx.lang_items().get(LangItem::PanicNounwind).unwrap();
|
||||
let panic_instance = Instance::mono(tcx, def_id);
|
||||
if should_codegen_locally(tcx, &panic_instance) {
|
||||
if should_codegen_locally(tcx, panic_instance) {
|
||||
output.push(create_fn_mono_item(tcx, panic_instance, source));
|
||||
}
|
||||
} else if tcx.has_attr(def_id, sym::rustc_intrinsic) {
|
||||
// Codegen the fallback body of intrinsics with fallback bodies
|
||||
let instance = ty::Instance::new(def_id, instance.args);
|
||||
if should_codegen_locally(tcx, &instance) {
|
||||
if should_codegen_locally(tcx, instance) {
|
||||
output.push(create_fn_mono_item(tcx, instance, source));
|
||||
}
|
||||
}
|
||||
|
|
@ -1107,7 +1107,7 @@ fn visit_instance_use<'tcx>(
|
|||
|
||||
/// Returns `true` if we should codegen an instance in the local crate, or returns `false` if we
|
||||
/// can just link to the upstream crate and therefore don't need a mono item.
|
||||
pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> bool {
|
||||
pub(crate) fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
|
||||
let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else {
|
||||
return true;
|
||||
};
|
||||
|
|
@ -1304,7 +1304,7 @@ fn create_mono_items_for_vtable_methods<'tcx>(
|
|||
None
|
||||
}
|
||||
VtblEntry::Method(instance) => {
|
||||
Some(*instance).filter(|instance| should_codegen_locally(tcx, instance))
|
||||
Some(*instance).filter(|instance| should_codegen_locally(tcx, *instance))
|
||||
}
|
||||
})
|
||||
.map(|item| create_fn_mono_item(tcx, item, source));
|
||||
|
|
@ -1321,7 +1321,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
|
|||
GlobalAlloc::Static(def_id) => {
|
||||
assert!(!tcx.is_thread_local_static(def_id));
|
||||
let instance = Instance::mono(tcx, def_id);
|
||||
if should_codegen_locally(tcx, &instance) {
|
||||
if should_codegen_locally(tcx, instance) {
|
||||
trace!("collecting static {:?}", def_id);
|
||||
output.push(dummy_spanned(MonoItem::Static(def_id)));
|
||||
}
|
||||
|
|
@ -1339,7 +1339,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
|
|||
}
|
||||
}
|
||||
GlobalAlloc::Function(fn_instance) => {
|
||||
if should_codegen_locally(tcx, &fn_instance) {
|
||||
if should_codegen_locally(tcx, fn_instance) {
|
||||
trace!("collecting {:?} with {:#?}", alloc_id, fn_instance);
|
||||
output.push(create_fn_mono_item(tcx, fn_instance, DUMMY_SP));
|
||||
}
|
||||
|
|
@ -1474,7 +1474,7 @@ fn visit_mentioned_item<'tcx>(
|
|||
if let ty::Closure(def_id, args) = *source_ty.kind() {
|
||||
let instance =
|
||||
Instance::resolve_closure(tcx, def_id, args, ty::ClosureKind::FnOnce);
|
||||
if should_codegen_locally(tcx, &instance) {
|
||||
if should_codegen_locally(tcx, instance) {
|
||||
output.push(create_fn_mono_item(tcx, instance, span));
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1736,7 +1736,7 @@ fn create_mono_items_for_default_impls<'tcx>(
|
|||
let instance = ty::Instance::expect_resolve(tcx, param_env, method.def_id, args);
|
||||
|
||||
let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
|
||||
if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) {
|
||||
if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, instance) {
|
||||
output.push(mono_item);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
|
|||
!instance.def_id().is_local()
|
||||
&& tcx.is_compiler_builtins(LOCAL_CRATE)
|
||||
&& tcx.codegen_fn_attrs(instance.def_id()).link_name.is_none()
|
||||
&& !should_codegen_locally(tcx, &instance)
|
||||
&& !should_codegen_locally(tcx, instance)
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
// Finds items that are externally reachable, to determine which items
|
||||
// need to have their metadata (and possibly their AST) serialized.
|
||||
// All items that can be referred to through an exported name are
|
||||
// reachable, and when a reachable thing is inline or generic, it
|
||||
// makes all other generics or inline functions that it references
|
||||
// reachable as well.
|
||||
//! Finds local items that are externally reachable, which means that other crates need access to
|
||||
//! their compiled machine code or their MIR.
|
||||
//!
|
||||
//! An item is "externally reachable" if it is relevant for other crates. This obviously includes
|
||||
//! all public items. However, some of these items cannot be compiled to machine code (because they
|
||||
//! are generic), and for some the machine code is not sufficient (because we want to cross-crate
|
||||
//! inline them). These items "need cross-crate MIR". When a reachable function `f` needs
|
||||
//! cross-crate MIR, then all the functions it calls also become reachable, as they will be
|
||||
//! necessary to use the MIR of `f` from another crate. Furthermore, an item can become "externally
|
||||
//! reachable" by having a `const`/`const fn` return a pointer to that item, so we also need to
|
||||
//! recurse into reachable `const`/`const fn`.
|
||||
|
||||
use hir::def_id::LocalDefIdSet;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
|
|
@ -21,7 +26,9 @@ use rustc_privacy::DefIdVisitor;
|
|||
use rustc_session::config::CrateType;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
fn item_might_be_inlined(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
/// Determines whether this item is recursive for reachability. See `is_recursively_reachable_local`
|
||||
/// below for details.
|
||||
fn recursively_reachable(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
tcx.generics_of(def_id).requires_monomorphization(tcx)
|
||||
|| tcx.cross_crate_inlinable(def_id)
|
||||
|| tcx.is_const_fn(def_id)
|
||||
|
|
@ -54,12 +61,20 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
|
|||
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
||||
let res = match expr.kind {
|
||||
hir::ExprKind::Path(ref qpath) => {
|
||||
// This covers fn ptr casts but also "non-method" calls.
|
||||
Some(self.typeck_results().qpath_res(qpath, expr.hir_id))
|
||||
}
|
||||
hir::ExprKind::MethodCall(..) => self
|
||||
.typeck_results()
|
||||
.type_dependent_def(expr.hir_id)
|
||||
.map(|(kind, def_id)| Res::Def(kind, def_id)),
|
||||
hir::ExprKind::MethodCall(..) => {
|
||||
// Method calls don't involve a full "path", so we need to determine the callee
|
||||
// based on the receiver type.
|
||||
// If this is a method call on a generic type, we might not be able to find the
|
||||
// callee. That's why `reachable_set` also adds all potential callees for such
|
||||
// calls, i.e. all trait impl items, to the reachable set. So here we only worry
|
||||
// about the calls we can identify.
|
||||
self.typeck_results()
|
||||
.type_dependent_def(expr.hir_id)
|
||||
.map(|(kind, def_id)| Res::Def(kind, def_id))
|
||||
}
|
||||
hir::ExprKind::Closure(&hir::Closure { def_id, .. }) => {
|
||||
self.reachable_symbols.insert(def_id);
|
||||
None
|
||||
|
|
@ -96,16 +111,24 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
.expect("`ReachableContext::typeck_results` called outside of body")
|
||||
}
|
||||
|
||||
// Returns true if the given def ID represents a local item that is
|
||||
// eligible for inlining and false otherwise.
|
||||
fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
|
||||
/// Returns true if the given def ID represents a local item that is recursive for reachability,
|
||||
/// i.e. whether everything mentioned in here also needs to be considered reachable.
|
||||
///
|
||||
/// There are two reasons why an item may be recursively reachable:
|
||||
/// - It needs cross-crate MIR (see the module-level doc comment above).
|
||||
/// - It is a `const` or `const fn`. This is *not* because we need the MIR to interpret them
|
||||
/// (MIR for const-eval and MIR for codegen is separate, and MIR for const-eval is always
|
||||
/// encoded). Instead, it is because `const fn` can create `fn()` pointers to other items
|
||||
/// which end up in the evaluated result of the constant and can then be called from other
|
||||
/// crates. Those items must be considered reachable.
|
||||
fn is_recursively_reachable_local(&self, def_id: DefId) -> bool {
|
||||
let Some(def_id) = def_id.as_local() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
match self.tcx.hir_node_by_def_id(def_id) {
|
||||
Node::Item(item) => match item.kind {
|
||||
hir::ItemKind::Fn(..) => item_might_be_inlined(self.tcx, def_id.into()),
|
||||
hir::ItemKind::Fn(..) => recursively_reachable(self.tcx, def_id.into()),
|
||||
_ => false,
|
||||
},
|
||||
Node::TraitItem(trait_method) => match trait_method.kind {
|
||||
|
|
@ -117,7 +140,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
Node::ImplItem(impl_item) => match impl_item.kind {
|
||||
hir::ImplItemKind::Const(..) => true,
|
||||
hir::ImplItemKind::Fn(..) => {
|
||||
item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id())
|
||||
recursively_reachable(self.tcx, impl_item.hir_id().owner.to_def_id())
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => false,
|
||||
},
|
||||
|
|
@ -174,7 +197,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
Node::Item(item) => {
|
||||
match item.kind {
|
||||
hir::ItemKind::Fn(.., body) => {
|
||||
if item_might_be_inlined(self.tcx, item.owner_id.into()) {
|
||||
if recursively_reachable(self.tcx, item.owner_id.into()) {
|
||||
self.visit_nested_body(body);
|
||||
}
|
||||
}
|
||||
|
|
@ -228,7 +251,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
self.visit_nested_body(body);
|
||||
}
|
||||
hir::ImplItemKind::Fn(_, body) => {
|
||||
if item_might_be_inlined(self.tcx, impl_item.hir_id().owner.to_def_id()) {
|
||||
if recursively_reachable(self.tcx, impl_item.hir_id().owner.to_def_id()) {
|
||||
self.visit_nested_body(body)
|
||||
}
|
||||
}
|
||||
|
|
@ -316,7 +339,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
self.worklist.push(def_id);
|
||||
}
|
||||
_ => {
|
||||
if self.def_id_represents_local_inlined_item(def_id.to_def_id()) {
|
||||
if self.is_recursively_reachable_local(def_id.to_def_id()) {
|
||||
self.worklist.push(def_id);
|
||||
} else {
|
||||
self.reachable_symbols.insert(def_id);
|
||||
|
|
@ -394,6 +417,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
|||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
}
|
||||
|
||||
/// See module-level doc comment above.
|
||||
fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet {
|
||||
let effective_visibilities = &tcx.effective_visibilities(());
|
||||
|
||||
|
|
@ -427,14 +451,16 @@ fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet {
|
|||
}
|
||||
}
|
||||
{
|
||||
// Some methods from non-exported (completely private) trait impls still have to be
|
||||
// reachable if they are called from inlinable code. Generally, it's not known until
|
||||
// monomorphization if a specific trait impl item can be reachable or not. So, we
|
||||
// conservatively mark all of them as reachable.
|
||||
// As explained above, we have to mark all functions called from reachable
|
||||
// `item_might_be_inlined` items as reachable. The issue is, when those functions are
|
||||
// generic and call a trait method, we have no idea where that call goes! So, we
|
||||
// conservatively mark all trait impl items as reachable.
|
||||
// FIXME: One possible strategy for pruning the reachable set is to avoid marking impl
|
||||
// items of non-exported traits (or maybe all local traits?) unless their respective
|
||||
// trait items are used from inlinable code through method call syntax or UFCS, or their
|
||||
// trait is a lang item.
|
||||
// (But if you implement this, don't forget to take into account that vtables can also
|
||||
// make trait methods reachable!)
|
||||
let crate_items = tcx.hir_crate_items(());
|
||||
|
||||
for id in crate_items.free_items() {
|
||||
|
|
|
|||
|
|
@ -557,6 +557,11 @@ impl OutputTypes {
|
|||
self.0.contains_key(key)
|
||||
}
|
||||
|
||||
/// Returns `true` if user specified a name and not just produced type
|
||||
pub fn contains_explicit_name(&self, key: &OutputType) -> bool {
|
||||
self.0.get(key).map_or(false, |f| f.is_some())
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> BTreeMapIter<'_, OutputType, Option<OutFileName>> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,10 +33,10 @@ pub fn typeid_for_fnabi<'tcx>(
|
|||
/// Returns a type metadata identifier for the specified Instance.
|
||||
pub fn typeid_for_instance<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: &Instance<'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
options: TypeIdOptions,
|
||||
) -> String {
|
||||
typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options)
|
||||
typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options)
|
||||
}
|
||||
|
||||
/// Returns a KCFI type metadata identifier for the specified FnAbi.
|
||||
|
|
@ -55,12 +55,12 @@ pub fn kcfi_typeid_for_fnabi<'tcx>(
|
|||
/// Returns a KCFI type metadata identifier for the specified Instance.
|
||||
pub fn kcfi_typeid_for_instance<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: &Instance<'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
options: TypeIdOptions,
|
||||
) -> u32 {
|
||||
// A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the
|
||||
// xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
|
||||
let mut hash: XxHash64 = Default::default();
|
||||
hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, *instance, options).as_bytes());
|
||||
hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes());
|
||||
hash.finish() as u32
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ use crate::vec::Vec;
|
|||
/// # Representation
|
||||
///
|
||||
/// A `String` is made up of three components: a pointer to some bytes, a
|
||||
/// length, and a capacity. The pointer points to an internal buffer `String`
|
||||
/// length, and a capacity. The pointer points to the internal buffer which `String`
|
||||
/// uses to store its data. The length is the number of bytes currently stored
|
||||
/// in the buffer, and the capacity is the size of the buffer in bytes. As such,
|
||||
/// the length will always be less than or equal to the capacity.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ description = "The Rust Core Library"
|
|||
autotests = false
|
||||
autobenches = false
|
||||
# If you update this, be sure to update it in a bunch of other places too!
|
||||
# As of 2022, it was the ci/pgo.sh script and the core-no-fp-fmt-parse test.
|
||||
# As of 2024, it was src/tools/opt-dist, the core-no-fp-fmt-parse test and
|
||||
# the version of the prelude imported in core/lib.rs.
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use crate::cmp::BytewiseEq;
|
||||
use crate::convert::TryInto;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, U, const N: usize> PartialEq<[U; N]> for [T; N]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use crate::borrow::{Borrow, BorrowMut};
|
||||
use crate::cmp::Ordering;
|
||||
use crate::convert::{Infallible, TryFrom};
|
||||
use crate::convert::Infallible;
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
use crate::hash::{self, Hash};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//! Character conversions.
|
||||
|
||||
use crate::char::TryFromCharError;
|
||||
use crate::convert::TryFrom;
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
use crate::mem::transmute;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use super::TryFrom;
|
||||
use crate::num::TryFromIntError;
|
||||
|
||||
mod private {
|
||||
|
|
@ -323,7 +322,6 @@ impl_try_from_lower_bounded!(isize => usize);
|
|||
#[cfg(target_pointer_width = "16")]
|
||||
mod ptr_try_from_impls {
|
||||
use super::TryFromIntError;
|
||||
use crate::convert::TryFrom;
|
||||
|
||||
impl_try_from_upper_bounded!(usize => u8);
|
||||
impl_try_from_unbounded!(usize => u16, u32, u64, u128);
|
||||
|
|
@ -346,7 +344,6 @@ mod ptr_try_from_impls {
|
|||
#[cfg(target_pointer_width = "32")]
|
||||
mod ptr_try_from_impls {
|
||||
use super::TryFromIntError;
|
||||
use crate::convert::TryFrom;
|
||||
|
||||
impl_try_from_upper_bounded!(usize => u8, u16);
|
||||
impl_try_from_unbounded!(usize => u32, u64, u128);
|
||||
|
|
@ -372,7 +369,6 @@ mod ptr_try_from_impls {
|
|||
#[cfg(target_pointer_width = "64")]
|
||||
mod ptr_try_from_impls {
|
||||
use super::TryFromIntError;
|
||||
use crate::convert::TryFrom;
|
||||
|
||||
impl_try_from_upper_bounded!(usize => u8, u16, u32);
|
||||
impl_try_from_unbounded!(usize => u64, u128);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use crate::convert::TryFrom;
|
||||
use crate::{
|
||||
intrinsics,
|
||||
iter::{from_fn, TrustedLen, TrustedRandomAccess},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use crate::ascii::Char as AsciiChar;
|
||||
use crate::convert::TryFrom;
|
||||
use crate::mem;
|
||||
use crate::net::{Ipv4Addr, Ipv6Addr};
|
||||
use crate::num::NonZero;
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ use super::super::ByRefSized;
|
|||
use super::super::TrustedRandomAccessNoCoerce;
|
||||
use super::super::{ArrayChunks, Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
|
||||
use super::super::{FlatMap, Flatten};
|
||||
use super::super::{FromIterator, Intersperse, IntersperseWith, Product, Sum, Zip};
|
||||
use super::super::{
|
||||
Inspect, Map, MapWhile, MapWindows, Peekable, Rev, Scan, Skip, SkipWhile, StepBy, Take,
|
||||
TakeWhile,
|
||||
};
|
||||
use super::super::{Intersperse, IntersperseWith, Product, Sum, Zip};
|
||||
|
||||
fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -270,6 +270,7 @@
|
|||
#![feature(arm_target_feature)]
|
||||
#![feature(avx512_target_feature)]
|
||||
#![feature(hexagon_target_feature)]
|
||||
#![feature(loongarch_target_feature)]
|
||||
#![feature(mips_target_feature)]
|
||||
#![feature(powerpc_target_feature)]
|
||||
#![feature(riscv_target_feature)]
|
||||
|
|
@ -285,7 +286,7 @@ extern crate self as core;
|
|||
|
||||
#[prelude_import]
|
||||
#[allow(unused)]
|
||||
use prelude::v1::*;
|
||||
use prelude::rust_2021::*;
|
||||
|
||||
#[cfg(not(test))] // See #65860
|
||||
#[macro_use]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
//! This module is "publicly exported" through the `FromStr` implementations
|
||||
//! below.
|
||||
|
||||
use crate::convert::{TryFrom, TryInto};
|
||||
use crate::error::Error;
|
||||
use crate::fmt;
|
||||
use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
|
|
|
|||
|
|
@ -553,7 +553,7 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
|
||||
use crate::iter::{self, FusedIterator, TrustedLen};
|
||||
use crate::panicking::{panic, panic_str};
|
||||
use crate::pin::Pin;
|
||||
use crate::{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use crate::convert::{TryFrom, TryInto};
|
||||
use crate::num::NonZero;
|
||||
#[cfg(debug_assertions)]
|
||||
use crate::ub_checks::assert_unsafe_precondition;
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@
|
|||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
|
||||
use crate::iter::{self, FusedIterator, TrustedLen};
|
||||
use crate::ops::{self, ControlFlow, Deref, DerefMut};
|
||||
use crate::{convert, fmt, hint};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
use crate::iter::FromIterator;
|
||||
|
||||
/// Collapses all unit items from an iterator into one.
|
||||
///
|
||||
/// This is more useful when combined with higher-level abstractions, like
|
||||
|
|
|
|||
|
|
@ -45,10 +45,6 @@
|
|||
#![unstable(feature = "portable_simd", issue = "86656")]
|
||||
//! Portable SIMD module.
|
||||
|
||||
#[prelude_import]
|
||||
#[allow(unused_imports)]
|
||||
use core::prelude::v1::*;
|
||||
|
||||
#[path = "mod.rs"]
|
||||
mod core_simd;
|
||||
pub use self::core_simd::simd;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ use crate::simd::{
|
|||
ptr::{SimdConstPtr, SimdMutPtr},
|
||||
LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle,
|
||||
};
|
||||
use core::convert::{TryFrom, TryInto};
|
||||
|
||||
/// A SIMD vector with the shape of `[T; N]` but the operations of `T`.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 56087ea170d878a7a57b3a5725e0c00f5f5cad70
|
||||
Subproject commit 967e7afd87cbea3232581a4a55031134ab88f595
|
||||
|
|
@ -1003,6 +1003,7 @@ impl Step for PlainSourceTarball {
|
|||
// Vendor all Cargo dependencies
|
||||
let mut cmd = Command::new(&builder.initial_cargo);
|
||||
cmd.arg("vendor")
|
||||
.arg("--versioned-dirs")
|
||||
.arg("--sync")
|
||||
.arg(builder.src.join("./src/tools/cargo/Cargo.toml"))
|
||||
.arg("--sync")
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit e1eead1181a691e56299294d5f1d62fe7a26d317
|
||||
Subproject commit 98b33e9a441457b0a491fe1be90e7de64eafc3e5
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5afb503a4c1ea3c84370f8f4c08a1cddd1cdf6ad
|
||||
Subproject commit 984b36eca4b9293df04d5ba4eb5c4f77db0f51dc
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit e093099709456e6fd74fecd2505fdf49a2471c10
|
||||
Subproject commit 7601e0c5ad29d5bd3b518700ea63fddfff5915a7
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 8a5d647f19b08998612146b1cb2ca47083db63e0
|
||||
Subproject commit ffa246b7fd95a96e1cd54883e613aed42c32547d
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit d438c80c45c24be676ef5867edc79d0a14910efe
|
||||
Subproject commit a510712d05c6c98f987af24dd73cdfafee8922e6
|
||||
|
|
@ -143,13 +143,13 @@ impl Msrv {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn enter_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) {
|
||||
pub fn check_attributes(&mut self, sess: &Session, attrs: &[Attribute]) {
|
||||
if let Some(version) = Self::parse_attr(sess, attrs) {
|
||||
self.stack.push(version);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) {
|
||||
pub fn check_attributes_post(&mut self, sess: &Session, attrs: &[Attribute]) {
|
||||
if Self::parse_attr(sess, attrs).is_some() {
|
||||
self.stack.pop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -158,10 +158,10 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
|
|||
}
|
||||
}
|
||||
|
||||
fn enter_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||
fn check_attributes(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||
self.limit.push_attrs(cx.sess(), attrs, "cognitive_complexity");
|
||||
}
|
||||
fn exit_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||
fn check_attributes_post(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
|
||||
self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -162,12 +162,12 @@ impl MissingDoc {
|
|||
impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
||||
fn enter_lint_attrs(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) {
|
||||
fn check_attributes(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) {
|
||||
let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs);
|
||||
self.doc_hidden_stack.push(doc_hidden);
|
||||
}
|
||||
|
||||
fn exit_lint_attrs(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) {
|
||||
fn check_attributes_post(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) {
|
||||
self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ impl LateLintPass<'_> for MsrvAttrImpl {
|
|||
.filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
|
||||
.any(|t| match_type(cx, t.expect_ty(), &paths::MSRV))
|
||||
})
|
||||
&& !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs))
|
||||
&& !items.iter().any(|item| item.ident.name == sym!(check_attributes))
|
||||
{
|
||||
let context = if is_late_pass { "LateContext" } else { "EarlyContext" };
|
||||
let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" };
|
||||
|
|
|
|||
|
|
@ -131,14 +131,14 @@ use rustc_middle::hir::nested_filter;
|
|||
#[macro_export]
|
||||
macro_rules! extract_msrv_attr {
|
||||
($context:ident) => {
|
||||
fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
|
||||
fn check_attributes(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
|
||||
let sess = rustc_lint::LintContext::sess(cx);
|
||||
self.msrv.enter_lint_attrs(sess, attrs);
|
||||
self.msrv.check_attributes(sess, attrs);
|
||||
}
|
||||
|
||||
fn exit_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
|
||||
fn check_attributes_post(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
|
||||
let sess = rustc_lint::LintContext::sess(cx);
|
||||
self.msrv.exit_lint_attrs(sess, attrs);
|
||||
self.msrv.check_attributes_post(sess, attrs);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
cb7c63606e53715f94f3ba04d38e50772e4cd23d
|
||||
b13a71a2e77f4625d1a2b8a5b9488414686ebca9
|
||||
|
|
|
|||
|
|
@ -364,6 +364,10 @@ fn main() {
|
|||
let args = rustc_driver::args::raw_args(&early_dcx)
|
||||
.unwrap_or_else(|_| std::process::exit(rustc_driver::EXIT_FAILURE));
|
||||
|
||||
// Install the ctrlc handler that sets `rustc_const_eval::CTRL_C_RECEIVED`, even if
|
||||
// MIRI_BE_RUSTC is set.
|
||||
rustc_driver::install_ctrlc_handler();
|
||||
|
||||
// If the environment asks us to actually be rustc, then do that.
|
||||
if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
|
||||
// Earliest rustc setup.
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::num::TryFromIntError;
|
||||
use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
|
||||
use std::sync::atomic::Ordering::Relaxed;
|
||||
use std::task::Poll;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use either::Either;
|
||||
|
||||
use rustc_const_eval::CTRL_C_RECEIVED;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
|
|
@ -1045,21 +1046,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
/// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
|
||||
/// termination).
|
||||
fn run_threads(&mut self) -> InterpResult<'tcx, !> {
|
||||
static SIGNALED: AtomicBool = AtomicBool::new(false);
|
||||
ctrlc::set_handler(move || {
|
||||
// Indicate that we have ben signaled to stop. If we were already signaled, exit
|
||||
// immediately. In our interpreter loop we try to consult this value often, but if for
|
||||
// whatever reason we don't get to that check or the cleanup we do upon finding that
|
||||
// this bool has become true takes a long time, the exit here will promptly exit the
|
||||
// process on the second Ctrl-C.
|
||||
if SIGNALED.swap(true, Relaxed) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
let this = self.eval_context_mut();
|
||||
loop {
|
||||
if SIGNALED.load(Relaxed) {
|
||||
if CTRL_C_RECEIVED.load(Relaxed) {
|
||||
this.machine.handle_abnormal_termination();
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
|
|||
"byteorder", // via ruzstd in object in thorin-dwp
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"compiler_builtins",
|
||||
"cpufeatures",
|
||||
"crc32fast",
|
||||
|
|
@ -216,6 +217,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
|
|||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"crypto-common",
|
||||
"ctrlc",
|
||||
"darling",
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
|
|
@ -281,6 +283,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
|
|||
"memmap2",
|
||||
"memoffset",
|
||||
"miniz_oxide",
|
||||
"nix",
|
||||
"nu-ansi-term",
|
||||
"num-conv",
|
||||
"num_cpus",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const ENTRY_LIMIT: usize = 900;
|
|||
// FIXME: The following limits should be reduced eventually.
|
||||
|
||||
const ISSUES_ENTRY_LIMIT: usize = 1750;
|
||||
const ROOT_ENTRY_LIMIT: usize = 859;
|
||||
const ROOT_ENTRY_LIMIT: usize = 860;
|
||||
|
||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||
"rs", // test source files
|
||||
|
|
|
|||
|
|
@ -24,9 +24,8 @@ pub unsafe fn swap_i32(x: &mut i32, y: &mut i32) {
|
|||
// CHECK-NOT: alloca
|
||||
|
||||
// CHECK: %[[TEMP:.+]] = load i32, ptr %x, align 4
|
||||
// CHECK-SAME: !noundef
|
||||
// OPT3-SAME: !noundef
|
||||
// OPT0: %[[TEMP2:.+]] = load i32, ptr %y, align 4
|
||||
// OPT0-SAME: !noundef
|
||||
// OPT0: store i32 %[[TEMP2]], ptr %x, align 4
|
||||
// OPT0-NOT: memcpy
|
||||
// OPT3-NOT: load
|
||||
|
|
@ -42,9 +41,9 @@ pub unsafe fn swap_pair(x: &mut (i32, u32), y: &mut (i32, u32)) {
|
|||
// CHECK-NOT: alloca
|
||||
|
||||
// CHECK: load i32
|
||||
// CHECK-SAME: !noundef
|
||||
// OPT3-SAME: !noundef
|
||||
// CHECK: load i32
|
||||
// CHECK-SAME: !noundef
|
||||
// OPT3-SAME: !noundef
|
||||
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 8, i1 false)
|
||||
// CHECK: store i32
|
||||
// CHECK: store i32
|
||||
|
|
@ -57,10 +56,10 @@ pub unsafe fn swap_str<'a>(x: &mut &'a str, y: &mut &'a str) {
|
|||
// CHECK-NOT: alloca
|
||||
|
||||
// CHECK: load ptr
|
||||
// CHECK-SAME: !nonnull
|
||||
// CHECK-SAME: !noundef
|
||||
// OPT3-SAME: !nonnull
|
||||
// OPT3-SAME: !noundef
|
||||
// CHECK: load i64
|
||||
// CHECK-SAME: !noundef
|
||||
// OPT3-SAME: !noundef
|
||||
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 16, i1 false)
|
||||
// CHECK: store ptr
|
||||
// CHECK: store i64
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
//@ compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0
|
||||
//@ compile-flags: -C no-prepopulate-passes -Zmir-opt-level=0 -O
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(generic_nonzero)]
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ fn main() {
|
|||
// CHECK-LABEL: @_ZN20overaligned_constant4main
|
||||
// CHECK: [[full:%_.*]] = alloca %SmallStruct, align 8
|
||||
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[full]], ptr align 8 @0, i64 32, i1 false)
|
||||
// CHECK: %b.0 = load i32, ptr @0, align 4,
|
||||
// CHECK: %b.0 = load i32, ptr @0, align 4
|
||||
// CHECK: %b.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4
|
||||
let mut s = S(1);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
storage_conflicts: BitMatrix(0x0) {},
|
||||
} */
|
||||
|
||||
fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>, _2: &mut Context<'_>) -> Poll<()> {
|
||||
fn a::{closure#0}(_1: Pin<&mut {async fn body of a()}>, _2: &mut Context<'_>) -> Poll<()> {
|
||||
debug _task_context => _4;
|
||||
let mut _0: std::task::Poll<()>;
|
||||
let mut _3: ();
|
||||
|
|
@ -17,7 +17,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>
|
|||
let mut _5: u32;
|
||||
|
||||
bb0: {
|
||||
_5 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16})));
|
||||
_5 = discriminant((*(_1.0: &mut {async fn body of a()})));
|
||||
switchInt(move _5) -> [0: bb1, 1: bb4, otherwise: bb5];
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ fn a::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>
|
|||
|
||||
bb2: {
|
||||
_0 = Poll::<()>::Ready(move _3);
|
||||
discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16}))) = 1;
|
||||
discriminant((*(_1.0: &mut {async fn body of a()}))) = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,19 +51,19 @@
|
|||
},
|
||||
} */
|
||||
|
||||
fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>, _2: &mut Context<'_>) -> Poll<()> {
|
||||
fn b::{closure#0}(_1: Pin<&mut {async fn body of b()}>, _2: &mut Context<'_>) -> Poll<()> {
|
||||
debug _task_context => _38;
|
||||
let mut _0: std::task::Poll<()>;
|
||||
let _3: ();
|
||||
let mut _4: {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _5: {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _6: {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _4: {async fn body of a()};
|
||||
let mut _5: {async fn body of a()};
|
||||
let mut _6: {async fn body of a()};
|
||||
let mut _7: ();
|
||||
let _8: ();
|
||||
let mut _9: std::task::Poll<()>;
|
||||
let mut _10: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>;
|
||||
let mut _11: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _12: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _10: std::pin::Pin<&mut {async fn body of a()}>;
|
||||
let mut _11: &mut {async fn body of a()};
|
||||
let mut _12: &mut {async fn body of a()};
|
||||
let mut _13: &mut std::task::Context<'_>;
|
||||
let mut _14: &mut std::task::Context<'_>;
|
||||
let mut _15: &mut std::task::Context<'_>;
|
||||
|
|
@ -71,14 +71,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
let mut _18: !;
|
||||
let mut _19: &mut std::task::Context<'_>;
|
||||
let mut _20: ();
|
||||
let mut _21: {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _22: {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _23: {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _21: {async fn body of a()};
|
||||
let mut _22: {async fn body of a()};
|
||||
let mut _23: {async fn body of a()};
|
||||
let _24: ();
|
||||
let mut _25: std::task::Poll<()>;
|
||||
let mut _26: std::pin::Pin<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>;
|
||||
let mut _27: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _28: &mut {async fn body@$DIR/async_await.rs:12:14: 12:16};
|
||||
let mut _26: std::pin::Pin<&mut {async fn body of a()}>;
|
||||
let mut _27: &mut {async fn body of a()};
|
||||
let mut _28: &mut {async fn body of a()};
|
||||
let mut _29: &mut std::task::Context<'_>;
|
||||
let mut _30: &mut std::task::Context<'_>;
|
||||
let mut _31: &mut std::task::Context<'_>;
|
||||
|
|
@ -90,7 +90,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
let mut _38: &mut std::task::Context<'_>;
|
||||
let mut _39: u32;
|
||||
scope 1 {
|
||||
debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16});
|
||||
debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
|
||||
let _17: ();
|
||||
scope 2 {
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
}
|
||||
}
|
||||
scope 4 {
|
||||
debug __awaitee => (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16});
|
||||
debug __awaitee => (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()});
|
||||
let _33: ();
|
||||
scope 5 {
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
}
|
||||
|
||||
bb0: {
|
||||
_39 = discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})));
|
||||
_39 = discriminant((*(_1.0: &mut {async fn body of b()})));
|
||||
switchInt(move _39) -> [0: bb1, 1: bb29, 3: bb27, 4: bb28, otherwise: bb8];
|
||||
}
|
||||
|
||||
|
|
@ -122,14 +122,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
}
|
||||
|
||||
bb2: {
|
||||
_4 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable];
|
||||
_4 = <{async fn body of a()} as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable];
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_5);
|
||||
PlaceMention(_4);
|
||||
nop;
|
||||
(((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}) = move _4;
|
||||
(((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()}) = move _4;
|
||||
goto -> bb4;
|
||||
}
|
||||
|
||||
|
|
@ -139,9 +139,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
StorageLive(_10);
|
||||
StorageLive(_11);
|
||||
StorageLive(_12);
|
||||
_12 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16});
|
||||
_12 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()});
|
||||
_11 = &mut (*_12);
|
||||
_10 = Pin::<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable];
|
||||
_10 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _11) -> [return: bb5, unwind unreachable];
|
||||
}
|
||||
|
||||
bb5: {
|
||||
|
|
@ -157,7 +157,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
bb6: {
|
||||
_13 = &mut (*_14);
|
||||
StorageDead(_15);
|
||||
_9 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable];
|
||||
_9 = <{async fn body of a()} as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
|
|
@ -186,7 +186,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
StorageDead(_4);
|
||||
StorageDead(_19);
|
||||
StorageDead(_20);
|
||||
discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 3;
|
||||
discriminant((*(_1.0: &mut {async fn body of b()}))) = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -199,7 +199,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
StorageDead(_12);
|
||||
StorageDead(_9);
|
||||
StorageDead(_8);
|
||||
drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#3).0: {async fn body@$DIR/async_await.rs:12:14: 12:16})) -> [return: bb12, unwind unreachable];
|
||||
drop((((*(_1.0: &mut {async fn body of b()})) as variant#3).0: {async fn body of a()})) -> [return: bb12, unwind unreachable];
|
||||
}
|
||||
|
||||
bb11: {
|
||||
|
|
@ -224,14 +224,14 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
}
|
||||
|
||||
bb14: {
|
||||
_21 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable];
|
||||
_21 = <{async fn body of a()} as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable];
|
||||
}
|
||||
|
||||
bb15: {
|
||||
StorageDead(_22);
|
||||
PlaceMention(_21);
|
||||
nop;
|
||||
(((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16}) = move _21;
|
||||
(((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()}) = move _21;
|
||||
goto -> bb16;
|
||||
}
|
||||
|
||||
|
|
@ -241,9 +241,9 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
StorageLive(_26);
|
||||
StorageLive(_27);
|
||||
StorageLive(_28);
|
||||
_28 = &mut (((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16});
|
||||
_28 = &mut (((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()});
|
||||
_27 = &mut (*_28);
|
||||
_26 = Pin::<&mut {async fn body@$DIR/async_await.rs:12:14: 12:16}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable];
|
||||
_26 = Pin::<&mut {async fn body of a()}>::new_unchecked(move _27) -> [return: bb17, unwind unreachable];
|
||||
}
|
||||
|
||||
bb17: {
|
||||
|
|
@ -259,7 +259,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
bb18: {
|
||||
_29 = &mut (*_30);
|
||||
StorageDead(_31);
|
||||
_25 = <{async fn body@$DIR/async_await.rs:12:14: 12:16} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable];
|
||||
_25 = <{async fn body of a()} as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable];
|
||||
}
|
||||
|
||||
bb19: {
|
||||
|
|
@ -283,7 +283,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
StorageDead(_21);
|
||||
StorageDead(_35);
|
||||
StorageDead(_36);
|
||||
discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 4;
|
||||
discriminant((*(_1.0: &mut {async fn body of b()}))) = 4;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -296,7 +296,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
StorageDead(_28);
|
||||
StorageDead(_25);
|
||||
StorageDead(_24);
|
||||
drop((((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2})) as variant#4).0: {async fn body@$DIR/async_await.rs:12:14: 12:16})) -> [return: bb23, unwind unreachable];
|
||||
drop((((*(_1.0: &mut {async fn body of b()})) as variant#4).0: {async fn body of a()})) -> [return: bb23, unwind unreachable];
|
||||
}
|
||||
|
||||
bb22: {
|
||||
|
|
@ -319,7 +319,7 @@ fn b::{closure#0}(_1: Pin<&mut {async fn body@$DIR/async_await.rs:15:18: 18:2}>,
|
|||
|
||||
bb25: {
|
||||
_0 = Poll::<()>::Ready(move _37);
|
||||
discriminant((*(_1.0: &mut {async fn body@$DIR/async_await.rs:15:18: 18:2}))) = 1;
|
||||
discriminant((*(_1.0: &mut {async fn body of b()}))) = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,24 +5,24 @@
|
|||
debug permit => (_1.0: ActionPermit<'_, T>);
|
||||
debug ctx => (*(_1.1: &mut std::task::Context<'_>));
|
||||
let mut _0: ();
|
||||
let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
let mut _2: {async fn body of ActionPermit<'_, T>::perform()};
|
||||
let mut _3: ActionPermit<'_, T>;
|
||||
let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
let mut _5: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
let _6: ();
|
||||
let mut _7: std::task::Poll<()>;
|
||||
let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
|
||||
let mut _8: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>;
|
||||
let mut _9: &mut std::task::Context<'_>;
|
||||
let mut _10: &mut std::task::Context<'_>;
|
||||
scope 1 {
|
||||
debug fut => _2;
|
||||
let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
|
||||
let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>;
|
||||
scope 2 {
|
||||
debug fut => _4;
|
||||
scope 4 {
|
||||
}
|
||||
+ scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) {
|
||||
+ debug _task_context => _31;
|
||||
+ debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>);
|
||||
+ debug self => ((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})).0: ActionPermit<'_, T>);
|
||||
+ let _11: ActionPermit<'_, T>;
|
||||
+ let mut _12: std::future::Ready<()>;
|
||||
+ let mut _13: std::future::Ready<()>;
|
||||
|
|
@ -43,19 +43,19 @@
|
|||
+ let mut _30: ();
|
||||
+ let mut _31: &mut std::task::Context<'_>;
|
||||
+ let mut _32: u32;
|
||||
+ let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ scope 8 {
|
||||
+ debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>);
|
||||
+ debug self => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).0: ActionPermit<'_, T>);
|
||||
+ let mut _15: std::future::Ready<()>;
|
||||
+ scope 9 {
|
||||
+ debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>);
|
||||
+ debug __awaitee => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).1: std::future::Ready<()>);
|
||||
+ let _26: ();
|
||||
+ scope 10 {
|
||||
+ }
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
+ }
|
||||
}
|
||||
scope 3 {
|
||||
+ scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) {
|
||||
+ scope 6 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) {
|
||||
+ debug pointer => _5;
|
||||
+ }
|
||||
}
|
||||
|
|
@ -93,11 +93,11 @@
|
|||
StorageLive(_4);
|
||||
StorageLive(_5);
|
||||
_5 = &mut _2;
|
||||
- _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind unreachable];
|
||||
- _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked(move _5) -> [return: bb2, unwind unreachable];
|
||||
- }
|
||||
-
|
||||
- bb2: {
|
||||
+ _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 };
|
||||
+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: _5 };
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
|
|
@ -106,7 +106,7 @@
|
|||
StorageLive(_9);
|
||||
_10 = deref_copy (_1.1: &mut std::task::Context<'_>);
|
||||
_9 = &mut (*_10);
|
||||
- _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable];
|
||||
- _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable];
|
||||
+ StorageLive(_11);
|
||||
+ StorageLive(_15);
|
||||
+ StorageLive(_16);
|
||||
|
|
@ -123,7 +123,7 @@
|
|||
+ StorageLive(_38);
|
||||
+ StorageLive(_39);
|
||||
+ StorageLive(_40);
|
||||
+ _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ _32 = discriminant((*_33));
|
||||
+ switchInt(move _32) -> [0: bb3, 1: bb13, 3: bb12, otherwise: bb8];
|
||||
}
|
||||
|
|
@ -164,8 +164,8 @@
|
|||
|
||||
+ bb3: {
|
||||
+ _31 = move _9;
|
||||
+ _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
|
||||
+ StorageLive(_12);
|
||||
+ StorageLive(_13);
|
||||
|
|
@ -183,7 +183,7 @@
|
|||
- StorageDead(_2);
|
||||
- return;
|
||||
+ StorageDead(_13);
|
||||
+ _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
|
||||
+ goto -> bb5;
|
||||
+ }
|
||||
|
|
@ -194,7 +194,7 @@
|
|||
+ StorageLive(_19);
|
||||
+ StorageLive(_20);
|
||||
+ StorageLive(_21);
|
||||
+ _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
|
||||
+ _20 = &mut (*_21);
|
||||
+ _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb6, unwind unreachable];
|
||||
|
|
@ -236,7 +236,7 @@
|
|||
+ StorageDead(_12);
|
||||
+ StorageDead(_28);
|
||||
+ StorageDead(_29);
|
||||
+ _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ discriminant((*_38)) = 3;
|
||||
+ goto -> bb2;
|
||||
+ }
|
||||
|
|
@ -251,13 +251,13 @@
|
|||
+ StorageDead(_18);
|
||||
+ StorageDead(_17);
|
||||
+ StorageDead(_12);
|
||||
+ _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb11, unwind unreachable];
|
||||
+ }
|
||||
+
|
||||
+ bb11: {
|
||||
+ _7 = Poll::<()>::Ready(move _30);
|
||||
+ _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ discriminant((*_40)) = 1;
|
||||
+ goto -> bb2;
|
||||
+ }
|
||||
|
|
|
|||
|
|
@ -5,24 +5,24 @@
|
|||
debug permit => (_1.0: ActionPermit<'_, T>);
|
||||
debug ctx => (*(_1.1: &mut std::task::Context<'_>));
|
||||
let mut _0: ();
|
||||
let mut _2: {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
let mut _2: {async fn body of ActionPermit<'_, T>::perform()};
|
||||
let mut _3: ActionPermit<'_, T>;
|
||||
let mut _5: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
let mut _5: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
let _6: ();
|
||||
let mut _7: std::task::Poll<()>;
|
||||
let mut _8: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
|
||||
let mut _8: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>;
|
||||
let mut _9: &mut std::task::Context<'_>;
|
||||
let mut _10: &mut std::task::Context<'_>;
|
||||
scope 1 {
|
||||
debug fut => _2;
|
||||
let _4: std::pin::Pin<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>;
|
||||
let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>;
|
||||
scope 2 {
|
||||
debug fut => _4;
|
||||
scope 4 {
|
||||
}
|
||||
+ scope 7 (inlined ActionPermit::<'_, T>::perform::{closure#0}) {
|
||||
+ debug _task_context => _31;
|
||||
+ debug self => ((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})).0: ActionPermit<'_, T>);
|
||||
+ debug self => ((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})).0: ActionPermit<'_, T>);
|
||||
+ let _11: ActionPermit<'_, T>;
|
||||
+ let mut _12: std::future::Ready<()>;
|
||||
+ let mut _13: std::future::Ready<()>;
|
||||
|
|
@ -43,21 +43,21 @@
|
|||
+ let mut _30: ();
|
||||
+ let mut _31: &mut std::task::Context<'_>;
|
||||
+ let mut _32: u32;
|
||||
+ let mut _33: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _34: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _35: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _36: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _37: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _38: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _39: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _40: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _41: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _42: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6};
|
||||
+ let mut _33: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _34: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _35: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _36: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _37: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _38: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _39: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _40: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _41: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ let mut _42: &mut {async fn body of ActionPermit<'_, T>::perform()};
|
||||
+ scope 8 {
|
||||
+ debug self => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).0: ActionPermit<'_, T>);
|
||||
+ debug self => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).0: ActionPermit<'_, T>);
|
||||
+ let mut _15: std::future::Ready<()>;
|
||||
+ scope 9 {
|
||||
+ debug __awaitee => (((*(_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6})) as variant#3).1: std::future::Ready<()>);
|
||||
+ debug __awaitee => (((*(_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()})) as variant#3).1: std::future::Ready<()>);
|
||||
+ let _26: ();
|
||||
+ scope 10 {
|
||||
+ }
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
+ }
|
||||
}
|
||||
scope 3 {
|
||||
+ scope 6 (inlined Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked) {
|
||||
+ scope 6 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) {
|
||||
+ debug pointer => _5;
|
||||
+ }
|
||||
}
|
||||
|
|
@ -95,11 +95,11 @@
|
|||
StorageLive(_4);
|
||||
StorageLive(_5);
|
||||
_5 = &mut _2;
|
||||
- _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}>::new_unchecked(move _5) -> [return: bb2, unwind: bb5];
|
||||
- _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked(move _5) -> [return: bb2, unwind: bb5];
|
||||
- }
|
||||
-
|
||||
- bb2: {
|
||||
+ _4 = Pin::<&mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6}> { __pointer: _5 };
|
||||
+ _4 = Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}> { __pointer: _5 };
|
||||
StorageDead(_5);
|
||||
StorageLive(_6);
|
||||
StorageLive(_7);
|
||||
|
|
@ -108,7 +108,7 @@
|
|||
StorageLive(_9);
|
||||
_10 = deref_copy (_1.1: &mut std::task::Context<'_>);
|
||||
_9 = &mut (*_10);
|
||||
- _7 = <{async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5];
|
||||
- _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5];
|
||||
+ StorageLive(_11);
|
||||
+ StorageLive(_15);
|
||||
+ StorageLive(_16);
|
||||
|
|
@ -127,7 +127,7 @@
|
|||
+ StorageLive(_40);
|
||||
+ StorageLive(_41);
|
||||
+ StorageLive(_42);
|
||||
+ _33 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ _32 = discriminant((*_33));
|
||||
+ switchInt(move _32) -> [0: bb5, 1: bb22, 2: bb21, 3: bb20, otherwise: bb10];
|
||||
}
|
||||
|
|
@ -181,8 +181,8 @@
|
|||
- return;
|
||||
+ bb5: {
|
||||
+ _31 = move _9;
|
||||
+ _34 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _35 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ (((*_34) as variant#3).0: ActionPermit<'_, T>) = move ((*_35).0: ActionPermit<'_, T>);
|
||||
+ StorageLive(_12);
|
||||
+ StorageLive(_13);
|
||||
|
|
@ -200,7 +200,7 @@
|
|||
- drop(_2) -> [return: bb6, unwind terminate(cleanup)];
|
||||
+ bb6: {
|
||||
+ StorageDead(_13);
|
||||
+ _36 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ (((*_36) as variant#3).1: std::future::Ready<()>) = move _12;
|
||||
+ goto -> bb7;
|
||||
}
|
||||
|
|
@ -213,7 +213,7 @@
|
|||
+ StorageLive(_19);
|
||||
+ StorageLive(_20);
|
||||
+ StorageLive(_21);
|
||||
+ _37 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ _21 = &mut (((*_37) as variant#3).1: std::future::Ready<()>);
|
||||
+ _20 = &mut (*_21);
|
||||
+ _19 = Pin::<&mut std::future::Ready<()>>::new_unchecked(move _20) -> [return: bb8, unwind: bb15];
|
||||
|
|
@ -255,7 +255,7 @@
|
|||
+ StorageDead(_12);
|
||||
+ StorageDead(_28);
|
||||
+ StorageDead(_29);
|
||||
+ _38 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ discriminant((*_38)) = 3;
|
||||
+ goto -> bb4;
|
||||
+ }
|
||||
|
|
@ -270,13 +270,13 @@
|
|||
+ StorageDead(_18);
|
||||
+ StorageDead(_17);
|
||||
+ StorageDead(_12);
|
||||
+ _39 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb13, unwind: bb19];
|
||||
+ }
|
||||
+
|
||||
+ bb13: {
|
||||
+ _7 = Poll::<()>::Ready(move _30);
|
||||
+ _40 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ discriminant((*_40)) = 1;
|
||||
+ goto -> bb4;
|
||||
+ }
|
||||
|
|
@ -308,12 +308,12 @@
|
|||
+
|
||||
+ bb18 (cleanup): {
|
||||
+ StorageDead(_12);
|
||||
+ _41 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb19, unwind terminate(cleanup)];
|
||||
+ }
|
||||
+
|
||||
+ bb19 (cleanup): {
|
||||
+ _42 = deref_copy (_8.0: &mut {async fn body@$DIR/inline_coroutine_body.rs:25:28: 27:6});
|
||||
+ _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
|
||||
+ discriminant((*_42)) = 2;
|
||||
+ goto -> bb2;
|
||||
+ }
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ include ../tools.mk
|
|||
# ignore-cross-compile
|
||||
|
||||
# Test compiler behavior in case environment specifies wrong jobserver.
|
||||
# Note that by default, the compiler uses file descriptors 0 (stdin), 1 (stdout), 2 (stderr),
|
||||
# but also 3 and 4 for either end of the ctrl-c signal handler self-pipe.
|
||||
|
||||
all:
|
||||
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr -
|
||||
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=5,5" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr -
|
||||
bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff not_a_pipe.stderr -
|
||||
|
||||
# This test randomly fails, see https://github.com/rust-lang/rust/issues/110321
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=3,3"`: cannot open file descriptor 3 from the jobserver environment variable value: Bad file descriptor (os error 9)
|
||||
warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=5,5"`: cannot open file descriptor 5 from the jobserver environment variable value: Bad file descriptor (os error 9)
|
||||
|
|
||||
= note: the build environment is likely misconfigured
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
# ignore-cross-compile
|
||||
# needs-unwind contains should_panic test
|
||||
include ../tools.mk
|
||||
|
||||
# Test expected libtest's junit output
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//@ run-pass
|
||||
//@ needs-asm-support
|
||||
//@ needs-unwind
|
||||
|
||||
#![feature(asm_unwind)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:21:21: 24:2}`: 3078 bytes, alignment: 1 bytes
|
||||
print-type-size type: `{async fn body of test()}`: 3078 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 0 bytes
|
||||
print-type-size variant `Suspend0`: 3077 bytes
|
||||
print-type-size local `.__awaitee`: 3077 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}
|
||||
print-type-size local `.__awaitee`: 3077 bytes, type: {async fn body of calls_fut<{async fn body of big_fut()}>()}
|
||||
print-type-size variant `Returned`: 0 bytes
|
||||
print-type-size variant `Panicked`: 0 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 3077 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}>`: 3077 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body of calls_fut<{async fn body of big_fut()}>()}>`: 3077 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 3077 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 3077 bytes
|
||||
print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:10:64: 19:2}`: 3077 bytes, alignment: 1 bytes
|
||||
print-type-size type: `{async fn body of calls_fut<{async fn body of big_fut()}>()}`: 3077 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 1025 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
|
|
@ -20,29 +20,29 @@ print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1
|
|||
print-type-size padding: 1 bytes
|
||||
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
|
||||
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
|
||||
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
|
||||
print-type-size variant `Suspend1`: 3076 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
print-type-size padding: 1026 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes, alignment: 1 bytes, type: bool
|
||||
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}
|
||||
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body of big_fut()}
|
||||
print-type-size variant `Suspend2`: 2052 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
print-type-size padding: 1 bytes
|
||||
print-type-size local `.fut`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size local `..coroutine_field4`: 1 bytes, type: bool
|
||||
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}
|
||||
print-type-size local `.__awaitee`: 1 bytes, type: {async fn body of wait()}
|
||||
print-type-size variant `Returned`: 1025 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
print-type-size variant `Panicked`: 1025 bytes
|
||||
print-type-size upvar `.fut`: 1025 bytes, offset: 0 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}>`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 1025 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}>`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body of big_fut()}>`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 1025 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 1025 bytes
|
||||
print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:8:35: 8:37}`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size type: `{async fn body of big_fut()}`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 1024 bytes
|
||||
print-type-size upvar `.arg`: 1024 bytes
|
||||
|
|
@ -52,13 +52,13 @@ print-type-size variant `Panicked`: 1024 bytes
|
|||
print-type-size upvar `.arg`: 1024 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<bool>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<bool>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 1 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body of wait()}>`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 1 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 1 bytes
|
||||
|
|
@ -67,7 +67,7 @@ print-type-size discriminant: 1 bytes
|
|||
print-type-size variant `Ready`: 0 bytes
|
||||
print-type-size field `.0`: 0 bytes
|
||||
print-type-size variant `Pending`: 0 bytes
|
||||
print-type-size type: `{async fn body@$DIR/async-awaiting-fut.rs:6:17: 6:19}`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size type: `{async fn body of wait()}`: 1 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 0 bytes
|
||||
print-type-size variant `Returned`: 0 bytes
|
||||
|
|
|
|||
|
|
@ -1,47 +1,47 @@
|
|||
print-type-size type: `{async fn body@$DIR/large-arg.rs:6:21: 8:2}`: 3076 bytes, alignment: 1 bytes
|
||||
print-type-size type: `{async fn body of test()}`: 3076 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 0 bytes
|
||||
print-type-size variant `Suspend0`: 3075 bytes
|
||||
print-type-size local `.__awaitee`: 3075 bytes, type: {async fn body@$DIR/large-arg.rs:10:30: 12:2}
|
||||
print-type-size local `.__awaitee`: 3075 bytes, type: {async fn body of a<[u8; 1024]>()}
|
||||
print-type-size variant `Returned`: 0 bytes
|
||||
print-type-size variant `Panicked`: 0 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 3075 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:10:30: 12:2}>`: 3075 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body of a<[u8; 1024]>()}>`: 3075 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 3075 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 3075 bytes
|
||||
print-type-size type: `{async fn body@$DIR/large-arg.rs:10:30: 12:2}`: 3075 bytes, alignment: 1 bytes
|
||||
print-type-size type: `{async fn body of a<[u8; 1024]>()}`: 3075 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size variant `Suspend0`: 3074 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size local `.__awaitee`: 2050 bytes, type: {async fn body@$DIR/large-arg.rs:13:26: 15:2}
|
||||
print-type-size local `.__awaitee`: 2050 bytes, type: {async fn body of b<[u8; 1024]>()}
|
||||
print-type-size variant `Returned`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size variant `Panicked`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:13:26: 15:2}>`: 2050 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 2050 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:13:26: 15:2}>`: 2050 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body of b<[u8; 1024]>()}>`: 2050 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 2050 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 2050 bytes
|
||||
print-type-size type: `{async fn body@$DIR/large-arg.rs:13:26: 15:2}`: 2050 bytes, alignment: 1 bytes
|
||||
print-type-size type: `{async fn body of b<[u8; 1024]>()}`: 2050 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size variant `Suspend0`: 2049 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body@$DIR/large-arg.rs:16:26: 18:2}
|
||||
print-type-size local `.__awaitee`: 1025 bytes, type: {async fn body of c<[u8; 1024]>()}
|
||||
print-type-size variant `Returned`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size variant `Panicked`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body@$DIR/large-arg.rs:16:26: 18:2}>`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::ManuallyDrop<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size field `.value`: 1025 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body@$DIR/large-arg.rs:16:26: 18:2}>`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size type: `std::mem::MaybeUninit<{async fn body of c<[u8; 1024]>()}>`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size variant `MaybeUninit`: 1025 bytes
|
||||
print-type-size field `.uninit`: 0 bytes
|
||||
print-type-size field `.value`: 1025 bytes
|
||||
|
|
@ -50,7 +50,7 @@ print-type-size discriminant: 1 bytes
|
|||
print-type-size variant `Ready`: 1024 bytes
|
||||
print-type-size field `.0`: 1024 bytes
|
||||
print-type-size variant `Pending`: 0 bytes
|
||||
print-type-size type: `{async fn body@$DIR/large-arg.rs:16:26: 18:2}`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size type: `{async fn body of c<[u8; 1024]>()}`: 1025 bytes, alignment: 1 bytes
|
||||
print-type-size discriminant: 1 bytes
|
||||
print-type-size variant `Unresumed`: 1024 bytes
|
||||
print-type-size upvar `.t`: 1024 bytes
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
// ICE cannot convert Refree.. to a region vid
|
||||
// issue: rust-lang/rust#114464
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn test<const N: usize>() {}
|
||||
|
||||
fn wow<'a>() {
|
||||
test::<{
|
||||
let _: &'a ();
|
||||
//~^ ERROR cannot capture late-bound lifetime in constant
|
||||
3
|
||||
}>();
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
error: cannot capture late-bound lifetime in constant
|
||||
--> $DIR/convert-refree-region-vid-ice-114464.rs:11:17
|
||||
|
|
||||
LL | fn wow<'a>() {
|
||||
| -- lifetime defined here
|
||||
LL | test::<{
|
||||
LL | let _: &'a ();
|
||||
| ^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
// ICE no entry found for key generics_of
|
||||
// issue: rust-lang/rust#113133
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs, non_lifetime_binders)]
|
||||
|
||||
pub fn foo()
|
||||
where
|
||||
for<const N: usize = { const fn bar() {} bar(); 1 }> ():,
|
||||
//~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
|
||||
{}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
error: defaults for generic parameters are not allowed in `for<...>` binders
|
||||
--> $DIR/no-entry-found-for-key-ice-gce-nlb-113133.rs:9:9
|
||||
|
|
||||
LL | for<const N: usize = { const fn bar() {} bar(); 1 }> ():,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// rust-lang/rust#119731
|
||||
// ICE ... unevaluated constant UnevaluatedConst
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
mod v20 {
|
||||
const v4: usize = 512;
|
||||
pub type v11 = [[usize; v4]; v4];
|
||||
//~^ WARN type `v11` should have an upper camel case name
|
||||
const v2: v11 = [[256; v4]; v4];
|
||||
|
||||
const v0: [[usize; v4]; v4] = v6(v8);
|
||||
//~^ ERROR cannot find value `v8` in this scope
|
||||
//~| ERROR cannot find function `v6` in this scope
|
||||
pub struct v17<const v10: usize, const v7: v11> {
|
||||
//~^ WARN type `v17` should have an upper camel case name
|
||||
//~| ERROR `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter
|
||||
_p: (),
|
||||
}
|
||||
|
||||
impl v17<512, v0> {
|
||||
pub const fn v21() -> v18 {}
|
||||
//~^ ERROR cannot find type `v18` in this scope
|
||||
}
|
||||
|
||||
impl<const v10: usize> v17<v10, v2> {
|
||||
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
|
||||
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
|
||||
pub const fn v21() -> v18 {
|
||||
//~^ ERROR cannot find type `v18` in this scope
|
||||
v18 { _p: () }
|
||||
//~^ ERROR cannot find struct, variant or union type `v18` in this scope
|
||||
}
|
||||
}
|
||||
}
|
||||
pub use v20::{v13, v17};
|
||||
//~^ ERROR unresolved import `v20::v13`
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
error[E0432]: unresolved import `v20::v13`
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:37:15
|
||||
|
|
||||
LL | pub use v20::{v13, v17};
|
||||
| ^^^
|
||||
| |
|
||||
| no `v13` in `v20`
|
||||
| help: a similar name exists in the module: `v11`
|
||||
|
||||
error[E0425]: cannot find value `v8` in this scope
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:13:38
|
||||
|
|
||||
LL | const v0: [[usize; v4]; v4] = v6(v8);
|
||||
| ^^ not found in this scope
|
||||
|
||||
error[E0412]: cannot find type `v18` in this scope
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:23:31
|
||||
|
|
||||
LL | pub type v11 = [[usize; v4]; v4];
|
||||
| --------------------------------- similarly named type alias `v11` defined here
|
||||
...
|
||||
LL | pub const fn v21() -> v18 {}
|
||||
| ^^^ help: a type alias with a similar name exists: `v11`
|
||||
|
||||
error[E0412]: cannot find type `v18` in this scope
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:30:31
|
||||
|
|
||||
LL | pub type v11 = [[usize; v4]; v4];
|
||||
| --------------------------------- similarly named type alias `v11` defined here
|
||||
...
|
||||
LL | pub const fn v21() -> v18 {
|
||||
| ^^^ help: a type alias with a similar name exists: `v11`
|
||||
|
||||
error[E0422]: cannot find struct, variant or union type `v18` in this scope
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:32:13
|
||||
|
|
||||
LL | pub type v11 = [[usize; v4]; v4];
|
||||
| --------------------------------- similarly named type alias `v11` defined here
|
||||
...
|
||||
LL | v18 { _p: () }
|
||||
| ^^^ help: a type alias with a similar name exists: `v11`
|
||||
|
||||
warning: type `v11` should have an upper camel case name
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:9:14
|
||||
|
|
||||
LL | pub type v11 = [[usize; v4]; v4];
|
||||
| ^^^ help: convert the identifier to upper camel case (notice the capitalization): `V11`
|
||||
|
|
||||
= note: `#[warn(non_camel_case_types)]` on by default
|
||||
|
||||
warning: type `v17` should have an upper camel case name
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:16:16
|
||||
|
|
||||
LL | pub struct v17<const v10: usize, const v7: v11> {
|
||||
| ^^^ help: convert the identifier to upper camel case (notice the capitalization): `V17`
|
||||
|
||||
error[E0425]: cannot find function `v6` in this scope
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:13:35
|
||||
|
|
||||
LL | const v0: [[usize; v4]; v4] = v6(v8);
|
||||
| ^^ not found in this scope
|
||||
|
||||
error: `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:16:48
|
||||
|
|
||||
LL | pub struct v17<const v10: usize, const v7: v11> {
|
||||
| ^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool` and `char`
|
||||
help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
|
||||
|
|
||||
LL + #![feature(adt_const_params)]
|
||||
|
|
||||
|
||||
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:27:37
|
||||
|
|
||||
LL | impl<const v10: usize> v17<v10, v2> {
|
||||
| ^^
|
||||
|
||||
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#1}
|
||||
--> $DIR/unevaluated-const-ice-119731.rs:27:37
|
||||
|
|
||||
LL | impl<const v10: usize> v17<v10, v2> {
|
||||
| ^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 9 previous errors; 2 warnings emitted
|
||||
|
||||
Some errors have detailed explanations: E0412, E0422, E0425, E0432.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
||||
|
|
@ -2,13 +2,24 @@ pub struct VTable{
|
|||
state:extern "C" fn(),
|
||||
}
|
||||
|
||||
impl VTable{
|
||||
impl VTable {
|
||||
pub const fn vtable()->&'static VTable{
|
||||
Self::VTABLE
|
||||
}
|
||||
|
||||
const VTABLE: &'static VTable =
|
||||
&VTable{state};
|
||||
|
||||
pub const VTABLE2: &'static VTable =
|
||||
&VTable{state: state2};
|
||||
}
|
||||
|
||||
pub const VTABLE3: &'static VTable =
|
||||
&VTable{state: state3};
|
||||
|
||||
// Only referenced via a `pub const fn`, and yet reachable.
|
||||
extern "C" fn state() {}
|
||||
// Only referenced via a associated `pub const`, and yet reachable.
|
||||
extern "C" fn state2() {}
|
||||
// Only referenced via a free `pub const`, and yet reachable.
|
||||
extern "C" fn state3() {}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,7 @@
|
|||
use issue_63226::VTable;
|
||||
|
||||
static ICE_ICE:&'static VTable=VTable::vtable();
|
||||
static MORE_ICE:&'static VTable=VTable::VTABLE2;
|
||||
static MORE_ICE3:&'static VTable=issue_63226::VTABLE3;
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
18
tests/ui/delegation/ice-issue-122550.rs
Normal file
18
tests/ui/delegation/ice-issue-122550.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
fn description(&self) -> &str {}
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
struct F;
|
||||
struct S(F);
|
||||
|
||||
impl S {
|
||||
reuse <S as Trait>::description { &self.0 }
|
||||
//~^ ERROR mismatched types
|
||||
//~| ERROR the trait bound `S: Trait` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
31
tests/ui/delegation/ice-issue-122550.stderr
Normal file
31
tests/ui/delegation/ice-issue-122550.stderr
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/ice-issue-122550.rs:5:35
|
||||
|
|
||||
LL | fn description(&self) -> &str {}
|
||||
| ^^ expected `&str`, found `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/ice-issue-122550.rs:13:39
|
||||
|
|
||||
LL | reuse <S as Trait>::description { &self.0 }
|
||||
| ^^^^^^^ expected `&S`, found `&F`
|
||||
|
|
||||
= note: expected reference `&S`
|
||||
found reference `&F`
|
||||
|
||||
error[E0277]: the trait bound `S: Trait` is not satisfied
|
||||
--> $DIR/ice-issue-122550.rs:13:12
|
||||
|
|
||||
LL | reuse <S as Trait>::description { &self.0 }
|
||||
| ^ the trait `Trait` is not implemented for `S`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/ice-issue-122550.rs:4:1
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// ICE assertion failed: matches!(self.def_kind(ct.def.did), DefKind :: AnonConst)
|
||||
// issue: rust-lang/rust#108220
|
||||
//@ check-pass
|
||||
|
||||
#![feature(associated_const_equality)]
|
||||
#![allow(unused)]
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct NoPin;
|
||||
|
||||
pub trait SetAlternate<const A: u8> {}
|
||||
|
||||
impl SetAlternate<0> for NoPin {}
|
||||
|
||||
pub trait PinA<PER> {
|
||||
const A: u8;
|
||||
}
|
||||
|
||||
impl<PER> PinA<PER> for NoPin {
|
||||
const A: u8 = 0;
|
||||
}
|
||||
|
||||
pub trait Pins<USART> {}
|
||||
|
||||
impl<USART, T, const TA: u8> Pins<USART> for T where
|
||||
T: PinA<USART, A = { TA }> + SetAlternate<TA>
|
||||
{
|
||||
}
|
||||
|
||||
struct Serial<USART>(PhantomData<USART>);
|
||||
|
||||
impl<USART> Serial<USART> where NoPin: Pins<USART> {}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
error: the compiler unexpectedly panicked. this is a bug.
|
||||
|
||||
query stack during panic:
|
||||
#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body@$DIR/future.rs:33:35: 35:2}: core::future::future::Future`
|
||||
#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body of strlen()}: core::future::future::Future`
|
||||
#1 [codegen_select_candidate] computing candidate for `<strlen as Trait>`
|
||||
end of query stack
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
error[E0792]: expected generic lifetime parameter, found `'_`
|
||||
--> $DIR/defining-use-captured-non-universal-region.rs:13:18
|
||||
|
|
||||
LL | fn foo<'a>() -> impl Sized + 'a {
|
||||
| -- this generic parameter must be used with a generic lifetime parameter
|
||||
...
|
||||
LL | let i: i32 = foo::<'_>();
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// This was an ICE. See #110726.
|
||||
|
||||
//@ revisions: statik infer fixed
|
||||
//@ [fixed] check-pass
|
||||
#![allow(unconditional_recursion)]
|
||||
|
||||
fn foo<'a>() -> impl Sized + 'a {
|
||||
#[cfg(statik)]
|
||||
let i: i32 = foo::<'static>();
|
||||
//[statik]~^ ERROR expected generic lifetime parameter, found `'static`
|
||||
|
||||
#[cfg(infer)]
|
||||
let i: i32 = foo::<'_>();
|
||||
//[infer]~^ ERROR expected generic lifetime parameter, found `'_`
|
||||
|
||||
#[cfg(fixed)]
|
||||
let i: i32 = foo::<'a>();
|
||||
|
||||
i
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
error[E0792]: expected generic lifetime parameter, found `'static`
|
||||
--> $DIR/defining-use-captured-non-universal-region.rs:9:18
|
||||
|
|
||||
LL | fn foo<'a>() -> impl Sized + 'a {
|
||||
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
|
||||
LL | #[cfg(statik)]
|
||||
LL | let i: i32 = foo::<'static>();
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0792`.
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// issue: #110623
|
||||
//@ check-pass
|
||||
|
||||
use std::{collections::BTreeMap, num::ParseIntError, str::FromStr};
|
||||
|
||||
enum FileSystem {
|
||||
File(usize),
|
||||
Directory(BTreeMap<String, FileSystem>),
|
||||
}
|
||||
|
||||
impl FromStr for FileSystem {
|
||||
type Err = ParseIntError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
if s.starts_with("dir") {
|
||||
Ok(Self::new_dir())
|
||||
} else {
|
||||
Ok(Self::File(s.split_whitespace().next().unwrap().parse()?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FileSystem {
|
||||
fn new_dir() -> FileSystem {
|
||||
FileSystem::Directory(BTreeMap::new())
|
||||
}
|
||||
|
||||
fn insert(&mut self, name: String, other: FileSystem) -> Option<FileSystem> {
|
||||
match self {
|
||||
FileSystem::File(_) => panic!("can only insert into directory!"),
|
||||
FileSystem::Directory(tree) => tree.insert(name, other),
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively build a tree from commands. This uses (abuses?)
|
||||
// the fact that `cd /` only appears at the start and that
|
||||
// subsequent `cd`s can only move ONE level to use the recursion
|
||||
// stack as the filesystem stack
|
||||
fn build<'a>(
|
||||
&mut self,
|
||||
mut commands: impl Iterator<Item = &'a str> + 'a,
|
||||
) -> Option<impl Iterator<Item = &'a str> + 'a> {
|
||||
let cmd = commands.next()?;
|
||||
let mut elements = cmd.lines();
|
||||
match elements.next().map(str::trim) {
|
||||
Some("cd /") | None => self.build(commands),
|
||||
Some("cd ..") => {
|
||||
// return to higher scope
|
||||
Some(commands)
|
||||
}
|
||||
Some("ls") => {
|
||||
for item in elements {
|
||||
let name = item.split_whitespace().last().unwrap();
|
||||
let prior = self.insert(name.to_string(), item.parse().unwrap());
|
||||
debug_assert!(prior.is_none());
|
||||
}
|
||||
// continue on
|
||||
self.build(commands)
|
||||
}
|
||||
Some(other_cd) => {
|
||||
let name = other_cd
|
||||
.trim()
|
||||
.strip_prefix("cd ")
|
||||
.expect("expected a cd command");
|
||||
let mut directory = FileSystem::new_dir();
|
||||
let further_commands = directory.build(commands);
|
||||
self.insert(name.to_string(), directory);
|
||||
self.build(further_commands?) // THIS LINE FAILS TO COMPILE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
//@ check-pass
|
||||
|
||||
#![feature(adt_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Bar<const FOO: &'static str> {}
|
||||
impl Bar<"asdf"> for () {}
|
||||
|
||||
fn foo<const FOO: &'static str>() -> impl Bar<"asdf"> {
|
||||
()
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// issue: #111906
|
||||
//@ check-pass
|
||||
|
||||
#![allow(unconditional_recursion)]
|
||||
|
||||
fn foo<'a: 'a>() -> impl Sized {
|
||||
let _: () = foo::<'a>();
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn bar<'a: 'a>() -> impl Sized + 'a {
|
||||
let _: *mut &'a () = bar::<'a>();
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
error: {foo<DefId(..)_'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
|
||||
error: {foo<'{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
|
||||
--> $DIR/erased-regions-in-hidden-ty.rs:12:36
|
||||
|
|
||||
LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: {foo<DefId(..)_'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
|
||||
error: {foo<'{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
|
||||
--> $DIR/erased-regions-in-hidden-ty.rs:12:36
|
||||
|
|
||||
LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
// Make sure that the compiler can handle `ReErased` in the hidden type of an opaque.
|
||||
|
||||
fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
|
||||
//~^ ERROR 'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
|
||||
//~^ ERROR '{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
|
||||
// Can't write whole type because of lack of path sanitization
|
||||
|| ()
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue