Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #99752

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ pub(crate) enum RegionErrorKind<'tcx> {
span: Span,
/// The hidden type.
hidden_ty: Ty<'tcx>,
/// The opaque type.
key: ty::OpaqueTypeKey<'tcx>,
/// The unexpected region.
member_region: ty::Region<'tcx>,
},
Expand Down Expand Up @@ -205,14 +207,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}

RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, key, member_region } => {
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
self.buffer_error(unexpected_hidden_region_diagnostic(
self.infcx.tcx,
span,
named_ty,
named_region,
named_key,
));
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_borrowck/src/member_constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub(crate) struct NllMemberConstraint<'tcx> {
/// The hidden type in which `R0` appears. (Used in error reporting.)
pub(crate) hidden_ty: Ty<'tcx>,

pub(crate) key: ty::OpaqueTypeKey<'tcx>,

/// The region `R0`.
pub(crate) member_region_vid: ty::RegionVid,

Expand Down Expand Up @@ -90,6 +92,7 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
member_region_vid,
definition_span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
key: m_c.key,
start_index,
end_index,
});
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1763,6 +1763,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
key: m_c.key,
member_region,
});
}
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// after producing an error for each of them.
let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
self.tcx,
def_id,
opaque_type_key,
map,
instantiated_ty.ty,
instantiated_ty.span,
Expand Down Expand Up @@ -429,7 +429,7 @@ fn check_opaque_type_parameter_valid(
struct ReverseMapper<'tcx> {
tcx: TyCtxt<'tcx>,

opaque_type_def_id: LocalDefId,
key: ty::OpaqueTypeKey<'tcx>,
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
map_missing_regions_to_empty: bool,

Expand All @@ -443,14 +443,14 @@ struct ReverseMapper<'tcx> {
impl<'tcx> ReverseMapper<'tcx> {
fn new(
tcx: TyCtxt<'tcx>,
opaque_type_def_id: LocalDefId,
key: ty::OpaqueTypeKey<'tcx>,
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
hidden_ty: Ty<'tcx>,
span: Span,
) -> Self {
Self {
tcx,
opaque_type_def_id,
key,
map,
map_missing_regions_to_empty: false,
hidden_ty: Some(hidden_ty),
Expand Down Expand Up @@ -504,7 +504,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
}
}

let generics = self.tcx().generics_of(self.opaque_type_def_id);
let generics = self.tcx().generics_of(self.key.def_id);
match self.map.get(&r.into()).map(|k| k.unpack()) {
Some(GenericArgKind::Lifetime(r1)) => r1,
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
Expand All @@ -513,9 +513,10 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
if let Some(hidden_ty) = self.hidden_ty.take() {
unexpected_hidden_region_diagnostic(
self.tcx,
self.tcx.def_span(self.opaque_type_def_id),
self.tcx.def_span(self.key.def_id),
hidden_ty,
r,
self.key,
)
.emit();
}
Expand Down
72 changes: 48 additions & 24 deletions compiler/rustc_const_eval/src/interpret/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::convert::TryFrom;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
self,
interpret::{ConstValue, GlobalId, InterpResult, Scalar},
interpret::{ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar},
BinOp,
};
use rustc_middle::ty;
Expand Down Expand Up @@ -328,15 +328,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// We managed to find a valid allocation for one pointer, but not the other.
// That means they are definitely not pointing to the same allocation.
throw_ub_format!(
"{} called on pointers into different allocations",
"`{}` called on pointers into different allocations",
intrinsic_name
);
}
(Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
// Found allocation for both. They must be into the same allocation.
if a_alloc_id != b_alloc_id {
throw_ub_format!(
"{} called on pointers into different allocations",
"`{}` called on pointers into different allocations",
intrinsic_name
);
}
Expand All @@ -346,47 +346,71 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
};

// Compute distance.
let distance = {
// The subtraction is always done in `isize` to enforce
// the "no more than `isize::MAX` apart" requirement.
let a_offset = ImmTy::from_uint(a_offset, isize_layout);
let b_offset = ImmTy::from_uint(b_offset, isize_layout);
let (val, overflowed, _ty) =
self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
let dist = {
// Addresses are unsigned, so this is a `usize` computation. We have to do the
// overflow check separately anyway.
let (val, overflowed, _ty) = {
let a_offset = ImmTy::from_uint(a_offset, usize_layout);
let b_offset = ImmTy::from_uint(b_offset, usize_layout);
self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?
};
if overflowed {
throw_ub_format!("pointers were too far apart for {}", intrinsic_name);
// a < b
if intrinsic_name == sym::ptr_offset_from_unsigned {
throw_ub_format!(
"`{}` called when first pointer has smaller offset than second: {} < {}",
intrinsic_name,
a_offset,
b_offset,
);
}
// The signed form of the intrinsic allows this. If we interpret the
// difference as isize, we'll get the proper signed difference. If that
// seems *positive*, they were more than isize::MAX apart.
let dist = val.to_machine_isize(self)?;
if dist >= 0 {
throw_ub_format!(
"`{}` called when first pointer is too far before second",
intrinsic_name
);
}
dist
} else {
// b >= a
let dist = val.to_machine_isize(self)?;
// If converting to isize produced a *negative* result, we had an overflow
// because they were more than isize::MAX apart.
if dist < 0 {
throw_ub_format!(
"`{}` called when first pointer is too far ahead of second",
intrinsic_name
);
}
dist
}
val.to_machine_isize(self)?
};

// Check that the range between them is dereferenceable ("in-bounds or one past the
// end of the same allocation"). This is like the check in ptr_offset_inbounds.
let min_ptr = if distance >= 0 { b } else { a };
let min_ptr = if dist >= 0 { b } else { a };
self.check_ptr_access_align(
min_ptr,
Size::from_bytes(distance.unsigned_abs()),
Size::from_bytes(dist.unsigned_abs()),
Align::ONE,
CheckInAllocMsg::OffsetFromTest,
)?;

if intrinsic_name == sym::ptr_offset_from_unsigned && distance < 0 {
throw_ub_format!(
"{} called when first pointer has smaller offset than second: {} < {}",
intrinsic_name,
a_offset,
b_offset,
);
}

// Perform division by size to compute return value.
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
assert!(0 <= dist && dist <= self.machine_isize_max());
usize_layout
} else {
assert!(self.machine_isize_min() <= dist && dist <= self.machine_isize_max());
isize_layout
};
let pointee_layout = self.layout_of(substs.type_at(0))?;
// If ret_layout is unsigned, we checked that so is the distance, so we are good.
let val = ImmTy::from_int(distance, ret_layout);
let val = ImmTy::from_int(dist, ret_layout);
let size = ImmTy::from_int(pointee_layout.size.bytes(), ret_layout);
self.exact_div(&val, &size, dest)?;
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,12 +237,14 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
span: Span,
hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>,
opaque_ty: ty::OpaqueTypeKey<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs);
let mut err = struct_span_err!(
tcx.sess,
span,
E0700,
"hidden type for `impl Trait` captures lifetime that does not appear in bounds",
"hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds",
);

// Explain the region we are capturing.
Expand Down
65 changes: 57 additions & 8 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
use rustc_middle::traits::select;
use rustc_middle::ty::abstract_const::AbstractConst;
use rustc_middle::ty::abstract_const::{AbstractConst, FailureKind};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::relate::RelateResult;
Expand Down Expand Up @@ -966,14 +966,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub fn member_constraint(
&self,
opaque_type_def_id: LocalDefId,
key: ty::OpaqueTypeKey<'tcx>,
definition_span: Span,
hidden_ty: Ty<'tcx>,
region: ty::Region<'tcx>,
in_regions: &Lrc<Vec<ty::Region<'tcx>>>,
) {
self.inner.borrow_mut().unwrap_region_constraints().member_constraint(
opaque_type_def_id,
key,
definition_span,
hidden_ty,
region,
Expand Down Expand Up @@ -1675,7 +1675,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub fn const_eval_resolve(
&self,
param_env: ty::ParamEnv<'tcx>,
mut param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
Expand All @@ -1686,10 +1686,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// variables
if substs.has_infer_types_or_consts() {
let ac = AbstractConst::new(self.tcx, unevaluated.shrink());
if let Ok(None) = ac {
substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
} else {
return Err(ErrorHandled::TooGeneric);
match ac {
Ok(None) => {
substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
param_env = self.tcx.param_env(unevaluated.def.did);
}
Ok(Some(ct)) => {
if ct.unify_failure_kind(self.tcx) == FailureKind::Concrete {
substs = replace_param_and_infer_substs_with_placeholder(self.tcx, substs);
} else {
return Err(ErrorHandled::TooGeneric);
}
}
Err(guar) => return Err(ErrorHandled::Reported(guar)),
}
}

Expand Down Expand Up @@ -2000,3 +2009,43 @@ impl<'tcx> fmt::Debug for RegionObligation<'tcx> {
)
}
}

/// Replaces substs that reference param or infer variables with suitable
/// placeholders. This function is meant to remove these param and infer
/// substs when they're not actually needed to evaluate a constant.
fn replace_param_and_infer_substs_with_placeholder<'tcx>(
tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>,
) -> SubstsRef<'tcx> {
tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
match arg.unpack() {
GenericArgKind::Type(_)
if arg.has_param_types_or_consts() || arg.has_infer_types_or_consts() =>
{
tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::ROOT,
name: ty::BoundVar::from_usize(idx),
}))
.into()
}
GenericArgKind::Const(ct)
if ct.has_infer_types_or_consts() || ct.has_param_types_or_consts() =>
{
let ty = ct.ty();
// If the type references param or infer, replace that too...
if ty.has_param_types_or_consts() || ty.has_infer_types_or_consts() {
bug!("const `{ct}`'s type should not reference params or types");
}
tcx.mk_const(ty::ConstS {
ty,
kind: ty::ConstKind::Placeholder(ty::PlaceholderConst {
universe: ty::UniverseIndex::ROOT,
name: ty::BoundConst { ty, var: ty::BoundVar::from_usize(idx) },
}),
})
.into()
}
_ => arg,
}
}))
}
10 changes: 1 addition & 9 deletions compiler/rustc_infer/src/infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,15 +394,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);

concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
op: |r| {
self.member_constraint(
opaque_type_key.def_id,
span,
concrete_ty,
r,
&choice_regions,
)
},
op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions),
});
}

Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_infer/src/infer/region_constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_data_structures::unify as ut;
use rustc_hir::def_id::LocalDefId;
use rustc_index::vec::IndexVec;
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
use rustc_middle::ty::ReStatic;
Expand Down Expand Up @@ -533,7 +532,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {

pub fn member_constraint(
&mut self,
opaque_type_def_id: LocalDefId,
key: ty::OpaqueTypeKey<'tcx>,
definition_span: Span,
hidden_ty: Ty<'tcx>,
member_region: ty::Region<'tcx>,
Expand All @@ -546,7 +545,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
}

self.data.member_constraints.push(MemberConstraint {
opaque_type_def_id,
key,
definition_span,
hidden_ty,
member_region,
Expand Down
Loading