Merge from rustc

This commit is contained in:
Ralf Jung 2024-03-26 11:52:02 +01:00
commit c51eb819fe
168 changed files with 2339 additions and 672 deletions

View file

@ -3784,6 +3784,7 @@ dependencies = [
name = "rustc_driver_impl"
version = "0.0.0"
dependencies = [
"ctrlc",
"libc",
"rustc_ast",
"rustc_ast_lowering",

View file

@ -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

View file

@ -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
}
}

View file

@ -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 });

View file

@ -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> {

View file

@ -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();

View file

@ -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

View file

@ -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)
};

View file

@ -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);

View file

@ -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 });

View file

@ -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

View file

@ -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)?;

View file

@ -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>) {}

View file

@ -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);

View file

@ -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" }

View file

@ -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)

View file

@ -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)

View file

@ -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.

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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);
]);

View file

@ -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).

View file

@ -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)
}
}

View file

@ -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

View file

@ -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));

View file

@ -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)");
}

View file

@ -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);
}
}

View file

@ -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) {

View file

@ -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() {

View file

@ -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()
}

View file

@ -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
}

View file

@ -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.

View file

@ -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]

View file

@ -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]

View file

@ -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};

View file

@ -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;

View file

@ -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);

View file

@ -1,4 +1,3 @@
use crate::convert::TryFrom;
use crate::{
intrinsics,
iter::{from_fn, TrustedLen, TrustedRandomAccess},

View file

@ -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;

View file

@ -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 = ()>) {}

View file

@ -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]

View file

@ -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};

View file

@ -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::{

View file

@ -1,4 +1,3 @@
use crate::convert::{TryFrom, TryInto};
use crate::num::NonZero;
#[cfg(debug_assertions)]
use crate::ub_checks::assert_unsafe_precondition;

View file

@ -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};

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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();
}

View file

@ -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");
}
}

View file

@ -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");
}

View file

@ -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" };

View file

@ -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);
}
};
}

View file

@ -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.

View file

@ -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();
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);
}

View file

@ -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",

View file

@ -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

View file

@ -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

View file

@ -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)]

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
+ }

View file

@ -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;
+ }

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,5 @@
# ignore-cross-compile
# needs-unwind contains should_panic test
include ../tools.mk
# Test expected libtest's junit output

View file

@ -1,5 +1,6 @@
//@ run-pass
//@ needs-asm-support
//@ needs-unwind
#![feature(asm_unwind)]

View file

@ -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

View file

@ -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

View file

@ -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() {}

View file

@ -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

View file

@ -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() {}

View file

@ -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

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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() {}

View 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() {}

View 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`.

View file

@ -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() {}

View file

@ -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

View file

@ -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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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() {}

View file

@ -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 {

View file

@ -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 {

View file

@ -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
|| ()
}

View file

@ -2,10 +2,8 @@
use std::fmt::Debug;
fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) {
//~^ ERROR cannot resolve opaque type
|x| x
//~^ ERROR concrete type differs from previous defining opaque type use
//~^ ERROR expected generic lifetime parameter, found `'_`
}
fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) {

Some files were not shown because too many files have changed in this diff Show more