Merge from rustc

This commit is contained in:
Ralf Jung 2023-11-16 10:26:50 +01:00
commit 13bfe141ff
82 changed files with 877 additions and 338 deletions

View file

@ -50,8 +50,8 @@ impl OutlivesSuggestionBuilder {
// naming the `'self` lifetime in methods, etc.
fn region_name_is_suggestable(name: &RegionName) -> bool {
match name.source {
RegionNameSource::NamedEarlyBoundRegion(..)
| RegionNameSource::NamedFreeRegion(..)
RegionNameSource::NamedEarlyParamRegion(..)
| RegionNameSource::NamedLateParamRegion(..)
| RegionNameSource::Static => true,
// Don't give suggestions for upvars, closure return types, or other unnameable

View file

@ -181,8 +181,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref()
&& let ty::BoundRegionKind::BrEnv = free_region.bound_region
if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref()
&& let ty::BoundRegionKind::BrEnv = late_param.bound_region
&& let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty
{
return args.as_closure().kind() == ty::ClosureKind::FnMut;
@ -995,7 +995,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.infcx
.tcx
.is_suitable_region(sub)
.and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.boundregion))
.and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.bound_region))
else {
return;
};
@ -1004,7 +1004,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.infcx
.tcx
.is_suitable_region(sup)
.and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.boundregion))
.and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.bound_region))
else {
return;
};

View file

@ -23,14 +23,14 @@ pub(crate) struct RegionName {
}
/// Denotes the source of a region that is named by a `RegionName`. For example, a free region that
/// was named by the user would get `NamedFreeRegion` and `'static` lifetime would get `Static`.
/// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get `Static`.
/// This helps to print the right kinds of diagnostics.
#[derive(Debug, Clone)]
pub(crate) enum RegionNameSource {
/// A bound (not free) region that was instantiated at the def site (not an HRTB).
NamedEarlyBoundRegion(Span),
NamedEarlyParamRegion(Span),
/// A free region that the user has a name (`'a`) for.
NamedFreeRegion(Span),
NamedLateParamRegion(Span),
/// The `'static` region.
Static,
/// The free region corresponding to the environment of a closure.
@ -69,8 +69,8 @@ pub(crate) enum RegionNameHighlight {
impl RegionName {
pub(crate) fn was_named(&self) -> bool {
match self.source {
RegionNameSource::NamedEarlyBoundRegion(..)
| RegionNameSource::NamedFreeRegion(..)
RegionNameSource::NamedEarlyParamRegion(..)
| RegionNameSource::NamedLateParamRegion(..)
| RegionNameSource::Static => true,
RegionNameSource::SynthesizedFreeEnvRegion(..)
| RegionNameSource::AnonRegionFromArgument(..)
@ -85,8 +85,8 @@ impl RegionName {
pub(crate) fn span(&self) -> Option<Span> {
match self.source {
RegionNameSource::Static => None,
RegionNameSource::NamedEarlyBoundRegion(span)
| RegionNameSource::NamedFreeRegion(span)
RegionNameSource::NamedEarlyParamRegion(span)
| RegionNameSource::NamedLateParamRegion(span)
| RegionNameSource::SynthesizedFreeEnvRegion(span, _)
| RegionNameSource::AnonRegionFromUpvar(span, _)
| RegionNameSource::AnonRegionFromYieldTy(span, _)
@ -104,8 +104,8 @@ impl RegionName {
pub(crate) fn highlight_region_name(&self, diag: &mut Diagnostic) {
match &self.source {
RegionNameSource::NamedFreeRegion(span)
| RegionNameSource::NamedEarlyBoundRegion(span) => {
RegionNameSource::NamedLateParamRegion(span)
| RegionNameSource::NamedEarlyParamRegion(span) => {
diag.span_label(*span, format!("lifetime `{self}` defined here"));
}
RegionNameSource::SynthesizedFreeEnvRegion(span, note) => {
@ -280,28 +280,31 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
debug!("give_region_a_name: error_region = {:?}", error_region);
match *error_region {
ty::ReEarlyBound(ebr) => ebr.has_name().then(|| {
ty::ReEarlyParam(ebr) => ebr.has_name().then(|| {
let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyBoundRegion(span) }
RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyParamRegion(span) }
}),
ty::ReStatic => {
Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static })
}
ty::ReFree(free_region) => match free_region.bound_region {
ty::ReLateParam(late_param) => match late_param.bound_region {
ty::BoundRegionKind::BrNamed(region_def_id, name) => {
// Get the span to point to, even if we don't use the name.
let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP);
debug!(
"bound region named: {:?}, is_named: {:?}",
name,
free_region.bound_region.is_named()
late_param.bound_region.is_named()
);
if free_region.bound_region.is_named() {
if late_param.bound_region.is_named() {
// A named region that is actually named.
Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) })
Some(RegionName {
name,
source: RegionNameSource::NamedLateParamRegion(span),
})
} else if tcx.asyncness(self.mir_hir_id().owner).is_async() {
// If we spuriously thought that the region is named, we should let the
// system generate a true name for error messages. Currently this can
@ -847,7 +850,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
&self,
fr: RegionVid,
) -> Option<RegionName> {
let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
return None;
};
if region.has_name() {
@ -862,7 +865,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let found = tcx
.any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| {
*r == ty::ReEarlyBound(region)
*r == ty::ReEarlyParam(region)
});
Some(RegionName {
@ -881,7 +884,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
&self,
fr: RegionVid,
) -> Option<RegionName> {
let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
return None;
};
if region.has_name() {
@ -943,7 +946,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
&self,
clauses: &[ty::Clause<'tcx>],
ty: Ty<'tcx>,
region: ty::EarlyBoundRegion,
region: ty::EarlyParamRegion,
) -> bool {
let tcx = self.infcx.tcx;
ty.walk().any(|arg| {
@ -956,7 +959,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
ty::ClauseKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
_ => return false,
}
tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyBound(region))
tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region))
})
} else {
false

View file

@ -36,7 +36,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// call `infer_opaque_definition_from_instantiation` to get the inferred
/// type of `_Return<'_a>`. `infer_opaque_definition_from_instantiation`
/// compares lifetimes directly, so we need to map the inference variables
/// back to concrete lifetimes: `'static`, `ReEarlyBound` or `ReFree`.
/// 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
@ -386,7 +386,7 @@ fn check_opaque_type_parameter_valid(
let arg_is_param = match arg.unpack() {
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
GenericArgKind::Lifetime(lt) if is_ty_alias => {
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
matches!(*lt, ty::ReEarlyParam(_) | ty::ReLateParam(_))
}
// FIXME(#113916): we can't currently check for unique lifetime params,
// see that issue for more. We will also have to ignore unused lifetime

View file

@ -462,7 +462,6 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
// "Liberate" the late-bound regions. These correspond to
// "local" free regions.
let bound_inputs_and_output = self.compute_inputs_and_output(&indices, defining_ty);
let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars(
@ -784,7 +783,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
debug!(?br);
let liberated_region =
ty::Region::new_free(self.tcx, all_outlive_scope.to_def_id(), br.kind);
ty::Region::new_late_param(self.tcx, all_outlive_scope.to_def_id(), br.kind);
let region_vid = {
let name = match br.kind.get_name() {
Some(name) => name,
@ -854,7 +853,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
/// Initially, the `UniversalRegionIndices` map contains only the
/// early-bound regions in scope. Once that is all setup, we come
/// in later and instantiate the late-bound regions, and then we
/// insert the `ReFree` version of those into the map as
/// insert the `ReLateParam` version of those into the map as
/// well. These are used for error reporting.
fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) {
debug!("insert_late_bound_region({:?}, {:?})", r, vid);
@ -933,7 +932,8 @@ fn for_each_late_bound_region_in_item<'tcx>(
let ty::BoundVariableKind::Region(bound_region) = bound_var else {
continue;
};
let liberated_region = ty::Region::new_free(tcx, mir_def_id.to_def_id(), bound_region);
let liberated_region =
ty::Region::new_late_param(tcx, mir_def_id.to_def_id(), bound_region);
f(liberated_region);
}
}

View file

@ -368,6 +368,24 @@ pub unsafe fn create_module<'ll>(
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
);
// Add module flags specified via -Z llvm_module_flag
for (key, value, behavior) in &sess.opts.unstable_opts.llvm_module_flag {
let key = format!("{key}\0");
let behavior = match behavior.as_str() {
"error" => llvm::LLVMModFlagBehavior::Error,
"warning" => llvm::LLVMModFlagBehavior::Warning,
"require" => llvm::LLVMModFlagBehavior::Require,
"override" => llvm::LLVMModFlagBehavior::Override,
"append" => llvm::LLVMModFlagBehavior::Append,
"appendunique" => llvm::LLVMModFlagBehavior::AppendUnique,
"max" => llvm::LLVMModFlagBehavior::Max,
"min" => llvm::LLVMModFlagBehavior::Min,
// We already checked this during option parsing
_ => unreachable!(),
};
llvm::LLVMRustAddModuleFlag(llmod, behavior, key.as_ptr().cast(), *value)
}
llmod
}

View file

@ -1520,14 +1520,14 @@ fn report_ice(
/// This allows tools to enable rust logging without having to magically match rustc's
/// tracing crate version.
pub fn init_rustc_env_logger(handler: &EarlyErrorHandler) {
init_env_logger(handler, "RUSTC_LOG");
init_logger(handler, rustc_log::LoggerConfig::from_env("RUSTC_LOG"));
}
/// This allows tools to enable rust logging without having to magically match rustc's
/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
/// other than `RUSTC_LOG`.
pub fn init_env_logger(handler: &EarlyErrorHandler, env: &str) {
if let Err(error) = rustc_log::init_env_logger(env) {
/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose
/// the values directly rather than having to set an environment variable.
pub fn init_logger(handler: &EarlyErrorHandler, cfg: rustc_log::LoggerConfig) {
if let Err(error) = rustc_log::init_logger(cfg) {
handler.early_error(error.to_string());
}
}

View file

@ -258,12 +258,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local());
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion { def_id, index, name })
ty::Region::new_early_param(tcx, ty::EarlyParamRegion { def_id, index, name })
}
Some(rbv::ResolvedArg::Free(scope, id)) => {
let name = lifetime_name(id.expect_local());
ty::Region::new_free(tcx, scope, ty::BrNamed(id, name))
ty::Region::new_late_param(tcx, scope, ty::BrNamed(id, name))
// (*) -- not late-bound, won't change
}

View file

@ -532,8 +532,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReFree(fr) = *r {
ty::Region::new_free(
if let ty::ReLateParam(fr) = *r {
ty::Region::new_late_param(
self.tcx,
fr.scope,
self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region),
@ -1078,20 +1078,20 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
region: ty::Region<'tcx>,
) -> Result<ty::Region<'tcx>, Self::Error> {
match region.kind() {
// Remap all free regions, which correspond to late-bound regions in the function.
ty::ReFree(_) => {}
// Remap late-bound regions from the function.
ty::ReLateParam(_) => {}
// Remap early-bound regions as long as they don't come from the `impl` itself,
// in which case we don't really need to renumber them.
ty::ReEarlyBound(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {}
ty::ReEarlyParam(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {}
_ => return Ok(region),
}
let e = if let Some(region) = self.map.get(&region) {
if let ty::ReEarlyBound(e) = region.kind() { e } else { bug!() }
if let ty::ReEarlyParam(e) = region.kind() { e } else { bug!() }
} else {
let guar = match region.kind() {
ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. })
| ty::ReFree(ty::FreeRegion {
ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. })
| ty::ReLateParam(ty::LateParamRegion {
bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
..
}) => {
@ -1119,9 +1119,9 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
return Err(guar);
};
Ok(ty::Region::new_early_bound(
Ok(ty::Region::new_early_param(
self.tcx,
ty::EarlyBoundRegion {
ty::EarlyParamRegion {
def_id: e.def_id,
name: e.name,
index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32,

View file

@ -81,8 +81,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
self_type_did: DefId,
adt_to_impl_args: GenericArgsRef<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyEarlyBound)
else {
let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyParam) else {
return Ok(());
};

View file

@ -595,9 +595,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
// Same for the region. In our example, 'a corresponds
// to the 'me parameter.
let region_param = gat_generics.param_at(*region_a_idx, tcx);
let region_param = ty::Region::new_early_bound(
let region_param = ty::Region::new_early_param(
tcx,
ty::EarlyBoundRegion {
ty::EarlyParamRegion {
def_id: region_param.def_id,
index: region_param.index,
name: region_param.name,
@ -628,9 +628,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
debug!("required clause: {region_a} must outlive {region_b}");
// Translate into the generic parameters of the GAT.
let region_a_param = gat_generics.param_at(*region_a_idx, tcx);
let region_a_param = ty::Region::new_early_bound(
let region_a_param = ty::Region::new_early_param(
tcx,
ty::EarlyBoundRegion {
ty::EarlyParamRegion {
def_id: region_a_param.def_id,
index: region_a_param.index,
name: region_a_param.name,
@ -638,9 +638,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
);
// Same for the region.
let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
let region_b_param = ty::Region::new_early_bound(
let region_b_param = ty::Region::new_early_param(
tcx,
ty::EarlyBoundRegion {
ty::EarlyParamRegion {
def_id: region_b_param.def_id,
index: region_b_param.index,
name: region_b_param.name,

View file

@ -550,7 +550,7 @@ fn infringing_fields_error(
.entry((ty.clone(), predicate.clone()))
.or_default()
.push(origin.span());
if let ty::RegionKind::ReEarlyBound(ebr) = *b
if let ty::RegionKind::ReEarlyParam(ebr) = *b
&& ebr.has_name()
{
bounds.push((b.to_string(), a.to_string(), None));

View file

@ -443,7 +443,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
self.tcx.replace_late_bound_regions_uncached(
poly_trait_ref,
|_| {
ty::Region::new_early_bound(self.tcx, ty::EarlyBoundRegion {
ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
def_id: item_def_id,
index: 0,
name: Symbol::intern(&lt_name),

View file

@ -362,10 +362,10 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
) {
for param in opaque_own_params {
let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local());
if let ty::ReEarlyBound(..) = *orig_lifetime {
let dup_lifetime = ty::Region::new_early_bound(
if let ty::ReEarlyParam(..) = *orig_lifetime {
let dup_lifetime = ty::Region::new_early_param(
tcx,
ty::EarlyBoundRegion { def_id: param.def_id, index: param.index, name: param.name },
ty::EarlyParamRegion { def_id: param.def_id, index: param.index, name: param.name },
);
let span = tcx.def_span(param.def_id);
predicates.push((

View file

@ -2012,7 +2012,7 @@ fn is_late_bound_map(
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<!> {
debug!("r={:?}", r.kind());
if let ty::RegionKind::ReEarlyBound(region) = r.kind() {
if let ty::RegionKind::ReEarlyParam(region) = r.kind() {
self.arg_is_constrained[region.index as usize] = true;
}

View file

@ -13,8 +13,8 @@ impl From<ty::ParamTy> for Parameter {
}
}
impl From<ty::EarlyBoundRegion> for Parameter {
fn from(param: ty::EarlyBoundRegion) -> Self {
impl From<ty::EarlyParamRegion> for Parameter {
fn from(param: ty::EarlyParamRegion) -> Self {
Parameter(param.index)
}
}
@ -73,7 +73,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector {
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ReEarlyBound(data) = *r {
if let ty::ReEarlyParam(data) = *r {
self.parameters.push(Parameter::from(data));
}
ControlFlow::Continue(())

View file

@ -146,11 +146,11 @@ fn is_free_region(region: Region<'_>) -> bool {
// These correspond to `T: 'a` relationships:
//
// struct Foo<'a, T> {
// field: &'a T, // this would generate a ReEarlyBound referencing `'a`
// field: &'a T, // this would generate a ReEarlyParam referencing `'a`
// }
//
// We care about these, so fall through.
ty::ReEarlyBound(_) => true,
ty::ReEarlyParam(_) => true,
// These correspond to `T: 'static` relationships which can be
// rather surprising.
@ -173,7 +173,7 @@ fn is_free_region(region: Region<'_>) -> bool {
ty::ReError(_) => false,
// These regions don't appear in types from type declarations:
ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReFree(..) => {
ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReLateParam(..) => {
bug!("unexpected region in outlives inference: {:?}", region);
}
}

View file

@ -413,7 +413,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
variance: VarianceTermPtr<'a>,
) {
match *region {
ty::ReEarlyBound(ref data) => {
ty::ReEarlyParam(ref data) => {
self.add_constraint(current, data.index, variance);
}
@ -428,7 +428,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
ty::ReError(_) => {}
ty::ReFree(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => {
ty::ReLateParam(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => {
// We don't expect to see anything but 'static or bound
// regions when visiting member types or method types.
bug!(

View file

@ -106,7 +106,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeLifetimeCollector<'tcx> {
#[instrument(level = "trace", skip(self), ret)]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() {
if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() {
self.variances[ebr.index as usize] = ty::Invariant;
}
ControlFlow::Continue(())

View file

@ -238,7 +238,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
fn re_infer(&self, def: Option<&ty::GenericParamDef>, span: Span) -> Option<ty::Region<'tcx>> {
let v = match def {
Some(def) => infer::EarlyBoundRegion(span, def.name),
Some(def) => infer::RegionParameterDefinition(span, def.name),
None => infer::MiscVariable(span),
};
Some(self.next_region_var(v))

View file

@ -3296,8 +3296,12 @@ fn print_disambiguation_help<'tcx>(
{
let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
let item_name = item.ident(tcx);
let rcvr_ref = tcx.fn_sig(item.def_id).skip_binder().skip_binder().inputs()[0]
.ref_mutability()
let rcvr_ref = tcx.fn_sig(item.def_id)
.skip_binder()
.skip_binder()
.inputs()
.get(0)
.and_then(|ty| ty.ref_mutability())
.map_or("", |mutbl| mutbl.ref_prefix_str());
let args = format!(
"({}{})",

View file

@ -17,7 +17,7 @@ impl<'a> DescriptionCtx<'a> {
alt_span: Option<Span>,
) -> Option<Self> {
let (span, kind, arg) = match *region {
ty::ReEarlyBound(ref br) => {
ty::ReEarlyParam(ref br) => {
let scope = region.free_region_binding_scope(tcx).expect_local();
let span = if let Some(param) =
tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
@ -32,7 +32,7 @@ impl<'a> DescriptionCtx<'a> {
(Some(span), "as_defined_anon", String::new())
}
}
ty::ReFree(ref fr) => {
ty::ReLateParam(ref fr) => {
if !fr.bound_region.is_named()
&& let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
{
@ -70,7 +70,7 @@ impl<'a> DescriptionCtx<'a> {
ty::RePlaceholder(_) | ty::ReError(_) => return None,
// FIXME(#13998) RePlaceholder should probably print like
// ReFree rather than dumping Debug output on the user.
// ReLateParam rather than dumping Debug output on the user.
//
// We shouldn't really be having unification failures with ReVar
// and ReBound though.

View file

@ -172,7 +172,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
match *r {
ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyBound(..) => r,
ty::ReLateParam(_) | ty::ReErased | ty::ReStatic | ty::ReEarlyParam(..) => r,
ty::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region(
CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) },
@ -223,7 +223,11 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation {
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
match *r {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReErased | ty::ReStatic | ty::ReError(_) => r,
ty::ReEarlyParam(_)
| ty::ReLateParam(_)
| ty::ReErased
| ty::ReStatic
| ty::ReError(_) => r,
ty::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r),
ty::RePlaceholder(..) | ty::ReBound(..) => {
// We only expect region names that the user can type.
@ -359,9 +363,9 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
}
ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReEarlyParam(..)
| ty::ReError(_)
| ty::ReFree(_)
| ty::ReLateParam(_)
| ty::RePlaceholder(..)
| ty::ReErased => self.canonicalize_mode.canonicalize_free_region(self, r),
}

View file

@ -168,7 +168,7 @@ pub(super) fn note_and_explain_region<'tcx>(
alt_span: Option<Span>,
) {
let (description, span) = match *region {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::RePlaceholder(_) | ty::ReStatic => {
ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::RePlaceholder(_) | ty::ReStatic => {
msg_span_from_named_region(tcx, region, alt_span)
}
@ -202,7 +202,7 @@ fn msg_span_from_named_region<'tcx>(
alt_span: Option<Span>,
) -> (String, Option<Span>) {
match *region {
ty::ReEarlyBound(ref br) => {
ty::ReEarlyParam(ref br) => {
let scope = region.free_region_binding_scope(tcx).expect_local();
let span = if let Some(param) =
tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
@ -218,7 +218,7 @@ fn msg_span_from_named_region<'tcx>(
};
(text, Some(span))
}
ty::ReFree(ref fr) => {
ty::ReLateParam(ref fr) => {
if !fr.bound_region.is_named()
&& let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region)
{
@ -315,7 +315,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
// Explain the region we are capturing.
match *hidden_region {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
// Assuming regionck succeeded (*), we ought to always be
// capturing *some* region from the fn header, and hence it
// ought to be free. So under normal circumstances, we will go
@ -2364,7 +2364,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
span,
format!("{labeled_user_string} may not live long enough"),
match sub.kind() {
ty::ReEarlyBound(_) | ty::ReFree(_) if sub.has_name() => error_code!(E0309),
ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309),
ty::ReStatic => error_code!(E0310),
_ => error_code!(E0311),
},
@ -2372,7 +2372,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
'_explain: {
let (description, span) = match sub.kind() {
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
ty::ReEarlyParam(_) | ty::ReLateParam(_) | ty::ReStatic => {
msg_span_from_named_region(self.tcx, sub, Some(span))
}
_ => (format!("lifetime `{sub}`"), Some(span)),
@ -2515,7 +2515,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let (lifetime_def_id, lifetime_scope) = match self.tcx.is_suitable_region(lifetime) {
Some(info) if !lifetime.has_name() => {
(info.boundregion.get_id().unwrap().expect_local(), info.def_id)
(info.bound_region.get_id().unwrap().expect_local(), info.def_id)
}
_ => return lifetime.get_name_or_anon().to_string(),
};
@ -2714,8 +2714,8 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
a: ty::Region<'tcx>,
b: ty::Region<'tcx>,
) -> RelateResult<'tcx, ty::Region<'tcx>> {
if (a.is_var() && b.is_free_or_static())
|| (b.is_var() && a.is_free_or_static())
if (a.is_var() && b.is_free())
|| (b.is_var() && a.is_free())
|| (a.is_var() && b.is_var())
|| a == b
{
@ -2779,7 +2779,9 @@ impl<'tcx> InferCtxt<'tcx> {
br_string(br),
self.tcx.associated_item(def_id).name
),
infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{name}`"),
infer::RegionParameterDefinition(_, name) => {
format!(" for lifetime parameter `{name}`")
}
infer::UpvarRegion(ref upvar_id, _) => {
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
format!(" for capture of `{var_name}` by closure")

View file

@ -70,9 +70,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let anon_reg_sub = self.tcx().is_suitable_region(sub)?;
let scope_def_id_sup = anon_reg_sup.def_id;
let bregion_sup = anon_reg_sup.boundregion;
let bregion_sup = anon_reg_sup.bound_region;
let scope_def_id_sub = anon_reg_sub.def_id;
let bregion_sub = anon_reg_sub.boundregion;
let bregion_sub = anon_reg_sub.bound_region;
let ty_sup = find_anon_type(self.tcx(), sup, &bregion_sup)?;

View file

@ -41,8 +41,8 @@ pub fn find_param_with_region<'tcx>(
replace_region: Region<'tcx>,
) -> Option<AnonymousParamInfo<'tcx>> {
let (id, bound_region) = match *anon_region {
ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
ty::ReEarlyBound(ebr) => {
ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region),
ty::ReEarlyParam(ebr) => {
(tcx.parent(ebr.def_id), ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name))
}
_ => return None, // not a free region

View file

@ -22,8 +22,8 @@ impl<'a, 'tcx> RegionRelations<'a, 'tcx> {
Self { tcx, free_regions }
}
pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> {
self.free_regions.lub_free_regions(self.tcx, r_a, r_b)
pub fn lub_param_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> {
self.free_regions.lub_param_regions(self.tcx, r_a, r_b)
}
}
@ -59,7 +59,7 @@ impl<'tcx> FreeRegionMap<'tcx> {
r_a: Region<'tcx>,
r_b: Region<'tcx>,
) -> bool {
assert!(r_a.is_free_or_static() && r_b.is_free_or_static());
assert!(r_a.is_free() && r_b.is_free());
let re_static = tcx.lifetimes.re_static;
if self.check_relation(re_static, r_b) {
// `'a <= 'static` is always true, and not stored in the
@ -80,15 +80,15 @@ impl<'tcx> FreeRegionMap<'tcx> {
/// cases, this is more conservative than necessary, in order to
/// avoid making arbitrary choices. See
/// `TransitiveRelation::postdom_upper_bound` for more details.
pub fn lub_free_regions(
pub fn lub_param_regions(
&self,
tcx: TyCtxt<'tcx>,
r_a: Region<'tcx>,
r_b: Region<'tcx>,
) -> Region<'tcx> {
debug!("lub_free_regions(r_a={:?}, r_b={:?})", r_a, r_b);
assert!(r_a.is_free());
assert!(r_b.is_free());
debug!("lub_param_regions(r_a={:?}, r_b={:?})", r_a, r_b);
assert!(r_a.is_param());
assert!(r_b.is_param());
let result = if r_a == r_b {
r_a
} else {
@ -97,7 +97,7 @@ impl<'tcx> FreeRegionMap<'tcx> {
Some(r) => r,
}
};
debug!("lub_free_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
debug!("lub_param_regions(r_a={:?}, r_b={:?}) = {:?}", r_a, r_b, result);
result
}
}

View file

@ -115,8 +115,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> {
r
}
ty::ReEarlyBound(..)
| ty::ReFree(_)
ty::ReEarlyParam(..)
| ty::ReLateParam(_)
| ty::ReVar(_)
| ty::RePlaceholder(..)
| ty::ReStatic

View file

@ -340,8 +340,8 @@ where
ty::RePlaceholder(..)
| ty::ReVar(..)
| ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(..) => {
| ty::ReEarlyParam(..)
| ty::ReLateParam(..) => {
// see common code below
}
}

View file

@ -17,7 +17,7 @@ use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ReBound, RePlaceholder, ReVar};
use rustc_middle::ty::{ReEarlyBound, ReErased, ReError, ReFree, ReStatic};
use rustc_middle::ty::{ReEarlyParam, ReErased, ReError, ReLateParam, ReStatic};
use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
use std::fmt;
@ -390,7 +390,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
);
}
ReStatic | ReEarlyBound(_) | ReFree(_) => {
ReStatic | ReEarlyParam(_) | ReLateParam(_) => {
// nothing lives longer than `'static`
// All empty regions are less than early-bound, free,
@ -423,9 +423,9 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
);
}
ReStatic | ReEarlyBound(_) | ReFree(_) => {
ReStatic | ReEarlyParam(_) | ReLateParam(_) => {
// nothing lives longer than `'static`
// All empty regions are less than early-bound, free,
// All empty regions are less than early-bound, late-bound,
// and scope regions.
true
}
@ -450,8 +450,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// Check for the case where we know that `'b: 'static` -- in that case,
// `a <= b` for all `a`.
let b_free_or_static = b.is_free_or_static();
if b_free_or_static && sub_free_regions(tcx.lifetimes.re_static, b) {
if b.is_free() && sub_free_regions(tcx.lifetimes.re_static, b) {
return true;
}
@ -460,8 +459,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// `lub` relationship defined below, since sometimes the "lub"
// is actually the `postdom_upper_bound` (see
// `TransitiveRelation` for more details).
let a_free_or_static = a.is_free_or_static();
if a_free_or_static && b_free_or_static {
if a.is_free() && b.is_free() {
return sub_free_regions(a, b);
}
@ -501,8 +499,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
self.tcx().lifetimes.re_static
}
(ReEarlyBound(_) | ReFree(_), ReEarlyBound(_) | ReFree(_)) => {
self.region_rels.lub_free_regions(a, b)
(ReEarlyParam(_) | ReLateParam(_), ReEarlyParam(_) | ReLateParam(_)) => {
self.region_rels.lub_param_regions(a, b)
}
// For these types, we cannot define any additional
@ -723,13 +721,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
return;
}
// We place free regions first because we are special casing
// SubSupConflict(ReFree, ReFree) when reporting error, and so
// We place late-bound regions first because we are special casing
// SubSupConflict(ReLateParam, ReLateParam) when reporting error, and so
// the user will more likely get a specific suggestion.
fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
match *x.region {
ReEarlyBound(_) => 0,
ReFree(_) => 1,
ReEarlyParam(_) => 0,
ReLateParam(_) => 1,
_ => 2,
}
}

View file

@ -508,7 +508,10 @@ pub enum RegionVariableOrigin {
Coercion(Span),
/// Region variables created as the values for early-bound regions.
EarlyBoundRegion(Span, Symbol),
///
/// FIXME(@lcnr): This can also store a `DefId`, similar to
/// `TypeVariableOriginKind::TypeParameterDefinition`.
RegionParameterDefinition(Span, Symbol),
/// Region variables created when instantiating a binder with
/// existential variables, e.g. when calling a function or method.
@ -1165,7 +1168,7 @@ impl<'tcx> InferCtxt<'tcx> {
GenericParamDefKind::Lifetime => {
// Create a region inference variable for the given
// region parameter definition.
self.next_region_var(EarlyBoundRegion(span, param.name)).into()
self.next_region_var(RegionParameterDefinition(span, param.name)).into()
}
GenericParamDefKind::Type { .. } => {
// Create a type inference variable for the given
@ -2041,7 +2044,7 @@ impl RegionVariableOrigin {
| AddrOfRegion(a)
| Autoref(a)
| Coercion(a)
| EarlyBoundRegion(a, ..)
| RegionParameterDefinition(a, ..)
| BoundRegion(a, ..)
| UpvarRegion(_, a) => a,
Nll(..) => bug!("NLL variable used with `span`"),

View file

@ -138,8 +138,8 @@ impl<'tcx> OutlivesEnvironmentBuilder<'tcx> {
}
OutlivesBound::RegionSubRegion(r_a, r_b) => match (*r_a, *r_b) {
(
ty::ReStatic | ty::ReEarlyBound(_) | ty::ReFree(_),
ty::ReStatic | ty::ReEarlyBound(_) | ty::ReFree(_),
ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
ty::ReStatic | ty::ReEarlyParam(_) | ty::ReLateParam(_),
) => self.region_relation.add(r_a, r_b),
(ty::ReError(_), _) | (_, ty::ReError(_)) => {}
// FIXME(#109628): We shouldn't have existential variables in implied bounds.

View file

@ -662,8 +662,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
match *region {
ty::ReStatic
| ty::ReErased
| ty::ReFree(..)
| ty::ReEarlyBound(..)
| ty::ReLateParam(..)
| ty::ReEarlyParam(..)
| ty::ReError(_) => ty::UniverseIndex::ROOT,
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReVar(vid) => self.var_universe(vid),

View file

@ -769,6 +769,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(instrument_xray, Some(InstrumentXRay::default()));
tracked!(link_directives, false);
tracked!(link_only, true);
tracked!(llvm_module_flag, vec![("bar".to_string(), 123, "max".to_string())]);
tracked!(llvm_plugins, vec![String::from("plugin_name")]);
tracked!(location_detail, LocationDetail { file: true, line: false, column: false });
tracked!(maximal_hir_to_mir_coverage, true);

View file

@ -1910,7 +1910,7 @@ impl ExplicitOutlivesRequirements {
.iter()
.filter_map(|(clause, _)| match clause.kind().skip_binder() {
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => match *a {
ty::ReEarlyBound(ebr) if ebr.def_id == def_id => Some(b),
ty::ReEarlyParam(ebr) if ebr.def_id == def_id => Some(b),
_ => None,
},
_ => None,
@ -1953,7 +1953,7 @@ impl ExplicitOutlivesRequirements {
let is_inferred = match tcx.named_bound_var(lifetime.hir_id) {
Some(ResolvedArg::EarlyBound(def_id)) => inferred_outlives
.iter()
.any(|r| matches!(**r, ty::ReEarlyBound(ebr) if { ebr.def_id == def_id })),
.any(|r| matches!(**r, ty::ReEarlyParam(ebr) if { ebr.def_id == def_id })),
_ => false,
};

View file

@ -14,7 +14,7 @@
//!
//! ```
//! fn main() {
//! rustc_log::init_env_logger("LOG").unwrap();
//! rustc_log::init_logger(rustc_log::LoggerConfig::from_env("LOG")).unwrap();
//!
//! let edition = rustc_span::edition::Edition::Edition2021;
//! rustc_span::create_session_globals_then(edition, || {
@ -52,13 +52,36 @@ use tracing_subscriber::fmt::{
};
use tracing_subscriber::layer::SubscriberExt;
pub fn init_env_logger(env: &str) -> Result<(), Error> {
let filter = match env::var(env) {
/// The values of all the environment variables that matter for configuring a logger.
/// Errors are explicitly preserved so that we can share error handling.
pub struct LoggerConfig {
pub filter: Result<String, VarError>,
pub color_logs: Result<String, VarError>,
pub verbose_entry_exit: Result<String, VarError>,
pub verbose_thread_ids: Result<String, VarError>,
pub backtrace: Result<String, VarError>,
}
impl LoggerConfig {
pub fn from_env(env: &str) -> Self {
LoggerConfig {
filter: env::var(env),
color_logs: env::var(format!("{env}_COLOR")),
verbose_entry_exit: env::var(format!("{env}_ENTRY_EXIT")),
verbose_thread_ids: env::var(format!("{env}_THREAD_IDS")),
backtrace: env::var(format!("{env}_BACKTRACE")),
}
}
}
/// Initialize the logger with the given values for the filter, coloring, and other options env variables.
pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> {
let filter = match cfg.filter {
Ok(env) => EnvFilter::new(env),
_ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)),
};
let color_logs = match env::var(String::from(env) + "_COLOR") {
let color_logs = match cfg.color_logs {
Ok(value) => match value.as_ref() {
"always" => true,
"never" => false,
@ -69,14 +92,14 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> {
Err(VarError::NotUnicode(_value)) => return Err(Error::NonUnicodeColorValue),
};
let verbose_entry_exit = match env::var_os(String::from(env) + "_ENTRY_EXIT") {
None => false,
Some(v) => &v != "0",
let verbose_entry_exit = match cfg.verbose_entry_exit {
Ok(v) => &v != "0",
Err(_) => false,
};
let verbose_thread_ids = match env::var_os(String::from(env) + "_THREAD_IDS") {
None => false,
Some(v) => &v == "1",
let verbose_thread_ids = match cfg.verbose_thread_ids {
Ok(v) => &v == "1",
Err(_) => false,
};
let layer = tracing_tree::HierarchicalLayer::default()
@ -91,7 +114,7 @@ pub fn init_env_logger(env: &str) -> Result<(), Error> {
.with_thread_names(verbose_thread_ids);
let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer);
match env::var(format!("{env}_BACKTRACE")) {
match cfg.backtrace {
Ok(str) => {
let fmt_layer = tracing_subscriber::fmt::layer()
.with_writer(io::stderr)

View file

@ -64,8 +64,8 @@ impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
cmp::min_by_key(r1, r2, |r| match r.kind() {
ty::ReStatic
| ty::ReErased
| ty::ReFree(..)
| ty::ReEarlyBound(..)
| ty::ReLateParam(..)
| ty::ReEarlyParam(..)
| ty::ReError(_) => ty::UniverseIndex::ROOT,
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReVar(..) | ty::ReBound(..) => bug!("not a universal region"),

View file

@ -77,7 +77,7 @@ use std::ops::Deref;
/// picture, but rather the ending point.
//
// FIXME(pnkfelix): this currently derives `PartialOrd` and `Ord` to
// placate the same deriving in `ty::FreeRegion`, but we may want to
// placate the same deriving in `ty::LateParamRegion`, but we may want to
// actually attach a more meaningful ordering to scopes than the one
// generated via deriving here.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, TyEncodable, TyDecodable)]

View file

@ -525,6 +525,13 @@ impl<'tcx> TyCtxt<'tcx> {
self.alloc_map.lock().reserve()
}
/// Miri's provenance GC needs to see all live allocations. The interpreter manages most
/// allocations but some are managed by [`TyCtxt`] and without this method the interpreter
/// doesn't know their [`AllocId`]s are in use.
pub fn iter_allocs<F: FnMut(AllocId)>(self, func: F) {
self.alloc_map.lock().alloc_map.keys().copied().for_each(func)
}
/// Reserves a new ID *if* this allocation has not been dedup-reserved before.
/// Should only be used for "symbolic" allocations (function pointers, vtables, statics), we
/// don't want to dedup IDs for "real" memory!

View file

@ -113,9 +113,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type ExprConst = ty::Expr<'tcx>;
type Region = Region<'tcx>;
type EarlyBoundRegion = ty::EarlyBoundRegion;
type EarlyParamRegion = ty::EarlyParamRegion;
type BoundRegion = ty::BoundRegion;
type FreeRegion = ty::FreeRegion;
type LateParamRegion = ty::LateParamRegion;
type InferRegion = ty::RegionVid;
type PlaceholderRegion = ty::PlaceholderRegion;
@ -445,14 +445,14 @@ impl<'tcx> CommonConsts<'tcx> {
}
}
/// This struct contains information regarding the `ReFree(FreeRegion)` corresponding to a lifetime
/// conflict.
/// This struct contains information regarding a free parameter region,
/// either a `ReEarlyParam` or `ReLateParam`.
#[derive(Debug)]
pub struct FreeRegionInfo {
/// `LocalDefId` corresponding to FreeRegion
/// `LocalDefId` of the free region.
pub def_id: LocalDefId,
/// the bound region corresponding to FreeRegion
pub boundregion: ty::BoundRegionKind,
/// the bound region corresponding to free region.
pub bound_region: ty::BoundRegionKind,
/// checks if bound region is in Impl Item
pub is_impl_item: bool,
}
@ -1080,8 +1080,8 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionInfo> {
let (suitable_region_binding_scope, bound_region) = loop {
let def_id = match region.kind() {
ty::ReFree(fr) => fr.bound_region.get_id()?.as_local()?,
ty::ReEarlyBound(ebr) => ebr.def_id.expect_local(),
ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?,
ty::ReEarlyParam(ebr) => ebr.def_id.expect_local(),
_ => return None, // not a free region
};
let scope = self.local_parent(def_id);
@ -1102,11 +1102,7 @@ impl<'tcx> TyCtxt<'tcx> {
_ => false,
};
Some(FreeRegionInfo {
def_id: suitable_region_binding_scope,
boundregion: bound_region,
is_impl_item,
})
Some(FreeRegionInfo { def_id: suitable_region_binding_scope, bound_region, is_impl_item })
}
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
@ -1743,7 +1739,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
ty::Region::new_early_bound(self, param.to_early_bound_region_data()).into()
ty::Region::new_early_param(self, param.to_early_bound_region_data()).into()
}
GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(),
GenericParamDefKind::Const { .. } => ty::Const::new_param(
@ -2040,7 +2036,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Given the def-id of an early-bound lifetime on an RPIT corresponding to
/// a duplicated captured lifetime, map it back to the early- or late-bound
/// lifetime of the function from which it originally as captured. If it is
/// a late-bound lifetime, this will represent the liberated (`ReFree`) lifetime
/// a late-bound lifetime, this will represent the liberated (`ReLateParam`) lifetime
/// of the signature.
// FIXME(RPITIT): if we ever synthesize new lifetimes for RPITITs and not just
// re-use the generics of the opaque, this function will need to be tweaked slightly.
@ -2079,9 +2075,9 @@ impl<'tcx> TyCtxt<'tcx> {
}
let generics = self.generics_of(new_parent);
return ty::Region::new_early_bound(
return ty::Region::new_early_param(
self,
ty::EarlyBoundRegion {
ty::EarlyParamRegion {
def_id: ebv,
index: generics
.param_def_id_to_index(self, ebv)
@ -2092,7 +2088,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
Some(resolve_bound_vars::ResolvedArg::LateBound(_, _, lbv)) => {
let new_parent = self.parent(lbv);
return ty::Region::new_free(
return ty::Region::new_late_param(
self,
new_parent,
ty::BoundRegionKind::BrNamed(

View file

@ -326,7 +326,7 @@ impl<'tcx> TyCtxt<'tcx> {
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.replace_late_bound_regions_uncached(value, |br| {
ty::Region::new_free(self, all_outlive_scope, br.kind)
ty::Region::new_late_param(self, all_outlive_scope, br.kind)
})
}

View file

@ -809,7 +809,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
#[cold]
#[inline(never)]
fn region_param_out_of_range(data: ty::EarlyBoundRegion, args: &[GenericArg<'_>]) -> ! {
fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! {
bug!(
"Region parameter out of range when substituting in region {} (index={}, args = {:?})",
data.name,
@ -820,7 +820,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
#[cold]
#[inline(never)]
fn region_param_invalid(data: ty::EarlyBoundRegion, other: GenericArgKind<'_>) -> ! {
fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! {
bug!(
"Unexpected parameter {:?} when substituting in region {} (index={})",
other,
@ -835,7 +835,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
// regions that appear in a function signature is done using
// the specialized routine `ty::replace_late_regions()`.
match *r {
ty::ReEarlyBound(data) => {
ty::ReEarlyParam(data) => {
let rk = self.args.get(data.index as usize).map(|k| k.unpack());
match rk {
Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
@ -844,7 +844,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ArgFolder<'a, 'tcx> {
}
}
ty::ReBound(..)
| ty::ReFree(_)
| ty::ReLateParam(_)
| ty::ReStatic
| ty::RePlaceholder(_)
| ty::ReErased

View file

@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::Span;
use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum GenericParamDefKind {
@ -62,9 +62,9 @@ pub struct GenericParamDef {
}
impl GenericParamDef {
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
pub fn to_early_bound_region_data(&self) -> ty::EarlyParamRegion {
if let GenericParamDefKind::Lifetime = self.kind {
ty::EarlyBoundRegion { def_id: self.def_id, index: self.index, name: self.name }
ty::EarlyParamRegion { def_id: self.def_id, index: self.index, name: self.name }
} else {
bug!("cannot convert a non-lifetime parameter def to an early bound region")
}
@ -260,10 +260,10 @@ impl<'tcx> Generics {
}
}
/// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
/// Returns the `GenericParamDef` associated with this `EarlyParamRegion`.
pub fn region_param(
&'tcx self,
param: &EarlyBoundRegion,
param: &ty::EarlyParamRegion,
tcx: TyCtxt<'tcx>,
) -> &'tcx GenericParamDef {
let param = self.param_at(param.index as usize, tcx);

View file

@ -98,11 +98,12 @@ pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind,
ConstVid, CoroutineArgs, CoroutineArgsParts, EarlyBoundRegion, EffectVid, ExistentialPredicate,
ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, InlineConstArgs,
InlineConstArgsParts, ParamConst, ParamTy, PolyExistentialPredicate, PolyExistentialProjection,
PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, PredicateKind, Region,
RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
ConstVid, CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, EffectVid, ExistentialPredicate,
ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs,
InlineConstArgsParts, LateParamRegion, ParamConst, ParamTy, PolyExistentialPredicate,
PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef,
PredicateKind, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs,
VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
pub use self::typeck_results::{
@ -463,7 +464,7 @@ pub struct CReaderCacheKey {
#[rustc_pass_by_value]
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
impl ty::EarlyBoundRegion {
impl EarlyParamRegion {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
pub fn has_name(&self) -> bool {

View file

@ -113,7 +113,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
ty::ReError(_) => return r,
// The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) => {}
ty::ReEarlyParam(_) | ty::ReLateParam(_) => {}
ty::RePlaceholder(_) | ty::ReVar(_) => {
// All of the regions in the type should either have been

View file

@ -2158,10 +2158,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
let identify_regions = self.tcx.sess.opts.unstable_opts.identify_regions;
match *region {
ty::ReEarlyBound(ref data) => data.has_name(),
ty::ReEarlyParam(ref data) => data.has_name(),
ty::ReBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReFree(ty::FreeRegion { bound_region: br, .. })
| ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder {
bound: ty::BoundRegion { kind: br, .. }, ..
}) => {
@ -2228,14 +2228,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
// to fit that into a short string. Hence the recommendation to use
// `explain_region()` or `note_and_explain_region()`.
match *region {
ty::ReEarlyBound(ref data) => {
ty::ReEarlyParam(ref data) => {
if data.name != kw::Empty {
p!(write("{}", data.name));
return Ok(());
}
}
ty::ReBound(_, ty::BoundRegion { kind: br, .. })
| ty::ReFree(ty::FreeRegion { bound_region: br, .. })
| ty::ReLateParam(ty::LateParamRegion { bound_region: br, .. })
| ty::RePlaceholder(ty::Placeholder {
bound: ty::BoundRegion { kind: br, .. }, ..
}) => {

View file

@ -79,9 +79,9 @@ impl fmt::Debug for ty::BoundRegionKind {
}
}
impl fmt::Debug for ty::FreeRegion {
impl fmt::Debug for ty::LateParamRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region)
write!(f, "ReLateParam({:?}, {:?})", self.scope, self.bound_region)
}
}
@ -444,7 +444,7 @@ TrivialTypeTraversalImpls! {
crate::ty::Placeholder<crate::ty::BoundRegion>,
crate::ty::Placeholder<crate::ty::BoundTy>,
crate::ty::Placeholder<ty::BoundVar>,
crate::ty::FreeRegion,
crate::ty::LateParamRegion,
crate::ty::InferTy,
crate::ty::IntVarValue,
crate::ty::adjustment::PointerCoercion,

View file

@ -61,9 +61,9 @@ pub struct TypeAndMut<'tcx> {
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
#[derive(HashStable)]
/// A "free" region `fr` can be interpreted as "some region
/// The parameter representation of late-bound function parameters, "some region
/// at least as big as the scope `fr.scope`".
pub struct FreeRegion {
pub struct LateParamRegion {
pub scope: DefId,
pub bound_region: BoundRegionKind,
}
@ -1468,11 +1468,11 @@ pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
impl<'tcx> Region<'tcx> {
#[inline]
pub fn new_early_bound(
pub fn new_early_param(
tcx: TyCtxt<'tcx>,
early_bound_region: ty::EarlyBoundRegion,
early_bound_region: ty::EarlyParamRegion,
) -> Region<'tcx> {
tcx.intern_region(ty::ReEarlyBound(early_bound_region))
tcx.intern_region(ty::ReEarlyParam(early_bound_region))
}
#[inline]
@ -1493,12 +1493,12 @@ impl<'tcx> Region<'tcx> {
}
#[inline]
pub fn new_free(
pub fn new_late_param(
tcx: TyCtxt<'tcx>,
scope: DefId,
bound_region: ty::BoundRegionKind,
) -> Region<'tcx> {
tcx.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region }))
tcx.intern_region(ty::ReLateParam(ty::LateParamRegion { scope, bound_region }))
}
#[inline]
@ -1549,10 +1549,10 @@ impl<'tcx> Region<'tcx> {
/// to avoid the cost of the `match`.
pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
match kind {
ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region),
ty::ReEarlyParam(region) => Region::new_early_param(tcx, region),
ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region),
ty::ReFree(ty::FreeRegion { scope, bound_region }) => {
Region::new_free(tcx, scope, bound_region)
ty::ReLateParam(ty::LateParamRegion { scope, bound_region }) => {
Region::new_late_param(tcx, scope, bound_region)
}
ty::ReStatic => tcx.lifetimes.re_static,
ty::ReVar(vid) => Region::new_var(tcx, vid),
@ -1574,13 +1574,13 @@ impl<'tcx> Deref for Region<'tcx> {
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
#[derive(HashStable)]
pub struct EarlyBoundRegion {
pub struct EarlyParamRegion {
pub def_id: DefId,
pub index: u32,
pub name: Symbol,
}
impl fmt::Debug for EarlyBoundRegion {
impl fmt::Debug for EarlyParamRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name)
}
@ -1722,9 +1722,9 @@ impl<'tcx> Region<'tcx> {
pub fn get_name(self) -> Option<Symbol> {
if self.has_name() {
match *self {
ty::ReEarlyBound(ebr) => Some(ebr.name),
ty::ReEarlyParam(ebr) => Some(ebr.name),
ty::ReBound(_, br) => br.kind.get_name(),
ty::ReFree(fr) => fr.bound_region.get_name(),
ty::ReLateParam(fr) => fr.bound_region.get_name(),
ty::ReStatic => Some(kw::StaticLifetime),
ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(),
_ => None,
@ -1744,9 +1744,9 @@ impl<'tcx> Region<'tcx> {
/// Is this region named by the user?
pub fn has_name(self) -> bool {
match *self {
ty::ReEarlyBound(ebr) => ebr.has_name(),
ty::ReEarlyParam(ebr) => ebr.has_name(),
ty::ReBound(_, br) => br.kind.is_named(),
ty::ReFree(fr) => fr.bound_region.is_named(),
ty::ReLateParam(fr) => fr.bound_region.is_named(),
ty::ReStatic => true,
ty::ReVar(..) => false,
ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(),
@ -1802,12 +1802,12 @@ impl<'tcx> Region<'tcx> {
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
}
ty::ReEarlyBound(..) => {
ty::ReEarlyParam(..) => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_PARAM;
}
ty::ReFree { .. } => {
ty::ReLateParam { .. } => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
}
@ -1851,22 +1851,28 @@ impl<'tcx> Region<'tcx> {
/// function might return the `DefId` of a closure.
pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId {
match *self {
ty::ReEarlyBound(br) => tcx.parent(br.def_id),
ty::ReFree(fr) => fr.scope,
ty::ReEarlyParam(br) => tcx.parent(br.def_id),
ty::ReLateParam(fr) => fr.scope,
_ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self),
}
}
/// True for free regions other than `'static`.
pub fn is_free(self) -> bool {
matches!(*self, ty::ReEarlyBound(_) | ty::ReFree(_))
pub fn is_param(self) -> bool {
matches!(*self, ty::ReEarlyParam(_) | ty::ReLateParam(_))
}
/// True if `self` is a free region or static.
pub fn is_free_or_static(self) -> bool {
/// True for free region in the current context.
///
/// This is the case for `'static` and param regions.
pub fn is_free(self) -> bool {
match *self {
ty::ReStatic => true,
_ => self.is_free(),
ty::ReStatic | ty::ReEarlyParam(..) | ty::ReLateParam(..) => true,
ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReBound(..)
| ty::ReErased
| ty::ReError(..) => false,
}
}

View file

@ -126,7 +126,7 @@ pub struct TypeckResults<'tcx> {
/// fn(&'a u32) -> u32
/// ```
///
/// Note that `'a` is not bound (it would be an `ReFree`) and
/// Note that `'a` is not bound (it would be an `ReLateParam`) and
/// that the `Foo` opaque type is replaced by its hidden type.
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,

View file

@ -35,12 +35,14 @@ pub struct Discr<'tcx> {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CheckRegions {
No,
/// Only permit early bound regions. This is useful for Adts which
/// can never have late bound regions.
OnlyEarlyBound,
/// Permit both late bound and early bound regions. Use this for functions,
/// which frequently have late bound regions.
Bound,
/// Only permit parameter regions. This should be used
/// for everything apart from functions, which may use
/// `ReBound` to represent late-bound regions.
OnlyParam,
/// Check region parameters from a function definition.
/// Allows `ReEarlyParam` and `ReBound` to handle early
/// and late-bound region parameters.
FromFunction,
}
#[derive(Copy, Clone, Debug)]
@ -431,7 +433,7 @@ impl<'tcx> TyCtxt<'tcx> {
.filter(|&(_, k)| {
match k.unpack() {
GenericArgKind::Lifetime(region) => match region.kind() {
ty::ReEarlyBound(ref ebr) => {
ty::ReEarlyParam(ref ebr) => {
!impl_generics.region_param(ebr, self).pure_wrt_drop
}
// Error: not a region param
@ -468,17 +470,17 @@ impl<'tcx> TyCtxt<'tcx> {
for arg in args {
match arg.unpack() {
GenericArgKind::Lifetime(lt) => match (ignore_regions, lt.kind()) {
(CheckRegions::Bound, ty::ReBound(di, reg)) => {
(CheckRegions::FromFunction, ty::ReBound(di, reg)) => {
if !seen_late.insert((di, reg)) {
return Err(NotUniqueParam::DuplicateParam(lt.into()));
}
}
(CheckRegions::OnlyEarlyBound | CheckRegions::Bound, ty::ReEarlyBound(p)) => {
(CheckRegions::OnlyParam | CheckRegions::FromFunction, ty::ReEarlyParam(p)) => {
if !seen.insert(p.index) {
return Err(NotUniqueParam::DuplicateParam(lt.into()));
}
}
(CheckRegions::OnlyEarlyBound | CheckRegions::Bound, _) => {
(CheckRegions::OnlyParam | CheckRegions::FromFunction, _) => {
return Err(NotUniqueParam::NotParam(lt.into()));
}
(CheckRegions::No, _) => {}

View file

@ -9,13 +9,10 @@
html_playground_url = "https://play.rust-lang.org/",
test(attr(deny(warnings)))
)]
#![cfg_attr(not(bootstrap), doc(rust_logo))]
#![cfg_attr(not(bootstrap), allow(internal_features))]
#![cfg_attr(not(bootstrap), feature(rustdoc_internals))]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
// We want to be able to build this crate with a stable compiler, so no
// `#![feature]` attributes should be added.
// WARNING: We want to be able to build this crate with a stable compiler,
// so no `#![feature]` attributes should be added!
use rustc_lexer::unescape;
pub use Alignment::*;

View file

@ -429,6 +429,7 @@ mod desc {
pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`";
pub const parse_inlining_threshold: &str =
"either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
pub const parse_llvm_module_flag: &str = "<key>:<type>:<value>:<behavior>. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)";
}
mod parse {
@ -1331,6 +1332,33 @@ mod parse {
}
true
}
pub(crate) fn parse_llvm_module_flag(
slot: &mut Vec<(String, u32, String)>,
v: Option<&str>,
) -> bool {
let elements = v.unwrap_or_default().split(':').collect::<Vec<_>>();
let [key, md_type, value, behavior] = elements.as_slice() else {
return false;
};
if *md_type != "u32" {
// Currently we only support u32 metadata flags, but require the
// type for forward-compatibility.
return false;
}
let Ok(value) = value.parse::<u32>() else {
return false;
};
let behavior = behavior.to_lowercase();
let all_behaviors =
["error", "warning", "require", "override", "append", "appendunique", "max", "min"];
if !all_behaviors.contains(&behavior.as_str()) {
return false;
}
slot.push((key.to_string(), value, behavior));
true
}
}
options! {
@ -1629,6 +1657,8 @@ options! {
"link native libraries in the linker invocation (default: yes)"),
link_only: bool = (false, parse_bool, [TRACKED],
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED],
"a list of module flags to pass to LLVM (space separated)"),
llvm_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"a list LLVM plugins to enable (space separated)"),
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],

View file

@ -9,7 +9,7 @@
use crate::rustc_internal::{IndexMap, RustcInternal};
use crate::rustc_smir::hir::def::DefKind;
use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region};
use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyParamRegion, Region};
use rustc_hir as hir;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{alloc_range, AllocId};
@ -682,10 +682,44 @@ impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
type T = stable_mir::mir::Place;
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
stable_mir::mir::Place {
local: self.local.as_usize(),
projection: format!("{:?}", self.projection),
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
}
}
}
impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
type T = stable_mir::mir::ProjectionElem;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use mir::ProjectionElem::*;
match self {
Deref => stable_mir::mir::ProjectionElem::Deref,
Field(idx, ty) => {
stable_mir::mir::ProjectionElem::Field(idx.stable(tables), ty.stable(tables))
}
Index(local) => stable_mir::mir::ProjectionElem::Index(local.stable(tables)),
ConstantIndex { offset, min_length, from_end } => {
stable_mir::mir::ProjectionElem::ConstantIndex {
offset: *offset,
min_length: *min_length,
from_end: *from_end,
}
}
Subslice { from, to, from_end } => stable_mir::mir::ProjectionElem::Subslice {
from: *from,
to: *to,
from_end: *from_end,
},
// MIR includes an `Option<Symbol>` argument for `Downcast` that is the name of the
// variant, used for printing MIR. However this information should also be accessible
// via a lookup using the `VariantIdx`. The `Option<Symbol>` argument is therefore
// dropped when converting to Stable MIR. A brief justification for this decision can be
// found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486
Downcast(_, idx) => stable_mir::mir::ProjectionElem::Downcast(idx.stable(tables)),
OpaqueCast(ty) => stable_mir::mir::ProjectionElem::OpaqueCast(ty.stable(tables)),
Subtype(ty) => stable_mir::mir::ProjectionElem::Subtype(ty.stable(tables)),
}
}
}
@ -693,8 +727,8 @@ impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
type T = stable_mir::mir::UserTypeProjection;
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
UserTypeProjection { base: self.base.as_usize(), projection: format!("{:?}", self.projs) }
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) }
}
}
@ -1695,7 +1729,7 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
use stable_mir::ty::RegionKind;
match self {
ty::ReEarlyBound(early_reg) => RegionKind::ReEarlyBound(EarlyBoundRegion {
ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion {
def_id: tables.region_def(early_reg.def_id),
index: early_reg.index,
name: early_reg.name.to_string(),

View file

@ -282,12 +282,12 @@ fn encode_region<'tcx>(
s.push('E');
compress(dict, DictKey::Region(region), &mut s);
}
// FIXME(@lcnr): Why is `ReEarlyBound` reachable here.
RegionKind::ReEarlyBound(..) | RegionKind::ReErased => {
// FIXME(@lcnr): Why is `ReEarlyParam` reachable here.
RegionKind::ReEarlyParam(..) | RegionKind::ReErased => {
s.push_str("u6region");
compress(dict, DictKey::Region(region), &mut s);
}
RegionKind::ReFree(..)
RegionKind::ReLateParam(..)
| RegionKind::ReStatic
| RegionKind::ReError(_)
| RegionKind::ReVar(..)

View file

@ -237,7 +237,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
CanonicalizeMode::Response { .. } => return r,
},
ty::ReFree(_) | ty::ReEarlyBound(_) => match self.canonicalize_mode {
ty::ReLateParam(_) | ty::ReEarlyParam(_) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"),
},

View file

@ -58,7 +58,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
visitor: &mut V,
) -> ControlFlow<V::BreakTy> {
// HACK: An arbitrary cutoff to avoid dealing with overflow and cycles.
if self.goal.depth >= 10 {
if self.goal.depth <= 10 {
let infcx = self.goal.infcx;
infcx.probe(|_| {
let mut instantiated_goals = vec![];

View file

@ -20,6 +20,7 @@ use crate::traits::{
};
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diagnostic;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{util, TraitEngine};
@ -1002,7 +1003,12 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a> {
// and then prove the resulting predicate as a nested goal.
let trait_ref = match predicate.kind().no_bound_vars() {
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref,
Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))) => {
Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)))
if matches!(
infcx.tcx.def_kind(proj.projection_ty.def_id),
DefKind::AssocTy | DefKind::AssocConst
) =>
{
proj.projection_ty.trait_ref(infcx.tcx)
}
_ => return ControlFlow::Continue(()),

View file

@ -484,7 +484,7 @@ fn is_impossible_associated_item(
t.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ReEarlyBound(param) = r.kind()
if let ty::ReEarlyParam(param) = r.kind()
&& let param_def_id = self.generics.region_param(&param, self.tcx).def_id
&& self.tcx.parent(param_def_id) == self.trait_item_def_id
{

View file

@ -53,9 +53,9 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
DefKind::AssocTy if let Some(data) = tcx.opt_rpitit_info(def_id.to_def_id()) => {
match data {
ty::ImplTraitInTraitData::Trait { fn_def_id, .. } => {
// We need to remap all of the late-bound lifetimes in theassumed wf types
// of the fn (which are represented as ReFree) to the early-bound lifetimes
// of the RPITIT (which are represented by ReEarlyBound owned by the opaque).
// We need to remap all of the late-bound lifetimes in the assumed wf types
// of the fn (which are represented as ReLateParam) to the early-bound lifetimes
// of the RPITIT (which are represented by ReEarlyParam owned by the opaque).
// Luckily, this is very easy to do because we already have that mapping
// stored in the HIR of this RPITIT.
//
@ -65,19 +65,19 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
let mut mapping = FxHashMap::default();
let generics = tcx.generics_of(def_id);
// For each captured opaque lifetime, if it's late-bound (`ReFree` in this case,
// since it has been liberated), map it back to the early-bound lifetime of
// For each captured opaque lifetime, if it's late-bound (`ReLateParam` in this
// case, since it has been liberated), map it back to the early-bound lifetime of
// the GAT. Since RPITITs also have all of the fn's generics, we slice only
// the end of the list corresponding to the opaque's generics.
for param in &generics.params[tcx.generics_of(fn_def_id).params.len()..] {
let orig_lt =
tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local());
if matches!(*orig_lt, ty::ReFree(..)) {
if matches!(*orig_lt, ty::ReLateParam(..)) {
mapping.insert(
orig_lt,
ty::Region::new_early_bound(
ty::Region::new_early_param(
tcx,
ty::EarlyBoundRegion {
ty::EarlyParamRegion {
def_id: param.def_id,
index: param.index,
name: param.name,
@ -90,7 +90,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
let remapped_wf_tys = tcx.fold_regions(
tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(),
|region, _| {
// If `region` is a `ReFree` that is captured by the
// If `region` is a `ReLateParam` that is captured by the
// opaque, remap it to its corresponding the early-
// bound region.
if let Some(remapped_region) = mapping.get(&region) {

View file

@ -159,10 +159,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
// Only check that the parent generics of the TAIT/RPIT are unique.
// the args owned by the opaque are going to always be duplicate
// lifetime params for RPITs, and empty for TAITs.
match self
.tcx
.uses_unique_generic_params(&alias_ty.args[..parent_count], CheckRegions::Bound)
{
match self.tcx.uses_unique_generic_params(
&alias_ty.args[..parent_count],
CheckRegions::FromFunction,
) {
Ok(()) => {
// FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
// supported at all, so this is sound to do, but once we want to support them, you'll

View file

@ -8,7 +8,7 @@ bitflags! {
// required.
/// Does this have `Param`?
const HAS_TY_PARAM = 1 << 0;
/// Does this have `ReEarlyBound`?
/// Does this have `ReEarlyParam`?
const HAS_RE_PARAM = 1 << 1;
/// Does this have `ConstKind::Param`?
const HAS_CT_PARAM = 1 << 2;

View file

@ -47,9 +47,9 @@ pub trait Interner: Sized {
// Kinds of regions
type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
type EarlyBoundRegion: Clone + Debug + Hash + Ord;
type EarlyParamRegion: Clone + Debug + Hash + Ord;
type BoundRegion: Clone + Debug + Hash + Ord;
type FreeRegion: Clone + Debug + Hash + Ord;
type LateParamRegion: Clone + Debug + Hash + Ord;
type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
type PlaceholderRegion: Clone + Debug + Hash + Ord;

View file

@ -22,8 +22,8 @@ use self::RegionKind::*;
/// ```text
/// static ----------+-----...------+ (greatest)
/// | | |
/// early-bound and | |
/// free regions | |
/// param regions | |
/// | | |
/// | | |
/// | | |
/// empty(root) placeholder(U1) |
@ -88,8 +88,8 @@ use self::RegionKind::*;
/// To do this, we replace the bound regions with placeholder markers,
/// which don't satisfy any relation not explicitly provided.
///
/// There are two kinds of placeholder regions in rustc: `ReFree` and
/// `RePlaceholder`. When checking an item's body, `ReFree` is supposed
/// There are two kinds of placeholder regions in rustc: `ReLateParam` and
/// `RePlaceholder`. When checking an item's body, `ReLateParam` is supposed
/// to be used. These also support explicit bounds: both the internally-stored
/// *scope*, which the region is assumed to outlive, as well as other
/// relations stored in the `FreeRegionMap`. Note that these relations
@ -123,26 +123,35 @@ use self::RegionKind::*;
)]
#[derive(TyEncodable, TyDecodable)]
pub enum RegionKind<I: Interner> {
/// Region bound in a type or fn declaration which will be
/// substituted 'early' -- that is, at the same time when type
/// parameters are substituted.
ReEarlyBound(I::EarlyBoundRegion),
/// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
///
/// There are some important differences between region and type parameters.
/// Not all region parameters in the source are represented via `ReEarlyParam`:
/// late-bound function parameters are instead lowered to a `ReBound`. Late-bound
/// regions get eagerly replaced with `ReLateParam` which behaves in the same way as
/// `ReEarlyParam`. Region parameters are also sometimes implicit,
/// e.g. in `impl Trait for &()`.
ReEarlyParam(I::EarlyParamRegion),
/// A higher-ranked region. These represent either late-bound function parameters
/// or bound variables from a `for<'a>`-binder.
///
/// While inside of a function, e.g. during typeck, the late-bound function parameters
/// can be converted to `ReFree` by calling `tcx.liberate_late_bound_regions`.
/// can be converted to `ReLateParam` by calling `tcx.liberate_late_bound_regions`.
///
/// Bound regions inside of types **must not** be erased, as they impact trait
/// selection and the `TypeId` of that type. `for<'a> fn(&'a ())` and
/// `fn(&'static ())` are different types and have to be treated as such.
ReBound(DebruijnIndex, I::BoundRegion),
/// When checking a function body, the types of all arguments and so forth
/// that refer to bound region parameters are modified to refer to free
/// region parameters.
ReFree(I::FreeRegion),
/// Late-bound function parameters are represented using a `ReBound`. When
/// inside of a function, we convert these bound variables to placeholder
/// parameters via `tcx.liberate_late_bound_regions`. They are then treated
/// the same way as `ReEarlyParam` while inside of the function.
///
/// See <https://rustc-dev-guide.rust-lang.org/early-late-bound-summary.html> for
/// more info about early and late bound lifetime parameters.
ReLateParam(I::LateParamRegion),
/// Static data that has an "infinite" lifetime. Top in the region lattice.
ReStatic,
@ -150,8 +159,11 @@ pub enum RegionKind<I: Interner> {
/// A region variable. Should not exist outside of type inference.
ReVar(I::InferRegion),
/// A placeholder region -- basically, the higher-ranked version of `ReFree`.
/// A placeholder region -- the higher-ranked version of `ReLateParam`.
/// Should not exist outside of type inference.
///
/// Used when instantiating a `forall` binder via
/// `infcx.instantiate_binder_with_placeholders`.
RePlaceholder(I::PlaceholderRegion),
/// Erased region, used by trait selection, in MIR and during codegen.
@ -166,9 +178,9 @@ pub enum RegionKind<I: Interner> {
#[inline]
const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
match value {
ReEarlyBound(_) => 0,
ReEarlyParam(_) => 0,
ReBound(_, _) => 1,
ReFree(_) => 2,
ReLateParam(_) => 2,
ReStatic => 3,
ReVar(_) => 4,
RePlaceholder(_) => 5,
@ -180,9 +192,9 @@ const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
// This is manually implemented because a derive would require `I: Copy`
impl<I: Interner> Copy for RegionKind<I>
where
I::EarlyBoundRegion: Copy,
I::EarlyParamRegion: Copy,
I::BoundRegion: Copy,
I::FreeRegion: Copy,
I::LateParamRegion: Copy,
I::InferRegion: Copy,
I::PlaceholderRegion: Copy,
I::ErrorGuaranteed: Copy,
@ -195,9 +207,9 @@ impl<I: Interner> PartialEq for RegionKind<I> {
fn eq(&self, other: &RegionKind<I>) -> bool {
regionkind_discriminant(self) == regionkind_discriminant(other)
&& match (self, other) {
(ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r,
(ReEarlyParam(a_r), ReEarlyParam(b_r)) => a_r == b_r,
(ReBound(a_d, a_r), ReBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
(ReFree(a_r), ReFree(b_r)) => a_r == b_r,
(ReLateParam(a_r), ReLateParam(b_r)) => a_r == b_r,
(ReStatic, ReStatic) => true,
(ReVar(a_r), ReVar(b_r)) => a_r == b_r,
(RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
@ -223,13 +235,13 @@ impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
match this.data {
ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
ReEarlyParam(data) => write!(f, "ReEarlyParam({data:?})"),
ReBound(binder_id, bound_region) => {
write!(f, "ReBound({binder_id:?}, {bound_region:?})")
}
ReFree(fr) => write!(f, "{fr:?}"),
ReLateParam(fr) => write!(f, "{fr:?}"),
ReStatic => f.write_str("ReStatic"),
@ -252,9 +264,9 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
// This is not a derived impl because a derive would require `I: HashStable`
impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
where
I::EarlyBoundRegion: HashStable<CTX>,
I::EarlyParamRegion: HashStable<CTX>,
I::BoundRegion: HashStable<CTX>,
I::FreeRegion: HashStable<CTX>,
I::LateParamRegion: HashStable<CTX>,
I::InferRegion: HashStable<CTX>,
I::PlaceholderRegion: HashStable<CTX>,
{
@ -269,10 +281,10 @@ where
d.hash_stable(hcx, hasher);
r.hash_stable(hcx, hasher);
}
ReEarlyBound(r) => {
ReEarlyParam(r) => {
r.hash_stable(hcx, hasher);
}
ReFree(r) => {
ReLateParam(r) => {
r.hash_stable(hcx, hasher);
}
RePlaceholder(r) => {

View file

@ -398,22 +398,128 @@ pub enum Operand {
pub struct Place {
pub local: Local,
/// projection out of a place (access a field, deref a pointer, etc)
pub projection: String,
pub projection: Vec<ProjectionElem>,
}
// In MIR ProjectionElem is parameterized on the second Field argument and the Index argument. This
// is so it can be used for both Places (for which the projection elements are of type
// ProjectionElem<Local, Ty>) and user-provided type annotations (for which the projection elements
// are of type ProjectionElem<(), ()>). In SMIR we don't need this generality, so we just use
// ProjectionElem for Places.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ProjectionElem {
/// Dereference projections (e.g. `*_1`) project to the address referenced by the base place.
Deref,
/// A field projection (e.g., `f` in `_1.f`) project to a field in the base place. The field is
/// referenced by source-order index rather than the name of the field. The fields type is also
/// given.
Field(FieldIdx, Ty),
/// Index into a slice/array. The value of the index is computed at runtime using the `V`
/// argument.
///
/// Note that this does not also dereference, and so it does not exactly correspond to slice
/// indexing in Rust. In other words, in the below Rust code:
///
/// ```rust
/// let x = &[1, 2, 3, 4];
/// let i = 2;
/// x[i];
/// ```
///
/// The `x[i]` is turned into a `Deref` followed by an `Index`, not just an `Index`. The same
/// thing is true of the `ConstantIndex` and `Subslice` projections below.
Index(Local),
/// Index into a slice/array given by offsets.
///
/// These indices are generated by slice patterns. Easiest to explain by example:
///
/// ```ignore (illustrative)
/// [X, _, .._, _, _] => { offset: 0, min_length: 4, from_end: false },
/// [_, X, .._, _, _] => { offset: 1, min_length: 4, from_end: false },
/// [_, _, .._, X, _] => { offset: 2, min_length: 4, from_end: true },
/// [_, _, .._, _, X] => { offset: 1, min_length: 4, from_end: true },
/// ```
ConstantIndex {
/// index or -index (in Python terms), depending on from_end
offset: u64,
/// The thing being indexed must be at least this long. For arrays this
/// is always the exact length.
min_length: u64,
/// Counting backwards from end? This is always false when indexing an
/// array.
from_end: bool,
},
/// Projects a slice from the base place.
///
/// These indices are generated by slice patterns. If `from_end` is true, this represents
/// `slice[from..slice.len() - to]`. Otherwise it represents `array[from..to]`.
Subslice {
from: u64,
to: u64,
/// Whether `to` counts from the start or end of the array/slice.
from_end: bool,
},
/// "Downcast" to a variant of an enum or a coroutine.
Downcast(VariantIdx),
/// Like an explicit cast from an opaque type to a concrete type, but without
/// requiring an intermediate variable.
OpaqueCast(Ty),
/// A `Subtype(T)` projection is applied to any `StatementKind::Assign` where
/// type of lvalue doesn't match the type of rvalue, the primary goal is making subtyping
/// explicit during optimizations and codegen.
///
/// This projection doesn't impact the runtime behavior of the program except for potentially changing
/// some type metadata of the interpreter or codegen backend.
Subtype(Ty),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UserTypeProjection {
pub base: UserTypeAnnotationIndex,
pub projection: String,
pub projection: Opaque,
}
pub type Local = usize;
pub const RETURN_LOCAL: Local = 0;
/// The source-order index of a field in a variant.
///
/// For example, in the following types,
/// ```ignore(illustrative)
/// enum Demo1 {
/// Variant0 { a: bool, b: i32 },
/// Variant1 { c: u8, d: u64 },
/// }
/// struct Demo2 { e: u8, f: u16, g: u8 }
/// ```
/// `a`'s `FieldIdx` is `0`,
/// `b`'s `FieldIdx` is `1`,
/// `c`'s `FieldIdx` is `0`, and
/// `g`'s `FieldIdx` is `2`.
type FieldIdx = usize;
/// The source-order index of a variant in a type.
///
/// For example, in the following types,
/// ```ignore(illustrative)
/// enum Demo1 {
/// Variant0 { a: bool, b: i32 },
/// Variant1 { c: u8, d: u64 },
/// }
/// struct Demo2 { e: u8, f: u16, g: u8 }
/// ```
/// `a` is in the variant with the `VariantIdx` of `0`,
/// `c` is in the variant with the `VariantIdx` of `1`, and
/// `g` is in the variant with the `VariantIdx` of `0`.
pub type VariantIdx = usize;
type UserTypeAnnotationIndex = usize;
@ -536,6 +642,10 @@ impl Constant {
}
impl Place {
// FIXME(klinvill): This function is expected to resolve down the chain of projections to get
// the type referenced at the end of it. E.g. calling `ty()` on `*(_1.f)` should end up
// returning the type referenced by `f`. The information needed to do this may not currently be
// present in Stable MIR since at least an implementation for AdtDef is probably needed.
pub fn ty(&self, locals: &[LocalDecl]) -> Ty {
let _start_ty = locals[self.local].ty;
todo!("Implement projection")

View file

@ -76,6 +76,15 @@ pub trait MirVisitor {
self.super_place(place, ptx, location)
}
fn visit_projection_elem(
&mut self,
elem: &ProjectionElem,
ptx: PlaceContext,
location: Location,
) {
self.super_projection_elem(elem, ptx, location);
}
fn visit_local(&mut self, local: &Local, ptx: PlaceContext, location: Location) {
let _ = (local, ptx, location);
}
@ -264,7 +273,29 @@ pub trait MirVisitor {
fn super_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) {
let _ = location;
let _ = ptx;
visit_opaque(&Opaque(place.projection.clone()));
self.visit_local(&place.local, ptx, location);
for elem in &place.projection {
self.visit_projection_elem(elem, ptx, location);
}
}
fn super_projection_elem(
&mut self,
elem: &ProjectionElem,
ptx: PlaceContext,
location: Location,
) {
match elem {
ProjectionElem::Deref => {}
ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location),
ProjectionElem::Index(local) => self.visit_local(local, ptx, location),
ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {}
ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {}
ProjectionElem::Downcast(_idx) => {}
ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location),
ProjectionElem::Subtype(ty) => self.visit_ty(ty, location),
}
}
fn super_rvalue(&mut self, rvalue: &Rvalue, location: Location) {

View file

@ -61,7 +61,7 @@ pub struct Region {
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RegionKind {
ReEarlyBound(EarlyBoundRegion),
ReEarlyParam(EarlyParamRegion),
ReBound(DebruijnIndex, BoundRegion),
ReStatic,
RePlaceholder(Placeholder<BoundRegion>),
@ -71,7 +71,7 @@ pub enum RegionKind {
pub(crate) type DebruijnIndex = u32;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct EarlyBoundRegion {
pub struct EarlyParamRegion {
pub def_id: RegionDef,
pub index: u32,
pub name: Symbol,

View file

@ -0,0 +1,12 @@
# `llvm-module-flag`
---------------------
This flag allows adding a key/value to the `!llvm.module.flags` metadata in the
LLVM-IR for a compiled Rust module. The syntax is
`-Z llvm_module_flag=<name>:<type>:<value>:<behavior>`
Currently only u32 values are supported but the type is required to be specified
for forward compatibility. The `behavior` element must match one of the named
LLVM [metadata behaviors](https://llvm.org/docs/LangRef.html#module-flags-metadata)

View file

@ -723,7 +723,7 @@ where
fn region_name(region: Region<'_>) -> Option<Symbol> {
match *region {
ty::ReEarlyBound(r) => Some(r.name),
ty::ReEarlyParam(r) => Some(r.name),
_ => None,
}
}
@ -743,7 +743,7 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
match *r {
// These are the regions that can be seen in the AST.
ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned().unwrap_or(r),
ty::ReEarlyBound(_) | ty::ReStatic | ty::ReBound(..) | ty::ReError(_) => r,
ty::ReEarlyParam(_) | ty::ReStatic | ty::ReBound(..) | ty::ReError(_) => r,
r => bug!("unexpected region: {r:?}"),
}
}

View file

@ -287,9 +287,9 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Life
ty::ReStatic => Some(Lifetime::statik()),
_ if !region.has_name() => None,
ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => Some(Lifetime(name)),
ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
ty::ReEarlyParam(ref data) => Some(Lifetime(data.name)),
ty::ReBound(..)
| ty::ReFree(..)
| ty::ReLateParam(..)
| ty::ReVar(..)
| ty::ReError(_)
| ty::RePlaceholder(..)
@ -1928,13 +1928,13 @@ fn clean_trait_object_lifetime_bound<'tcx>(
// latter contrary to `clean_middle_region`.
match *region {
ty::ReStatic => Some(Lifetime::statik()),
ty::ReEarlyBound(region) if region.name != kw::Empty => Some(Lifetime(region.name)),
ty::ReEarlyParam(region) if region.name != kw::Empty => Some(Lifetime(region.name)),
ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) if name != kw::Empty => {
Some(Lifetime(name))
}
ty::ReEarlyBound(_)
ty::ReEarlyParam(_)
| ty::ReBound(..)
| ty::ReFree(_)
| ty::ReLateParam(_)
| ty::ReVar(_)
| ty::RePlaceholder(_)
| ty::ReErased

View file

@ -53,6 +53,7 @@ extern crate rustc_interface;
extern crate rustc_lexer;
extern crate rustc_lint;
extern crate rustc_lint_defs;
extern crate rustc_log;
extern crate rustc_macros;
extern crate rustc_metadata;
extern crate rustc_middle;
@ -175,7 +176,7 @@ pub fn main() {
// in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml).
init_logging(&handler);
rustc_driver::init_env_logger(&handler, "RUSTDOC_LOG");
rustc_driver::init_logger(&handler, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG"));
let exit_code = rustc_driver::catch_with_exit_code(|| match get_args(&handler) {
Some(args) => main_args(&mut handler, &args, using_internal_features),

View file

@ -175,7 +175,7 @@ impl<'tcx> PassByRefOrValue {
},
// Early bound regions on functions are either from the containing item, are bounded by another
// lifetime, or are used as a bound for a type or lifetime.
RegionKind::ReEarlyBound(..) => continue,
RegionKind::ReEarlyParam(..) => continue,
_ => (),
}

View file

@ -465,9 +465,9 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
.walk()
.filter_map(|arg| {
arg.as_region().and_then(|lifetime| match lifetime.kind() {
ty::ReEarlyBound(r) => Some(r.def_id),
ty::ReEarlyParam(r) => Some(r.def_id),
ty::ReBound(_, r) => r.kind.get_id(),
ty::ReFree(r) => r.bound_region.get_id(),
ty::ReLateParam(r) => r.bound_region.get_id(),
ty::ReStatic
| ty::ReVar(_)
| ty::RePlaceholder(_)

View file

@ -1,6 +1,7 @@
#![feature(rustc_private)]
extern crate rustc_driver;
extern crate rustc_log;
extern crate rustc_session;
use std::env;
@ -173,7 +174,7 @@ fn parse_args() -> (OutputFormat, PathBuf) {
fn main() {
let handler =
rustc_session::EarlyErrorHandler::new(rustc_session::config::ErrorOutputType::default());
rustc_driver::init_env_logger(&handler, "RUST_LOG");
rustc_driver::init_logger(&handler, rustc_log::LoggerConfig::from_env("RUST_LOG"));
let (format, dst) = parse_args();
let result = main_with_result(format, &dst);
if let Err(e) = result {

View file

@ -9,11 +9,12 @@ extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_hir;
extern crate rustc_interface;
extern crate rustc_log;
extern crate rustc_metadata;
extern crate rustc_middle;
extern crate rustc_session;
use std::env;
use std::env::{self, VarError};
use std::num::NonZeroU64;
use std::path::PathBuf;
use std::str::FromStr;
@ -183,45 +184,54 @@ macro_rules! show_error {
($($tt:tt)*) => { show_error(&format_args!($($tt)*)) };
}
fn init_early_loggers(handler: &EarlyErrorHandler) {
// Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
// initialize them both, and we always initialize `miri`'s first.
let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE");
env_logger::init_from_env(env);
// Enable verbose entry/exit logging by default if MIRI_LOG is set.
if env::var_os("MIRI_LOG").is_some() && env::var_os("RUSTC_LOG_ENTRY_EXIT").is_none() {
env::set_var("RUSTC_LOG_ENTRY_EXIT", "1");
}
// We only initialize `rustc` if the env var is set (so the user asked for it).
// If it is not set, we avoid initializing now so that we can initialize
// later with our custom settings, and *not* log anything for what happens before
// `miri` gets started.
if env::var_os("RUSTC_LOG").is_some() {
rustc_driver::init_rustc_env_logger(handler);
}
}
fn rustc_logger_config() -> rustc_log::LoggerConfig {
// Start with the usual env vars.
let mut cfg = rustc_log::LoggerConfig::from_env("RUSTC_LOG");
fn init_late_loggers(handler: &EarlyErrorHandler, tcx: TyCtxt<'_>) {
// We initialize loggers right before we start evaluation. We overwrite the `RUSTC_LOG`
// env var if it is not set, control it based on `MIRI_LOG`.
// (FIXME: use `var_os`, but then we need to manually concatenate instead of `format!`.)
// Overwrite if MIRI_LOG is set.
if let Ok(var) = env::var("MIRI_LOG") {
if env::var_os("RUSTC_LOG").is_none() {
// MIRI_LOG serves as default for RUSTC_LOG, if that is not set.
if matches!(cfg.filter, Err(VarError::NotPresent)) {
// We try to be a bit clever here: if `MIRI_LOG` is just a single level
// used for everything, we only apply it to the parts of rustc that are
// CTFE-related. Otherwise, we use it verbatim for `RUSTC_LOG`.
// This way, if you set `MIRI_LOG=trace`, you get only the right parts of
// rustc traced, but you can also do `MIRI_LOG=miri=trace,rustc_const_eval::interpret=debug`.
if log::Level::from_str(&var).is_ok() {
env::set_var(
"RUSTC_LOG",
format!("rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var}"),
);
cfg.filter = Ok(format!(
"rustc_middle::mir::interpret={var},rustc_const_eval::interpret={var}"
));
} else {
env::set_var("RUSTC_LOG", &var);
cfg.filter = Ok(var);
}
rustc_driver::init_rustc_env_logger(handler);
}
// Enable verbose entry/exit logging by default if MIRI_LOG is set.
if matches!(cfg.verbose_entry_exit, Err(VarError::NotPresent)) {
cfg.verbose_entry_exit = Ok(format!("1"));
}
}
cfg
}
fn init_early_loggers(handler: &EarlyErrorHandler) {
// Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
// initialize them both, and we always initialize `miri`'s first.
let env = env_logger::Env::new().filter("MIRI_LOG").write_style("MIRI_LOG_STYLE");
env_logger::init_from_env(env);
// Now for rustc. We only initialize `rustc` if the env var is set (so the user asked for it).
// If it is not set, we avoid initializing now so that we can initialize later with our custom
// settings, and *not* log anything for what happens before `miri` gets started.
if env::var_os("RUSTC_LOG").is_some() {
rustc_driver::init_logger(handler, rustc_logger_config());
}
}
fn init_late_loggers(handler: &EarlyErrorHandler, tcx: TyCtxt<'_>) {
// If `RUSTC_LOG` is not set, then `init_early_loggers` did not call
// `rustc_driver::init_logger`, so we have to do this now.
if env::var_os("RUSTC_LOG").is_none() {
rustc_driver::init_logger(handler, rustc_logger_config());
}
// If `MIRI_BACKTRACE` is set and `RUSTC_CTFE_BACKTRACE` is not, set `RUSTC_CTFE_BACKTRACE`.

View file

@ -0,0 +1,7 @@
// Test for -Z llvm_module_flags
// compile-flags: -Z llvm_module_flag=foo:u32:123:error -Z llvm_module_flag=bar:u32:42:max
fn main() {}
// CHECK: !{i32 1, !"foo", i32 123}
// CHECK: !{i32 7, !"bar", i32 42}

View file

@ -0,0 +1,173 @@
// run-pass
// Tests the Stable MIR projections API
// ignore-stage1
// ignore-cross-compile
// ignore-remote
// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
// edition: 2021
#![feature(rustc_private)]
#![feature(assert_matches)]
#![feature(control_flow_enum)]
extern crate rustc_hir;
extern crate rustc_middle;
#[macro_use]
extern crate rustc_smir;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate stable_mir;
use rustc_hir::def::DefKind;
use rustc_middle::ty::TyCtxt;
use rustc_smir::rustc_internal;
use stable_mir::mir::{ProjectionElem, Rvalue, StatementKind};
use stable_mir::ty::{RigidTy, TyKind};
use std::assert_matches::assert_matches;
use std::io::Write;
use std::ops::ControlFlow;
const CRATE_NAME: &str = "input";
/// Tests projections within Place objects
fn test_place_projections(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
let items = stable_mir::all_local_items();
let body = get_item(&items, (DefKind::Fn, "projections")).unwrap().body();
assert_eq!(body.blocks.len(), 4);
// The first statement assigns `&s.c` to a local. The projections include a deref for `s`, since
// `s` is passed as a reference argument, and a field access for field `c`.
match &body.blocks[0].statements[0].kind {
StatementKind::Assign(
stable_mir::mir::Place { local: _, projection: local_proj },
Rvalue::Ref(_, _, stable_mir::mir::Place { local: _, projection: r_proj }),
) => {
// We can't match on vecs, only on slices. Comparing statements for equality wouldn't be
// any easier since we'd then have to add in the expected local and region values
// instead of matching on wildcards.
assert!(local_proj.is_empty());
match &r_proj[..] {
// Similarly we can't match against a type, only against its kind.
[ProjectionElem::Deref, ProjectionElem::Field(2, ty)] => assert_matches!(
ty.kind(),
TyKind::RigidTy(RigidTy::Uint(stable_mir::ty::UintTy::U8))
),
other => panic!(
"Unable to match against expected rvalue projection. Expected the projection \
for `s.c`, which is a Deref and u8 Field. Got: {:?}",
other
),
};
}
other => panic!(
"Unable to match against expected Assign statement with a Ref rvalue. Expected the \
statement to assign `&s.c` to a local. Got: {:?}",
other
),
};
// This statement assigns `slice[1]` to a local. The projections include a deref for `slice`,
// since `slice` is a reference, and an index.
match &body.blocks[2].statements[0].kind {
StatementKind::Assign(
stable_mir::mir::Place { local: _, projection: local_proj },
Rvalue::Use(stable_mir::mir::Operand::Copy(stable_mir::mir::Place {
local: _,
projection: r_proj,
})),
) => {
// We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
// since we'd then have to add in the expected local values instead of matching on
// wildcards.
assert!(local_proj.is_empty());
assert_matches!(r_proj[..], [ProjectionElem::Deref, ProjectionElem::Index(_)]);
}
other => panic!(
"Unable to match against expected Assign statement with a Use rvalue. Expected the \
statement to assign `slice[1]` to a local. Got: {:?}",
other
),
};
// The first terminator gets a slice of an array via the Index operation. Specifically it
// performs `&vals[1..3]`. There are no projections in this case, the arguments are just locals.
match &body.blocks[0].terminator.kind {
stable_mir::mir::TerminatorKind::Call { args, .. } =>
// We can't match on vecs, only on slices. Comparing for equality wouldn't be any easier
// since we'd then have to add in the expected local values instead of matching on
// wildcards.
{
match &args[..] {
[
stable_mir::mir::Operand::Move(stable_mir::mir::Place {
local: _,
projection: arg1_proj,
}),
stable_mir::mir::Operand::Move(stable_mir::mir::Place {
local: _,
projection: arg2_proj,
}),
] => {
assert!(arg1_proj.is_empty());
assert!(arg2_proj.is_empty());
}
other => {
panic!(
"Unable to match against expected arguments to Index call. Expected two \
move operands. Got: {:?}",
other
)
}
}
}
other => panic!(
"Unable to match against expected Call terminator. Expected a terminator that calls \
the Index operation. Got: {:?}",
other
),
};
ControlFlow::Continue(())
}
// Use internal API to find a function in a crate.
fn get_item<'a>(
items: &'a stable_mir::CrateItems,
item: (DefKind, &str),
) -> Option<&'a stable_mir::CrateItem> {
items.iter().find(|crate_item| {
crate_item.kind().to_string() == format!("{:?}", item.0) && crate_item.name() == item.1
})
}
/// This test will generate and analyze a dummy crate using the stable mir.
/// For that, it will first write the dummy crate into a file.
/// Then it will create a `StableMir` using custom arguments and then
/// it will run the compiler.
fn main() {
let path = "input.rs";
generate_input(&path).unwrap();
let args = vec![
"rustc".to_string(),
"--crate-type=lib".to_string(),
"--crate-name".to_string(),
CRATE_NAME.to_string(),
path.to_string(),
];
run!(args, tcx, test_place_projections(tcx)).unwrap();
}
fn generate_input(path: &str) -> std::io::Result<()> {
let mut file = std::fs::File::create(path)?;
write!(
file,
r#"
pub struct Struct1 {{ _a: u8, _b: u16, c: u8 }}
pub fn projections(s: &Struct1) -> u8 {{
let v = &s.c;
let vals = [1, 2, 3, 4];
let slice = &vals[1..3];
v + slice[1]
}}"#
)?;
Ok(())
}

View file

@ -6,6 +6,8 @@ LL | impl<T: Send> AnotherTrait for T {}
...
LL | impl AnotherTrait for D<OpaqueType> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
|
= note: upstream crates may add a new impl of trait `std::marker::Send` for type `OpaqueType` in future versions
error: aborting due to previous error

View file

@ -1,4 +1,4 @@
error: {foo<ReEarlyBound(DefId(..), 0, 'a)>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
error: {foo<ReEarlyParam(DefId(..), 0, 'a)>::{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:11:36
|
LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {

View file

@ -1,4 +1,4 @@
error: {foo<ReEarlyBound(DefId(..), 0, 'a)>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
error: {foo<ReEarlyParam(DefId(..), 0, 'a)>::{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:11:36
|
LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {

View file

@ -0,0 +1,14 @@
struct Qux;
trait Foo {
fn foo();
}
trait FooBar {
fn foo() {}
}
fn main() {
Qux.foo();
//~^ ERROR no method named `foo` found for struct `Qux` in the current scope
}

View file

@ -0,0 +1,32 @@
error[E0599]: no method named `foo` found for struct `Qux` in the current scope
--> $DIR/method-ambiguity-no-rcvr.rs:12:9
|
LL | struct Qux;
| ---------- method `foo` not found for this struct
...
LL | Qux.foo();
| ^^^ this is an associated function, not a method
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: candidate #1 is defined in the trait `Foo`
--> $DIR/method-ambiguity-no-rcvr.rs:4:5
|
LL | fn foo();
| ^^^^^^^^^
note: candidate #2 is defined in the trait `FooBar`
--> $DIR/method-ambiguity-no-rcvr.rs:8:5
|
LL | fn foo() {}
| ^^^^^^^^
help: disambiguate the associated function for candidate #1
|
LL | <Qux as Foo>::foo(Qux);
| ~~~~~~~~~~~~~~~~~~~~~~
help: disambiguate the associated function for candidate #2
|
LL | <Qux as FooBar>::foo(Qux);
| ~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
For more information about this error, try `rustc --explain E0599`.

View file

@ -1,17 +1,17 @@
error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a)])` captures lifetime that does not appear in bounds
error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyParam(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyParam(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a)])` captures lifetime that does not appear in bounds
--> $DIR/impl-trait-captures.rs:11:5
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
| -- ------------ opaque type defined here
| |
| hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here
| hidden type `&ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) T` captures the anonymous lifetime defined here
LL | x
| ^
|
help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyBound(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyBound(DefId(0:14 ~ impl_trait_captures[aeb9]::foo::{opaque#0}::'a), 2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound
help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[aeb9]::foo::{opaque#0}), [ReEarlyParam(DefId(0:9 ~ impl_trait_captures[aeb9]::foo::'a), 0, 'a), T, ReEarlyParam(DefId(0:14 ~ impl_trait_captures[aeb9]::foo::{opaque#0}::'a), 2, 'a)])` captures `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))`, you can add an explicit `ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_))` lifetime bound
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReLateParam(DefId(0:8 ~ impl_trait_captures[aeb9]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[aeb9]::foo::'_), '_)) {
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to previous error