Skip to content

Commit 2614e43

Browse files
committed
Auto merge of rust-lang#99753 - Dylan-DPC:rollup-k046940, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - rust-lang#99618 (handle consts with param/infer in `const_eval_resolve` better) - rust-lang#99666 (Restore `Opaque` behavior to coherence check) - rust-lang#99692 (interpret, ptr_offset_from: refactor and test too-far-apart check) - rust-lang#99739 (Remove erroneous E0133 code from an error message.) - rust-lang#99748 (Use full type name instead of just saying `impl Trait` in "captures lifetime" error) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 96b9bb4 + ad32667 commit 2614e43

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+349
-170
lines changed

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ pub(crate) enum RegionErrorKind<'tcx> {
7878
span: Span,
7979
/// The hidden type.
8080
hidden_ty: Ty<'tcx>,
81+
/// The opaque type.
82+
key: ty::OpaqueTypeKey<'tcx>,
8183
/// The unexpected region.
8284
member_region: ty::Region<'tcx>,
8385
},
@@ -205,14 +207,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
205207
}
206208
}
207209

208-
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
210+
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, key, member_region } => {
209211
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
212+
let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
210213
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
211214
self.buffer_error(unexpected_hidden_region_diagnostic(
212215
self.infcx.tcx,
213216
span,
214217
named_ty,
215218
named_region,
219+
named_key,
216220
));
217221
}
218222

compiler/rustc_borrowck/src/member_constraints.rs

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ pub(crate) struct NllMemberConstraint<'tcx> {
3838
/// The hidden type in which `R0` appears. (Used in error reporting.)
3939
pub(crate) hidden_ty: Ty<'tcx>,
4040

41+
pub(crate) key: ty::OpaqueTypeKey<'tcx>,
42+
4143
/// The region `R0`.
4244
pub(crate) member_region_vid: ty::RegionVid,
4345

@@ -90,6 +92,7 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
9092
member_region_vid,
9193
definition_span: m_c.definition_span,
9294
hidden_ty: m_c.hidden_ty,
95+
key: m_c.key,
9396
start_index,
9497
end_index,
9598
});

compiler/rustc_borrowck/src/region_infer/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1763,6 +1763,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
17631763
errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
17641764
span: m_c.definition_span,
17651765
hidden_ty: m_c.hidden_ty,
1766+
key: m_c.key,
17661767
member_region,
17671768
});
17681769
}

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
246246
// after producing an error for each of them.
247247
let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
248248
self.tcx,
249-
def_id,
249+
opaque_type_key,
250250
map,
251251
instantiated_ty.ty,
252252
instantiated_ty.span,
@@ -429,7 +429,7 @@ fn check_opaque_type_parameter_valid(
429429
struct ReverseMapper<'tcx> {
430430
tcx: TyCtxt<'tcx>,
431431

432-
opaque_type_def_id: LocalDefId,
432+
key: ty::OpaqueTypeKey<'tcx>,
433433
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
434434
map_missing_regions_to_empty: bool,
435435

@@ -443,14 +443,14 @@ struct ReverseMapper<'tcx> {
443443
impl<'tcx> ReverseMapper<'tcx> {
444444
fn new(
445445
tcx: TyCtxt<'tcx>,
446-
opaque_type_def_id: LocalDefId,
446+
key: ty::OpaqueTypeKey<'tcx>,
447447
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
448448
hidden_ty: Ty<'tcx>,
449449
span: Span,
450450
) -> Self {
451451
Self {
452452
tcx,
453-
opaque_type_def_id,
453+
key,
454454
map,
455455
map_missing_regions_to_empty: false,
456456
hidden_ty: Some(hidden_ty),
@@ -504,7 +504,7 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
504504
}
505505
}
506506

507-
let generics = self.tcx().generics_of(self.opaque_type_def_id);
507+
let generics = self.tcx().generics_of(self.key.def_id);
508508
match self.map.get(&r.into()).map(|k| k.unpack()) {
509509
Some(GenericArgKind::Lifetime(r1)) => r1,
510510
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
@@ -513,9 +513,10 @@ impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
513513
if let Some(hidden_ty) = self.hidden_ty.take() {
514514
unexpected_hidden_region_diagnostic(
515515
self.tcx,
516-
self.tcx.def_span(self.opaque_type_def_id),
516+
self.tcx.def_span(self.key.def_id),
517517
hidden_ty,
518518
r,
519+
self.key,
519520
)
520521
.emit();
521522
}

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+48-24
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::convert::TryFrom;
77
use rustc_hir::def_id::DefId;
88
use rustc_middle::mir::{
99
self,
10-
interpret::{ConstValue, GlobalId, InterpResult, Scalar},
10+
interpret::{ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar},
1111
BinOp,
1212
};
1313
use rustc_middle::ty;
@@ -328,15 +328,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
328328
// We managed to find a valid allocation for one pointer, but not the other.
329329
// That means they are definitely not pointing to the same allocation.
330330
throw_ub_format!(
331-
"{} called on pointers into different allocations",
331+
"`{}` called on pointers into different allocations",
332332
intrinsic_name
333333
);
334334
}
335335
(Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
336336
// Found allocation for both. They must be into the same allocation.
337337
if a_alloc_id != b_alloc_id {
338338
throw_ub_format!(
339-
"{} called on pointers into different allocations",
339+
"`{}` called on pointers into different allocations",
340340
intrinsic_name
341341
);
342342
}
@@ -346,47 +346,71 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
346346
};
347347

348348
// Compute distance.
349-
let distance = {
350-
// The subtraction is always done in `isize` to enforce
351-
// the "no more than `isize::MAX` apart" requirement.
352-
let a_offset = ImmTy::from_uint(a_offset, isize_layout);
353-
let b_offset = ImmTy::from_uint(b_offset, isize_layout);
354-
let (val, overflowed, _ty) =
355-
self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
349+
let dist = {
350+
// Addresses are unsigned, so this is a `usize` computation. We have to do the
351+
// overflow check separately anyway.
352+
let (val, overflowed, _ty) = {
353+
let a_offset = ImmTy::from_uint(a_offset, usize_layout);
354+
let b_offset = ImmTy::from_uint(b_offset, usize_layout);
355+
self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?
356+
};
356357
if overflowed {
357-
throw_ub_format!("pointers were too far apart for {}", intrinsic_name);
358+
// a < b
359+
if intrinsic_name == sym::ptr_offset_from_unsigned {
360+
throw_ub_format!(
361+
"`{}` called when first pointer has smaller offset than second: {} < {}",
362+
intrinsic_name,
363+
a_offset,
364+
b_offset,
365+
);
366+
}
367+
// The signed form of the intrinsic allows this. If we interpret the
368+
// difference as isize, we'll get the proper signed difference. If that
369+
// seems *positive*, they were more than isize::MAX apart.
370+
let dist = val.to_machine_isize(self)?;
371+
if dist >= 0 {
372+
throw_ub_format!(
373+
"`{}` called when first pointer is too far before second",
374+
intrinsic_name
375+
);
376+
}
377+
dist
378+
} else {
379+
// b >= a
380+
let dist = val.to_machine_isize(self)?;
381+
// If converting to isize produced a *negative* result, we had an overflow
382+
// because they were more than isize::MAX apart.
383+
if dist < 0 {
384+
throw_ub_format!(
385+
"`{}` called when first pointer is too far ahead of second",
386+
intrinsic_name
387+
);
388+
}
389+
dist
358390
}
359-
val.to_machine_isize(self)?
360391
};
361392

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

372-
if intrinsic_name == sym::ptr_offset_from_unsigned && distance < 0 {
373-
throw_ub_format!(
374-
"{} called when first pointer has smaller offset than second: {} < {}",
375-
intrinsic_name,
376-
a_offset,
377-
b_offset,
378-
);
379-
}
380-
381403
// Perform division by size to compute return value.
382404
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
405+
assert!(0 <= dist && dist <= self.machine_isize_max());
383406
usize_layout
384407
} else {
408+
assert!(self.machine_isize_min() <= dist && dist <= self.machine_isize_max());
385409
isize_layout
386410
};
387411
let pointee_layout = self.layout_of(substs.type_at(0))?;
388412
// If ret_layout is unsigned, we checked that so is the distance, so we are good.
389-
let val = ImmTy::from_int(distance, ret_layout);
413+
let val = ImmTy::from_int(dist, ret_layout);
390414
let size = ImmTy::from_int(pointee_layout.size.bytes(), ret_layout);
391415
self.exact_div(&val, &size, dest)?;
392416
}

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,14 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
237237
span: Span,
238238
hidden_ty: Ty<'tcx>,
239239
hidden_region: ty::Region<'tcx>,
240+
opaque_ty: ty::OpaqueTypeKey<'tcx>,
240241
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
242+
let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs);
241243
let mut err = struct_span_err!(
242244
tcx.sess,
243245
span,
244246
E0700,
245-
"hidden type for `impl Trait` captures lifetime that does not appear in bounds",
247+
"hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds",
246248
);
247249

248250
// Explain the region we are capturing.

compiler/rustc_infer/src/infer/mod.rs

+57-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
2121
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
2222
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
2323
use rustc_middle::traits::select;
24-
use rustc_middle::ty::abstract_const::AbstractConst;
24+
use rustc_middle::ty::abstract_const::{AbstractConst, FailureKind};
2525
use rustc_middle::ty::error::{ExpectedFound, TypeError};
2626
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
2727
use rustc_middle::ty::relate::RelateResult;
@@ -966,14 +966,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
966966
#[instrument(skip(self), level = "debug")]
967967
pub fn member_constraint(
968968
&self,
969-
opaque_type_def_id: LocalDefId,
969+
key: ty::OpaqueTypeKey<'tcx>,
970970
definition_span: Span,
971971
hidden_ty: Ty<'tcx>,
972972
region: ty::Region<'tcx>,
973973
in_regions: &Lrc<Vec<ty::Region<'tcx>>>,
974974
) {
975975
self.inner.borrow_mut().unwrap_region_constraints().member_constraint(
976-
opaque_type_def_id,
976+
key,
977977
definition_span,
978978
hidden_ty,
979979
region,
@@ -1675,7 +1675,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16751675
#[instrument(skip(self), level = "debug")]
16761676
pub fn const_eval_resolve(
16771677
&self,
1678-
param_env: ty::ParamEnv<'tcx>,
1678+
mut param_env: ty::ParamEnv<'tcx>,
16791679
unevaluated: ty::Unevaluated<'tcx>,
16801680
span: Option<Span>,
16811681
) -> EvalToValTreeResult<'tcx> {
@@ -1686,10 +1686,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16861686
// variables
16871687
if substs.has_infer_types_or_consts() {
16881688
let ac = AbstractConst::new(self.tcx, unevaluated.shrink());
1689-
if let Ok(None) = ac {
1690-
substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
1691-
} else {
1692-
return Err(ErrorHandled::TooGeneric);
1689+
match ac {
1690+
Ok(None) => {
1691+
substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
1692+
param_env = self.tcx.param_env(unevaluated.def.did);
1693+
}
1694+
Ok(Some(ct)) => {
1695+
if ct.unify_failure_kind(self.tcx) == FailureKind::Concrete {
1696+
substs = replace_param_and_infer_substs_with_placeholder(self.tcx, substs);
1697+
} else {
1698+
return Err(ErrorHandled::TooGeneric);
1699+
}
1700+
}
1701+
Err(guar) => return Err(ErrorHandled::Reported(guar)),
16931702
}
16941703
}
16951704

@@ -2000,3 +2009,43 @@ impl<'tcx> fmt::Debug for RegionObligation<'tcx> {
20002009
)
20012010
}
20022011
}
2012+
2013+
/// Replaces substs that reference param or infer variables with suitable
2014+
/// placeholders. This function is meant to remove these param and infer
2015+
/// substs when they're not actually needed to evaluate a constant.
2016+
fn replace_param_and_infer_substs_with_placeholder<'tcx>(
2017+
tcx: TyCtxt<'tcx>,
2018+
substs: SubstsRef<'tcx>,
2019+
) -> SubstsRef<'tcx> {
2020+
tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
2021+
match arg.unpack() {
2022+
GenericArgKind::Type(_)
2023+
if arg.has_param_types_or_consts() || arg.has_infer_types_or_consts() =>
2024+
{
2025+
tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
2026+
universe: ty::UniverseIndex::ROOT,
2027+
name: ty::BoundVar::from_usize(idx),
2028+
}))
2029+
.into()
2030+
}
2031+
GenericArgKind::Const(ct)
2032+
if ct.has_infer_types_or_consts() || ct.has_param_types_or_consts() =>
2033+
{
2034+
let ty = ct.ty();
2035+
// If the type references param or infer, replace that too...
2036+
if ty.has_param_types_or_consts() || ty.has_infer_types_or_consts() {
2037+
bug!("const `{ct}`'s type should not reference params or types");
2038+
}
2039+
tcx.mk_const(ty::ConstS {
2040+
ty,
2041+
kind: ty::ConstKind::Placeholder(ty::PlaceholderConst {
2042+
universe: ty::UniverseIndex::ROOT,
2043+
name: ty::BoundConst { ty, var: ty::BoundVar::from_usize(idx) },
2044+
}),
2045+
})
2046+
.into()
2047+
}
2048+
_ => arg,
2049+
}
2050+
}))
2051+
}

compiler/rustc_infer/src/infer/opaque_types.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -394,15 +394,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
394394
);
395395

396396
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
397-
op: |r| {
398-
self.member_constraint(
399-
opaque_type_key.def_id,
400-
span,
401-
concrete_ty,
402-
r,
403-
&choice_regions,
404-
)
405-
},
397+
op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions),
406398
});
407399
}
408400

compiler/rustc_infer/src/infer/region_constraints/mod.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_data_structures::intern::Interned;
1212
use rustc_data_structures::sync::Lrc;
1313
use rustc_data_structures::undo_log::UndoLogs;
1414
use rustc_data_structures::unify as ut;
15-
use rustc_hir::def_id::LocalDefId;
1615
use rustc_index::vec::IndexVec;
1716
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
1817
use rustc_middle::ty::ReStatic;
@@ -533,7 +532,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
533532

534533
pub fn member_constraint(
535534
&mut self,
536-
opaque_type_def_id: LocalDefId,
535+
key: ty::OpaqueTypeKey<'tcx>,
537536
definition_span: Span,
538537
hidden_ty: Ty<'tcx>,
539538
member_region: ty::Region<'tcx>,
@@ -546,7 +545,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
546545
}
547546

548547
self.data.member_constraints.push(MemberConstraint {
549-
opaque_type_def_id,
548+
key,
550549
definition_span,
551550
hidden_ty,
552551
member_region,

0 commit comments

Comments
 (0)