提交 7f08d04d 编写于 作者: B bors

Auto merge of #98591 - matthiaskrgr:rollup-7dok1wq, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #98331 (Fix rustdoc argument error)
 - #98506 (Fix span issues in object safety suggestions)
 - #98563 (interpret: refactor allocation info query)
 - #98576 (small regions refactoring)
 - #98577 (Fix "kind" for associated types in trait implementations in rustdoc JSON)
 - #98578 (Remove eddyb from miri failure pings)
 - #98579 (liballoc tests: avoid int2ptr cast)
 - #98581 (Add triagebot mentions.)
 - #98587 (libcore tests: avoid int2ptr casts)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
......@@ -879,7 +879,7 @@ fn give_name_if_anonymous_region_appears_in_impl_signature(
}
let mut found = false;
tcx.fold_regions(tcx.type_of(body_parent_did), &mut true, |r: ty::Region<'tcx>, _| {
tcx.fold_regions(tcx.type_of(body_parent_did), |r: ty::Region<'tcx>, _| {
if *r == ty::ReEarlyBound(region) {
found = true;
}
......
......@@ -1009,7 +1009,7 @@ fn try_promote_type_test_subject(
debug!("try_promote_type_test_subject(ty = {:?})", ty);
let ty = tcx.fold_regions(ty, &mut false, |r, _depth| {
let ty = tcx.fold_regions(ty, |r, _depth| {
let region_vid = self.to_region_vid(r);
// The challenge if this. We have some region variable `r`
......@@ -1289,7 +1289,7 @@ fn normalize_to_scc_representatives<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
tcx.fold_regions(value, &mut false, |r, _db| {
tcx.fold_regions(value, |r, _db| {
let vid = self.to_region_vid(r);
let scc = self.constraint_sccs.scc(vid);
let repr = self.scc_representatives[scc];
......
......@@ -59,7 +59,7 @@ pub(crate) fn infer_opaque_types(
debug!(?concrete_type, ?substs);
let mut subst_regions = vec![self.universal_regions.fr_static];
let universal_substs = infcx.tcx.fold_regions(substs, &mut false, |region, _| {
let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
if let ty::RePlaceholder(..) = region.kind() {
// Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
return region;
......@@ -91,7 +91,7 @@ pub(crate) fn infer_opaque_types(
subst_regions.dedup();
let universal_concrete_type =
infcx.tcx.fold_regions(concrete_type, &mut false, |region, _| match *region {
infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
ty::ReVar(vid) => subst_regions
.iter()
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
......@@ -146,7 +146,7 @@ pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
where
T: TypeFoldable<'tcx>,
{
tcx.fold_regions(ty, &mut false, |region, _| match *region {
tcx.fold_regions(ty, |region, _| match *region {
ty::ReVar(vid) => {
// Find something that we can name
let upper_bound = self.approx_universal_upper_bound(vid);
......
......@@ -31,7 +31,7 @@ pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'_, 'tcx>, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
infcx.tcx.fold_regions(value, |_region, _depth| {
let origin = NllRegionVariableOrigin::Existential { from_forall: false };
infcx.next_nll_region_var(origin)
})
......
......@@ -23,7 +23,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>,
implicit_region_bound: ty::Region<'tcx>,
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
span: Span,
......@@ -36,7 +36,7 @@ pub(crate) fn new(
infcx: &'a InferCtxt<'a, 'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>,
implicit_region_bound: ty::Region<'tcx>,
param_env: ty::ParamEnv<'tcx>,
locations: Locations,
span: Span,
......@@ -108,7 +108,7 @@ pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx
// create new region variables, which can't be done later when
// verifying these bounds.
if t1.has_placeholders() {
t1 = tcx.fold_regions(t1, &mut false, |r, _| match *r {
t1 = tcx.fold_regions(t1, |r, _| match *r {
ty::RePlaceholder(placeholder) => {
self.constraints.placeholder_region(self.infcx, placeholder)
}
......@@ -120,7 +120,7 @@ pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx
&mut *self,
tcx,
region_bound_pairs,
implicit_region_bound,
Some(implicit_region_bound),
param_env,
)
.type_must_outlive(origin, t1, r2);
......
......@@ -61,7 +61,7 @@ pub(crate) struct CreateResult<'tcx> {
pub(crate) fn create<'tcx>(
infcx: &InferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>,
implicit_region_bound: ty::Region<'tcx>,
universal_regions: &Rc<UniversalRegions<'tcx>>,
constraints: &mut MirTypeckRegionConstraints<'tcx>,
) -> CreateResult<'tcx> {
......@@ -223,7 +223,7 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> {
infcx: &'this InferCtxt<'this, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
universal_regions: Rc<UniversalRegions<'tcx>>,
implicit_region_bound: Option<ty::Region<'tcx>>,
implicit_region_bound: ty::Region<'tcx>,
constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
// outputs:
......
......@@ -230,7 +230,7 @@ pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<
self.infcx,
&self.borrowck_context.universal_regions,
&self.region_bound_pairs,
Some(self.implicit_region_bound),
self.implicit_region_bound,
self.param_env,
Locations::All(DUMMY_SP),
DUMMY_SP,
......
......@@ -157,7 +157,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
} = free_region_relations::create(
infcx,
param_env,
Some(implicit_region_bound),
implicit_region_bound,
universal_regions,
&mut constraints,
);
......@@ -1142,7 +1142,7 @@ fn push_region_constraints(
self.infcx,
self.borrowck_context.universal_regions,
self.region_bound_pairs,
Some(self.implicit_region_bound),
self.implicit_region_bound,
self.param_env,
locations,
locations.span(self.body),
......
......@@ -725,7 +725,7 @@ fn replace_free_regions_with_nll_infer_vars<T>(
where
T: TypeFoldable<'tcx>,
{
self.tcx.fold_regions(value, &mut false, |_region, _depth| self.next_nll_region_var(origin))
self.tcx.fold_regions(value, |_region, _depth| self.next_nll_region_var(origin))
}
#[instrument(level = "debug", skip(self, indices))]
......@@ -817,9 +817,7 @@ pub fn fold_to_region_vids<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
tcx.fold_regions(value, &mut false, |region, _| {
tcx.mk_region(ty::ReVar(self.to_region_vid(region)))
})
tcx.fold_regions(value, |region, _| tcx.mk_region(ty::ReVar(self.to_region_vid(region))))
}
}
......
......@@ -56,15 +56,14 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
/// Used by `get_size_and_align` to indicate whether the allocation needs to be live.
#[derive(Debug, Copy, Clone)]
pub enum AllocCheck {
/// Allocation must be live and not a function pointer.
Dereferenceable,
/// Allocations needs to be live, but may be a function pointer.
Live,
/// Allocation may be dead.
MaybeDead,
/// The return value of `get_alloc_info` indicates the "kind" of the allocation.
pub enum AllocKind {
/// A regular live data allocation.
LiveData,
/// A function allocation (that fn ptrs point to).
Function,
/// A dead allocation.
Dead,
}
/// The value of a function pointer.
......@@ -360,8 +359,7 @@ fn get_ptr_access(
align,
CheckInAllocMsg::MemoryAccessTest,
|alloc_id, offset, tag| {
let (size, align) =
self.get_alloc_size_and_align(alloc_id, AllocCheck::Dereferenceable)?;
let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
Ok((size, align, (alloc_id, offset, tag)))
},
)
......@@ -379,15 +377,7 @@ pub fn check_ptr_access_align(
msg: CheckInAllocMsg,
) -> InterpResult<'tcx> {
self.check_and_deref_ptr(ptr, size, Some(align), msg, |alloc_id, _, _| {
let check = match msg {
CheckInAllocMsg::DerefTest | CheckInAllocMsg::MemoryAccessTest => {
AllocCheck::Dereferenceable
}
CheckInAllocMsg::PointerArithmeticTest
| CheckInAllocMsg::OffsetFromTest
| CheckInAllocMsg::InboundsTest => AllocCheck::Live,
};
let (size, align) = self.get_alloc_size_and_align(alloc_id, check)?;
let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?;
Ok((size, align, ()))
})?;
Ok(())
......@@ -655,30 +645,19 @@ pub fn get_alloc_extra_mut<'a>(
/// Obtain the size and alignment of an allocation, even if that allocation has
/// been deallocated.
///
/// If `liveness` is `AllocCheck::MaybeDead`, this function always returns `Ok`.
pub fn get_alloc_size_and_align(
&self,
id: AllocId,
liveness: AllocCheck,
) -> InterpResult<'tcx, (Size, Align)> {
pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) {
// # Regular allocations
// Don't use `self.get_raw` here as that will
// a) cause cycles in case `id` refers to a static
// b) duplicate a global's allocation in miri
if let Some((_, alloc)) = self.memory.alloc_map.get(id) {
return Ok((alloc.size(), alloc.align));
return (alloc.size(), alloc.align, AllocKind::LiveData);
}
// # Function pointers
// (both global from `alloc_map` and local from `extra_fn_ptr_map`)
if self.get_fn_alloc(id).is_some() {
return if let AllocCheck::Dereferenceable = liveness {
// The caller requested no function pointers.
throw_ub!(DerefFunctionPointer(id))
} else {
Ok((Size::ZERO, Align::ONE))
};
return (Size::ZERO, Align::ONE, AllocKind::Function);
}
// # Statics
......@@ -690,32 +669,38 @@ pub fn get_alloc_size_and_align(
// Use size and align of the type.
let ty = self.tcx.type_of(did);
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
Ok((layout.size, layout.align.abi))
(layout.size, layout.align.abi, AllocKind::LiveData)
}
Some(GlobalAlloc::Memory(alloc)) => {
// Need to duplicate the logic here, because the global allocations have
// different associated types than the interpreter-local ones.
let alloc = alloc.inner();
Ok((alloc.size(), alloc.align))
(alloc.size(), alloc.align, AllocKind::LiveData)
}
Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"),
// The rest must be dead.
None => {
if let AllocCheck::MaybeDead = liveness {
// Deallocated pointers are allowed, we should be able to find
// them in the map.
Ok(*self
.memory
.dead_alloc_map
.get(&id)
.expect("deallocated pointers should all be recorded in `dead_alloc_map`"))
} else {
throw_ub!(PointerUseAfterFree(id))
}
// Deallocated pointers are allowed, we should be able to find
// them in the map.
let (size, align) = *self
.memory
.dead_alloc_map
.get(&id)
.expect("deallocated pointers should all be recorded in `dead_alloc_map`");
(size, align, AllocKind::Dead)
}
}
}
/// Obtain the size and alignment of a live allocation.
pub fn get_live_alloc_size_and_align(&self, id: AllocId) -> InterpResult<'tcx, (Size, Align)> {
let (size, align, kind) = self.get_alloc_info(id);
if matches!(kind, AllocKind::Dead) {
throw_ub!(PointerUseAfterFree(id))
}
Ok((size, align))
}
fn get_fn_alloc(&self, id: AllocId) -> Option<FnVal<'tcx, M::ExtraFnVal>> {
if let Some(extra) = self.memory.extra_fn_ptr_map.get(&id) {
Some(FnVal::Other(*extra))
......@@ -1187,9 +1172,7 @@ pub fn scalar_may_be_null(&self, scalar: Scalar<M::PointerTag>) -> InterpResult<
let ptr = self.scalar_to_ptr(scalar)?;
match self.ptr_try_get_alloc_id(ptr) {
Ok((alloc_id, offset, _)) => {
let (size, _align) = self
.get_alloc_size_and_align(alloc_id, AllocCheck::MaybeDead)
.expect("alloc info with MaybeDead cannot fail");
let (size, _align, _kind) = self.get_alloc_info(alloc_id);
// If the pointer is out-of-bounds, it may be null.
// Note that one-past-the-end (offset == size) is still inbounds, and never null.
offset > size
......
......@@ -23,7 +23,7 @@
};
pub use self::intern::{intern_const_alloc_recursive, InternKind};
pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
pub use self::memory::{AllocCheck, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
pub use self::operand::{ImmTy, Immediate, OpTy, Operand};
pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};
pub use self::validity::{CtfeValidationMode, RefTracking};
......
......@@ -932,7 +932,7 @@ fn describe_codegen_flags() {
print_flag_list("-C", config::CG_OPTIONS);
}
fn print_flag_list<T>(
pub fn print_flag_list<T>(
cmdline_opt: &str,
flag_list: &[(&'static str, T, &'static str, &'static str)],
) {
......
......@@ -79,7 +79,7 @@ pub fn find_param_with_region<'tcx>(
// May return None; sometimes the tables are not yet populated.
let ty = fn_sig.inputs()[index];
let mut found_anon_region = false;
let new_param_ty = tcx.fold_regions(ty, &mut false, |r, _| {
let new_param_ty = tcx.fold_regions(ty, |r, _| {
if r == anon_region {
found_anon_region = true;
replace_region
......
......@@ -868,7 +868,7 @@ fn normalize<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
tcx.fold_regions(value, &mut false, |r, _db| match *r {
tcx.fold_regions(value, |r, _db| match *r {
ty::ReVar(rid) => self.resolve_var(rid),
_ => r,
})
......
......@@ -141,9 +141,6 @@ pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionOblig
/// `('a, K)` in this list tells us that the bounds in scope
/// indicate that `K: 'a`, where `K` is either a generic
/// parameter like `T` or a projection like `T::Item`.
/// - `implicit_region_bound`: if some, this is a region bound
/// that is considered to hold for all type parameters (the
/// function body).
/// - `param_env` is the parameter environment for the enclosing function.
/// - `body_id` is the body-id whose region obligations are being
/// processed.
......@@ -151,7 +148,6 @@ pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionOblig
pub fn process_registered_region_obligations(
&self,
region_bound_pairs_map: &FxHashMap<hir::HirId, RegionBoundPairs<'tcx>>,
implicit_region_bound: Option<ty::Region<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
) {
assert!(
......@@ -170,13 +166,8 @@ pub fn process_registered_region_obligations(
let sup_type = self.resolve_vars_if_possible(sup_type);
if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) {
let outlives = &mut TypeOutlives::new(
self,
self.tcx,
&region_bound_pairs,
implicit_region_bound,
param_env,
);
let outlives =
&mut TypeOutlives::new(self, self.tcx, &region_bound_pairs, None, param_env);
outlives.type_must_outlive(origin, sup_type, sub_region);
} else {
self.tcx.sess.delay_span_bug(
......
......@@ -16,6 +16,11 @@
pub struct VerifyBoundCx<'cx, 'tcx> {
tcx: TyCtxt<'tcx>,
region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
/// During borrowck, if there are no outlives bounds on a generic
/// parameter `T`, we assume that `T: 'in_fn_body` holds.
///
/// Outside of borrowck the only way to prove `T: '?0` is by
/// setting `'?0` to `'empty`.
implicit_region_bound: Option<ty::Region<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
}
......@@ -263,8 +268,8 @@ fn declared_generic_bounds_from_env_for_erased_ty(
// fn foo<'a, A>(x: &'a A) { x.bar() }
//
// The problem is that the type of `x` is `&'a A`. To be
// well-formed, then, A must be lower-generic by `'a`, but we
// don't know that this holds from first principles.
// well-formed, then, A must outlive `'a`, but we don't know that
// this holds from first principles.
let from_region_bound_pairs = self.region_bound_pairs.iter().filter_map(|&(r, p)| {
debug!(
"declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
......
......@@ -863,7 +863,7 @@ pub enum ObjectSafetyViolation {
impl ObjectSafetyViolation {
pub fn error_msg(&self) -> Cow<'static, str> {
match *self {
match self {
ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(),
ObjectSafetyViolation::SupertraitSelf(ref spans) => {
if spans.iter().any(|sp| *sp != DUMMY_SP) {
......@@ -873,7 +873,7 @@ pub fn error_msg(&self) -> Cow<'static, str> {
.into()
}
}
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_, _, _), _) => {
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
format!("associated function `{}` has no `self` parameter", name).into()
}
ObjectSafetyViolation::Method(
......@@ -897,9 +897,11 @@ pub fn error_msg(&self) -> Cow<'static, str> {
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => {
format!("method `{}` has generic type parameters", name).into()
}
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => {
format!("method `{}`'s `self` parameter cannot be dispatched on", name).into()
}
ObjectSafetyViolation::Method(
name,
MethodViolationCode::UndispatchableReceiver(_),
_,
) => format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(),
ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => {
format!("it contains associated `const` `{}`", name).into()
}
......@@ -911,51 +913,40 @@ pub fn error_msg(&self) -> Cow<'static, str> {
}
pub fn solution(&self, err: &mut Diagnostic) {
match *self {
match self {
ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => {}
ObjectSafetyViolation::Method(
name,
MethodViolationCode::StaticMethod(sugg, self_span, has_args),
MethodViolationCode::StaticMethod(Some((add_self_sugg, make_sized_sugg))),
_,
) => {
err.span_suggestion(
self_span,
&format!(
add_self_sugg.1,
format!(
"consider turning `{}` into a method by giving it a `&self` argument",
name
),
format!("&self{}", if has_args { ", " } else { "" }),
add_self_sugg.0.to_string(),
Applicability::MaybeIncorrect,
);
err.span_suggestion(
make_sized_sugg.1,
format!(
"alternatively, consider constraining `{}` so it does not apply to \
trait objects",
name
),
make_sized_sugg.0.to_string(),
Applicability::MaybeIncorrect,
);
match sugg {
Some((sugg, span)) => {
err.span_suggestion(
span,
&format!(
"alternatively, consider constraining `{}` so it does not apply to \
trait objects",
name
),
sugg,
Applicability::MaybeIncorrect,
);
}
None => {
err.help(&format!(
"consider turning `{}` into a method by giving it a `&self` \
argument or constraining it so it does not apply to trait objects",
name
));
}
}
}
ObjectSafetyViolation::Method(
name,
MethodViolationCode::UndispatchableReceiver,
span,
MethodViolationCode::UndispatchableReceiver(Some(span)),
_,
) => {
err.span_suggestion(
span,
*span,
&format!(
"consider changing method `{}`'s `self` parameter to be `&self`",
name
......@@ -991,13 +982,13 @@ trait objects",
}
/// Reasons a method might not be object-safe.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
pub enum MethodViolationCode {
/// e.g., `fn foo()`
StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */),
StaticMethod(Option<(/* add &self */ (String, Span), /* add Self: Sized */ (String, Span))>),
/// e.g., `fn foo(&self, x: Self)`
ReferencesSelfInput(usize),
ReferencesSelfInput(Option<Span>),
/// e.g., `fn foo(&self) -> Self`
ReferencesSelfOutput,
......@@ -1009,7 +1000,7 @@ pub enum MethodViolationCode {
Generic,
/// the method's receiver (`self` argument) can't be dispatched on
UndispatchableReceiver,
UndispatchableReceiver(Option<Span>),
}
/// These are the error cases for `codegen_fulfill_obligation`.
......
......@@ -465,13 +465,12 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn fold_regions<T>(
self,
value: T,
skipped_regions: &mut bool,
mut f: impl FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> T
where
T: TypeFoldable<'tcx>,
{
value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f))
value.fold_with(&mut RegionFolder::new(self, &mut f))
}
/// Invoke `callback` on every region appearing free in `value`.
......@@ -579,7 +578,6 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
pub struct RegionFolder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
skipped_regions: &'a mut bool,
/// Stores the index of a binder *just outside* the stuff we have
/// visited. So this begins as INNERMOST; when we pass through a
......@@ -597,10 +595,9 @@ impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
#[inline]
pub fn new(
tcx: TyCtxt<'tcx>,
skipped_regions: &'a mut bool,
fold_region_fn: &'a mut dyn FnMut(ty::Region<'tcx>, ty::DebruijnIndex) -> ty::Region<'tcx>,
) -> RegionFolder<'a, 'tcx> {
RegionFolder { tcx, skipped_regions, current_index: ty::INNERMOST, fold_region_fn }
RegionFolder { tcx, current_index: ty::INNERMOST, fold_region_fn }
}
}
......@@ -624,7 +621,6 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
ty::ReLateBound(debruijn, _) if debruijn < self.current_index => {
debug!(?self.current_index, "skipped bound region");
*self.skipped_regions = true;
r
}
_ => {
......
......@@ -220,7 +220,7 @@ pub fn find_auto_trait_generics<A>(
.map(|&(id, _)| (id, vec![]))
.collect();
infcx.process_registered_region_obligations(&body_id_map, None, full_env);
infcx.process_registered_region_obligations(&body_id_map, full_env);
let region_data = infcx
.inner
......
......@@ -407,11 +407,7 @@ fn resolve_negative_obligation<'cx, 'tcx>(
// function bodies with closures).
outlives_env.save_implied_bounds(CRATE_HIR_ID);
infcx.process_registered_region_obligations(
outlives_env.region_bound_pairs_map(),
Some(tcx.lifetimes.re_root_empty),
param_env,
);
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs_map(), param_env);
let errors = infcx.resolve_regions(region_context, &outlives_env);
......
......@@ -366,15 +366,9 @@ fn object_safety_violation_for_method(
// Get an accurate span depending on the violation.
violation.map(|v| {
let node = tcx.hir().get_if_local(method.def_id);
let span = match (v, node) {
(MethodViolationCode::ReferencesSelfInput(arg), Some(node)) => node
.fn_decl()
.and_then(|decl| decl.inputs.get(arg + 1))
.map_or(method.ident(tcx).span, |arg| arg.span),
(MethodViolationCode::UndispatchableReceiver, Some(node)) => node
.fn_decl()
.and_then(|decl| decl.inputs.get(0))
.map_or(method.ident(tcx).span, |arg| arg.span),
let span = match (&v, node) {
(MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span,
(MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span,
(MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
node.fn_decl().map_or(method.ident(tcx).span, |decl| decl.output.span())
}
......@@ -397,32 +391,41 @@ fn virtual_call_violation_for_method<'tcx>(
// The method's first parameter must be named `self`
if !method.fn_has_self_parameter {
// We'll attempt to provide a structured suggestion for `Self: Sized`.
let sugg =
tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
|generics| match generics.predicates {
[] => (" where Self: Sized", generics.where_clause_span),
[.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
},
);
// Get the span pointing at where the `self` receiver should be.
let sm = tcx.sess.source_map();
let self_span = method.ident(tcx).span.to(tcx
.hir()
.span_if_local(method.def_id)
.unwrap_or_else(|| sm.next_point(method.ident(tcx).span))
.shrink_to_hi());
let self_span = sm.span_through_char(self_span, '(').shrink_to_hi();
return Some(MethodViolationCode::StaticMethod(
sugg,
self_span,
!sig.inputs().skip_binder().is_empty(),
));
let sugg = if let Some(hir::Node::TraitItem(hir::TraitItem {
generics,
kind: hir::TraitItemKind::Fn(sig, _),
..
})) = tcx.hir().get_if_local(method.def_id).as_ref()
{
let sm = tcx.sess.source_map();
Some((
(
format!("&self{}", if sig.decl.inputs.is_empty() { "" } else { ", " }),
sm.span_through_char(sig.span, '(').shrink_to_hi(),
),
(
format!("{} Self: Sized", generics.add_where_or_trailing_comma()),
generics.tail_span_for_predicate_suggestion(),
),
))
} else {
None
};
return Some(MethodViolationCode::StaticMethod(sugg));
}
for (i, &input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
for (i, &input_ty) in sig.skip_binder().inputs().iter().enumerate().skip(1) {
if contains_illegal_self_type_reference(tcx, trait_def_id, sig.rebind(input_ty)) {
return Some(MethodViolationCode::ReferencesSelfInput(i));
let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, _),
..
})) = tcx.hir().get_if_local(method.def_id).as_ref()
{
Some(sig.decl.inputs[i].span)
} else {
None
};
return Some(MethodViolationCode::ReferencesSelfInput(span));
}
}
if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) {
......@@ -456,7 +459,16 @@ fn virtual_call_violation_for_method<'tcx>(
// `Receiver: Unsize<Receiver[Self => dyn Trait]>`.
if receiver_ty != tcx.types.self_param {
if !receiver_is_dispatchable(tcx, method, receiver_ty) {
return Some(MethodViolationCode::UndispatchableReceiver);
let span = if let Some(hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(sig, _),
..
})) = tcx.hir().get_if_local(method.def_id).as_ref()
{
Some(sig.decl.inputs[0].span)
} else {
None
};
return Some(MethodViolationCode::UndispatchableReceiver(span));
} else {
// Do sanity check to make sure the receiver actually has the layout of a pointer.
......
......@@ -225,7 +225,7 @@ pub fn resolve_interior<'a, 'tcx>(
// Note that each region slot in the types gets a new fresh late bound region,
// which means that none of the regions inside relate to any other, even if
// typeck had previously found constraints that would cause them to be related.
let folded = fcx.tcx.fold_regions(erased, &mut false, |_, current_depth| {
let folded = fcx.tcx.fold_regions(erased, |_, current_depth| {
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(counter),
kind: ty::BrAnon(counter),
......
......@@ -366,7 +366,6 @@ fn visit_region_obligations(&mut self, hir_id: hir::HirId) {
fn resolve_regions_and_report_errors(&self) {
self.infcx.process_registered_region_obligations(
self.outlives_environment.region_bound_pairs_map(),
Some(self.tcx.lifetimes.re_root_empty),
self.param_env,
);
......
......@@ -596,13 +596,7 @@ fn ty_known_to_outlive<'tcx>(
) -> bool {
resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| {
let origin = infer::RelateParamBound(DUMMY_SP, ty, None);
let outlives = &mut TypeOutlives::new(
infcx,
tcx,
region_bound_pairs,
Some(infcx.tcx.lifetimes.re_root_empty),
param_env,
);
let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env);
outlives.type_must_outlive(origin, ty, region);
})
}
......
......@@ -393,7 +393,7 @@ fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
}
fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match *r {
let ty = self.tcx.fold_regions(ty, |r, _| match *r {
ty::ReErased => self.tcx.lifetimes.re_static,
_ => r,
});
......@@ -1917,7 +1917,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
Some(ty) => {
let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
// Typeck doesn't expect erased regions to be returned from `type_of`.
let fn_sig = tcx.fold_regions(fn_sig, &mut false, |r, _| match *r {
let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
ty::ReErased => tcx.lifetimes.re_static,
_ => r,
});
......
......@@ -772,7 +772,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
}
// Typeck doesn't expect erased regions to be returned from `type_of`.
tcx.fold_regions(ty, &mut false, |r, _| match *r {
tcx.fold_regions(ty, |r, _| match *r {
ty::ReErased => tcx.lifetimes.re_static,
_ => r,
})
......
......@@ -207,7 +207,7 @@ fn test_format_macro_interface() {
{
let val = usize::MAX;
let exp = format!("{val:#x}");
t!(format!("{:p}", val as *const isize), exp);
t!(format!("{:p}", std::ptr::invalid::<isize>(val)), exp);
}
// Escaping
......
use core::alloc::Layout;
use core::ptr::NonNull;
use core::ptr::{self, NonNull};
#[test]
fn const_unchecked_layout() {
......@@ -9,7 +9,7 @@ fn const_unchecked_layout() {
const DANGLING: NonNull<u8> = LAYOUT.dangling();
assert_eq!(LAYOUT.size(), SIZE);
assert_eq!(LAYOUT.align(), ALIGN);
assert_eq!(Some(DANGLING), NonNull::new(ALIGN as *mut u8));
assert_eq!(Some(DANGLING), NonNull::new(ptr::invalid_mut(ALIGN)));
}
#[test]
......
......@@ -2,6 +2,7 @@
use std::default::Default;
use std::hash::{BuildHasher, Hash, Hasher};
use std::ptr;
use std::rc::Rc;
struct MyHasher {
......@@ -69,10 +70,10 @@ fn hash<T: Hash>(t: &T) -> u64 {
let cs: Rc<[u8]> = Rc::new([1, 2, 3]);
assert_eq!(hash(&cs), 9);
let ptr = 5_usize as *const i32;
let ptr = ptr::invalid::<i32>(5_usize);
assert_eq!(hash(&ptr), 5);
let ptr = 5_usize as *mut i32;
let ptr = ptr::invalid_mut::<i32>(5_usize);
assert_eq!(hash(&ptr), 5);
if cfg!(miri) {
......
......@@ -353,9 +353,9 @@ fn align_offset_zst() {
// all, because no amount of elements will align the pointer.
let mut p = 1;
while p < 1024 {
assert_eq!((p as *const ()).align_offset(p), 0);
assert_eq!(ptr::invalid::<()>(p).align_offset(p), 0);
if p != 1 {
assert_eq!(((p + 1) as *const ()).align_offset(p), !0);
assert_eq!(ptr::invalid::<()>(p + 1).align_offset(p), !0);
}
p = (p + 1).next_power_of_two();
}
......@@ -371,7 +371,7 @@ fn align_offset_stride1() {
let expected = ptr % align;
let offset = if expected == 0 { 0 } else { align - expected };
assert_eq!(
(ptr as *const u8).align_offset(align),
ptr::invalid::<u8>(ptr).align_offset(align),
offset,
"ptr = {}, align = {}, size = 1",
ptr,
......@@ -434,14 +434,14 @@ unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool {
while align < limit {
for ptr in 1usize..4 * align {
unsafe {
x |= test_weird_stride::<A3>(ptr as *const A3, align);
x |= test_weird_stride::<A4>(ptr as *const A4, align);
x |= test_weird_stride::<A5>(ptr as *const A5, align);
x |= test_weird_stride::<A6>(ptr as *const A6, align);
x |= test_weird_stride::<A7>(ptr as *const A7, align);
x |= test_weird_stride::<A8>(ptr as *const A8, align);
x |= test_weird_stride::<A9>(ptr as *const A9, align);
x |= test_weird_stride::<A10>(ptr as *const A10, align);
x |= test_weird_stride::<A3>(ptr::invalid::<A3>(ptr), align);
x |= test_weird_stride::<A4>(ptr::invalid::<A4>(ptr), align);
x |= test_weird_stride::<A5>(ptr::invalid::<A5>(ptr), align);
x |= test_weird_stride::<A6>(ptr::invalid::<A6>(ptr), align);
x |= test_weird_stride::<A7>(ptr::invalid::<A7>(ptr), align);
x |= test_weird_stride::<A8>(ptr::invalid::<A8>(ptr), align);
x |= test_weird_stride::<A9>(ptr::invalid::<A9>(ptr), align);
x |= test_weird_stride::<A10>(ptr::invalid::<A10>(ptr), align);
}
}
align = (align + 1).next_power_of_two();
......@@ -479,8 +479,8 @@ fn ptr_metadata() {
let () = metadata(&[4, 7]);
let () = metadata(&(4, String::new()));
let () = metadata(&Pair(4, String::new()));
let () = metadata(0 as *const Extern);
let () = metadata(0 as *const <&u32 as std::ops::Deref>::Target);
let () = metadata(ptr::null::<()>() as *const Extern);
let () = metadata(ptr::null::<()>() as *const <&u32 as std::ops::Deref>::Target);
assert_eq!(metadata("foo"), 3_usize);
assert_eq!(metadata(&[4, 7][..]), 2_usize);
......
......@@ -3,7 +3,7 @@
#[test]
fn test_waker_getters() {
let raw_waker = RawWaker::new(42usize as *mut (), &WAKER_VTABLE);
let raw_waker = RawWaker::new(ptr::invalid_mut(42usize), &WAKER_VTABLE);
assert_eq!(raw_waker.data() as usize, 42);
assert!(ptr::eq(raw_waker.vtable(), &WAKER_VTABLE));
......@@ -15,7 +15,7 @@ fn test_waker_getters() {
}
static WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
|data| RawWaker::new((data as usize + 1) as *mut (), &WAKER_VTABLE),
|data| RawWaker::new(ptr::invalid_mut(data as usize + 1), &WAKER_VTABLE),
|_| {},
|_| {},
|_| {},
......
......@@ -6,6 +6,7 @@
use std::str::FromStr;
use rustc_data_structures::fx::FxHashMap;
use rustc_driver::print_flag_list;
use rustc_session::config::{
self, parse_crate_types_from_list, parse_externs, parse_target_triple, CrateType,
};
......@@ -310,11 +311,15 @@ pub(crate) fn should_emit_crate(&self) -> bool {
impl Options {
/// Parses the given command-line for options. If an error message or other early-return has
/// been printed, returns `Err` with the exit code.
pub(crate) fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> {
pub(crate) fn from_matches(
matches: &getopts::Matches,
args: Vec<String>,
) -> Result<Options, i32> {
let args = &args[1..];
// Check for unstable options.
nightly_options::check_nightly_options(matches, &opts());
if matches.opt_present("h") || matches.opt_present("help") {
if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") {
crate::usage("rustdoc");
return Err(0);
} else if matches.opt_present("version") {
......@@ -335,6 +340,21 @@ pub(crate) fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> {
// check for deprecated options
check_deprecated_options(matches, &diag);
let z_flags = matches.opt_strs("Z");
if z_flags.iter().any(|x| *x == "help") {
print_flag_list("-Z", config::DB_OPTIONS);
return Err(0);
}
let c_flags = matches.opt_strs("C");
if c_flags.iter().any(|x| *x == "help") {
print_flag_list("-C", config::CG_OPTIONS);
return Err(0);
}
let w_flags = matches.opt_strs("W");
if w_flags.iter().any(|x| *x == "help") {
print_flag_list("-W", config::DB_OPTIONS);
return Err(0);
}
if matches.opt_strs("passes") == ["list"] {
println!("Available passes for running rustdoc:");
for pass in passes::PASSES {
......
......@@ -252,8 +252,11 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
default: None,
},
// FIXME: do not map to Typedef but to a custom variant
AssocTypeItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)),
AssocTypeItem(t, b) => ItemEnum::AssocType {
generics: t.generics.into_tcx(tcx),
bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
default: t.item_type.map(|ty| ty.into_tcx(tcx)),
},
// `convert_item` early returns `None` for striped items and keywords.
StrippedItem(_) | KeywordItem(_) => unreachable!(),
ExternCrateItem { ref src } => ItemEnum::ExternCrate {
......
......@@ -686,7 +686,7 @@ fn main_args(at_args: &[String]) -> MainResult {
// Note that we discard any distinction between different non-zero exit
// codes from `from_matches` here.
let options = match config::Options::from_matches(&matches) {
let options = match config::Options::from_matches(&matches, args) {
Ok(opts) => opts,
Err(code) => {
return if code == 0 {
......
-include ../../run-make-fulldeps/tools.mk
all:
$(BARE_RUSTDOC) 2>&1 | sed -E 's@/nightly/|/beta/|/stable/|/1\.[0-9]+\.[0-9]+/@/$$CHANNEL/@g' | diff - output-default.stdout
This is a test to verify that the default behavior of `rustdoc` is printing out help output instead of erroring out (#88756).
rustdoc [options] <input>
Options:
-h, --help show this help message
-V, --version print rustdoc's version
-v, --verbose use verbose output
-w, --output-format [html]
the output type to write
--output PATH Which directory to place the output. This option is
deprecated, use --out-dir instead.
-o, --out-dir PATH which directory to place the output
--crate-name NAME
specify the name of this crate
--crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]
Comma separated list of types of crates
for the compiler to emit
-L, --library-path DIR
directory to add to crate search path
--cfg pass a --cfg to rustc
--check-cfg pass a --check-cfg to rustc
--extern NAME[=PATH]
pass an --extern to rustc
--extern-html-root-url NAME=URL
base URL to use for dependencies; for example,
"std=/doc" links std::vec::Vec to
/doc/std/vec/struct.Vec.html
--extern-html-root-takes-precedence
give precedence to `--extern-html-root-url`, not
`html_root_url`
-C, --codegen OPT[=VALUE]
pass a codegen option to rustc
--document-private-items
document private items
--document-hidden-items
document items that have doc(hidden)
--test run code examples as tests
--test-args ARGS
arguments to pass to the test runner
--test-run-directory PATH
The working directory in which to run tests
--target TRIPLE target triple to document
--markdown-css FILES
CSS files to include via <link> in a rendered Markdown
file
--html-in-header FILES
files to include inline in the <head> section of a
rendered Markdown file or generated documentation
--html-before-content FILES
files to include inline between <body> and the content
of a rendered Markdown file or generated documentation
--html-after-content FILES
files to include inline between the content and
</body> of a rendered Markdown file or generated
documentation
--markdown-before-content FILES
files to include inline between <body> and the content
of a rendered Markdown file or generated documentation
--markdown-after-content FILES
files to include inline between the content and
</body> of a rendered Markdown file or generated
documentation
--markdown-playground-url URL
URL to send code snippets to
--markdown-no-toc
don't include table of contents
-e, --extend-css PATH
To add some CSS rules with a given file to generate
doc with your own theme. However, your theme might
break if the rustdoc's generated HTML changes, so be
careful!
-Z FLAG internal and debugging options (only on nightly build)
--sysroot PATH Override the system root
--playground-url URL
URL to send code snippets to, may be reset by
--markdown-playground-url or
`#![doc(html_playground_url=...)]`
--display-doctest-warnings
show warnings that originate in doctests
--crate-version VERSION
crate version to print into documentation
--sort-modules-by-appearance
sort modules by where they appear in the program,
rather than alphabetically
--default-theme THEME
Set the default theme. THEME should be the theme name,
generally lowercase. If an unknown default theme is
specified, the builtin default is used. The set of
themes, and the rustdoc built-in default, are not
stable.
--default-setting SETTING[=VALUE]
Default value for a rustdoc setting (used when
"rustdoc-SETTING" is absent from web browser Local
Storage). If VALUE is not supplied, "true" is used.
Supported SETTINGs and VALUEs are not documented and
not stable.
--theme FILES additional themes which will be added to the generated
docs
--check-theme FILES
check if given theme is valid
--resource-suffix PATH
suffix to add to CSS and JavaScript files, e.g.,
"light.css" will become "light-suffix.css"
--edition EDITION
edition to use when compiling rust code (default:
2015)
--color auto|always|never
Configure coloring of output:
auto = colorize, if output goes to a tty (default);
always = always colorize output;
never = never colorize output
--error-format human|json|short
How errors and other messages are produced
--json CONFIG Configure the structure of JSON diagnostics
--disable-minification
Disable minification applied on JS files
-A, --allow LINT Set lint allowed
-W, --warn LINT Set lint warnings
--force-warn LINT
Set lint force-warn
-D, --deny LINT Set lint denied
-F, --forbid LINT Set lint forbidden
--cap-lints LEVEL
Set the most restrictive lint level. More restrictive
lints are capped at this level. By default, it is at
`forbid` level.
--index-page PATH
Markdown file to be used as index page
--enable-index-page
To enable generation of the index page
--static-root-path PATH
Path string to force loading static files from in
output pages. If not set, uses combinations of '../'
to reach the documentation root.
--disable-per-crate-search
disables generating the crate selector on the search
box
--persist-doctests PATH
Directory to persist doctest executables into
--show-coverage
calculate percentage of public items with
documentation
--enable-per-target-ignores
parse ignore-foo for ignoring doctests on a per-target
basis
--runtool The tool to run tests with when building for a different target than host
--runtool-arg One (of possibly many) arguments to pass to the runtool
--test-builder PATH
The rustc-like binary to use as the test builder
--check Run rustdoc checks
--generate-redirect-map
Generate JSON file at the top level instead of
generating HTML redirection files
--emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific]
Comma separated list of types of output for rustdoc to
emit
--no-run Compile doctests without running them
--show-type-layout
Include the memory layout of types in the docs
--nocapture Don't capture stdout and stderr of tests
--generate-link-to-definition
Make the identifiers in the HTML source code pages
navigable
--scrape-examples-output-path collect function call information and output at the given path
--scrape-examples-target-crate collect function call information for functions from the target crate
--scrape-tests Include test code when scraping examples
--with-examples path to function call information (for displaying examples in the documentation)
--plugin-path DIR
removed, see issue #44136
<https://github.com/rust-lang/rust/issues/44136> for
more information
--passes PASSES removed, see issue #44136
<https://github.com/rust-lang/rust/issues/44136> for
more information
--plugins PLUGINS
removed, see issue #44136
<https://github.com/rust-lang/rust/issues/44136> for
more information
--no-defaults removed, see issue #44136
<https://github.com/rust-lang/rust/issues/44136> for
more information
-r, --input-format [rust]
removed, see issue #44136
<https://github.com/rust-lang/rust/issues/44136> for
more information
@path Read newline separated options from `path`
More information available at https://doc.rust-lang.org/$CHANNEL/rustdoc/what-is-rustdoc.html
-include ../../run-make-fulldeps/tools.mk
all:
$(RUSTDOC) -W help 2>&1 | diff - output-default.stdout
This is a test to verify that `rustdoc` behaves the same as rustc and prints out help output for its options like -W (#88756).
#![no_std]
// @has assoc_items.json
pub struct Simple;
impl Simple {
// @has - "$.index[*][?(@.name=='CONSTANT')].kind" \"assoc_const\"
pub const CONSTANT: usize = 0;
}
pub trait EasyToImpl {
// @has - "$.index[*][?(@.name=='ToDeclare')].kind" \"assoc_type\"
// @has - "$.index[*][?(@.name=='ToDeclare')].inner.default" null
type ToDeclare;
// @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].kind" \"assoc_const\"
// @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" null
const AN_ATTRIBUTE: usize;
}
impl EasyToImpl for Simple {
// @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.kind" \"primitive\"
// @has - "$.index[*][?(@.name=='ToDeclare')].inner.default.inner" \"usize\"
type ToDeclare = usize;
// @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.kind" \"primitive\"
// @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.type.inner" \"usize\"
// @has - "$.index[*][?(@.name=='AN_ATTRIBUTE')].inner.default" \"12\"
const AN_ATTRIBUTE: usize = 12;
}
use std::sync::Arc;
pub trait A {
fn f();
fn f2(self: &Arc<Self>);
}
// aux-build:not-object-safe.rs
extern crate not_object_safe;
pub trait B where
Self: not_object_safe::A,
{
fn f2(&self);
}
struct S(Box<dyn B>);
//~^ ERROR the trait `B` cannot be made into an object
fn main() {}
error[E0038]: the trait `B` cannot be made into an object
--> $DIR/issue-98500.rs:11:14
|
LL | struct S(Box<dyn B>);
| ^^^^^ `B` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/auxiliary/not-object-safe.rs:4:8
|
LL | fn f();
| ^ ...because associated function `f` has no `self` parameter
LL | fn f2(self: &Arc<Self>);
| ^^ ...because method `f2`'s `self` parameter cannot be dispatched on
|
::: $DIR/issue-98500.rs:5:11
|
LL | pub trait B where
| - this trait cannot be made into an object...
= help: consider moving `f` to another trait
= help: consider moving `f2` to another trait
error: aborting due to previous error
For more information about this error, try `rustc --explain E0038`.
......@@ -2,7 +2,7 @@
#![allow(unused_variables, dead_code)]
trait Trait {
fn foo(&self) where Self: Other, Self: Sized, { }
fn foo(&self) where Self: Other, Self: Sized { }
fn bar(self: &Self) {} //~ ERROR invalid `self` parameter type
}
......
......@@ -28,8 +28,8 @@ LL | fn foo(&self) where Self: Other, { }
| +++++
help: alternatively, consider constraining `foo` so it does not apply to trait objects
|
LL | fn foo() where Self: Other, Self: Sized, { }
| +++++++++++++
LL | fn foo() where Self: Other, Self: Sized { }
| ~~~~~~~~~~~~~
help: consider changing method `bar`'s `self` parameter to be `&self`
|
LL | fn bar(self: &Self) {}
......
......@@ -30,7 +30,7 @@ except ImportError:
# These should be collaborators of the rust-lang/rust repository (with at least
# read privileges on it). CI will fail otherwise.
MAINTAINERS = {
'miri': {'oli-obk', 'RalfJung', 'eddyb'},
'miri': {'oli-obk', 'RalfJung'},
'rls': {'Xanewok'},
'rustfmt': {'topecongiro', 'calebcartwright'},
'book': {'carols10cents', 'steveklabnik'},
......
......@@ -215,3 +215,108 @@ changelog-path = "RELEASES.md"
changelog-branch = "master"
[shortcut]
[mentions."compiler/rustc_apfloat"]
message = """
Changes rustc_apfloat. rustc_apfloat is currently in limbo and you almost
certainly don't want to change it (see #55993).
"""
cc = ["@eddyb"]
[mentions."compiler/rustc_codegen_cranelift"]
cc = ["@bjorn3"]
[mentions."compiler/rustc_codegen_gcc"]
cc = ["@antoyo"]
[mentions."compiler/rustc_const_eval/src/interpret"]
message = "Some changes occurred to the CTFE / Miri engine"
cc = ["@rust-lang/miri"]
[mentions."compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs"]
message = "Some changes occurred in need_type_info.rs"
cc = ["@lcnr"]
[mentions."compiler/rustc_middle/src/mir/interpret"]
message = "Some changes occurred to the CTFE / Miri engine"
cc = ["@rust-lang/miri"]
[mentions."compiler/rustc_mir_transform/src/"]
message = "Some changes occurred to MIR optimizations"
cc = ["@rust-lang/mir-opt"]
[mentions."compiler/rustc_trait_selection/src/traits/const_evaluatable.rs"]
message = "Some changes occurred in const_evaluatable.rs"
cc = ["@lcnr"]
[mentions."compiler/rustc_error_codes/src/error_codes.rs"]
message = "Some changes occurred in diagnostic error codes"
cc = ["@GuillaumeGomez"]
[mentions."library"]
message = """
Hey! It looks like you've submitted a new PR for the library teams!
If this PR contains changes to any `rust-lang/rust` public library APIs then
please comment with `@rustbot label +T-libs-api -T-libs` to tag it
appropriately. If this PR contains changes to any unstable APIs please edit
the PR description to add a link to the relevant [API Change
Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html)
or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29)
if you haven't already. If you're unsure where your change falls no worries,
just leave it as is and the reviewer will take a look and make a decision to
forward on if necessary.
Examples of `T-libs-api` changes:
* Stabilizing library features
* Introducing insta-stable changes such as new implementations of existing
stable traits on existing stable types
* Introducing new or changing existing unstable library APIs (excluding
permanently unstable features / features without a tracking issue)
* Changing public documentation in ways that create new stability guarantees
* Changing observable runtime behavior of library APIs
"""
[mentions."src/librustdoc/clean/types.rs"]
cc = ["@camelid"]
[mentions."src/librustdoc/html/static"]
message = "Some changes occurred in HTML/CSS/JS."
cc = [
"@GuillaumeGomez",
"@Folyd",
"@jsha",
]
[mentions."src/librustdoc/html/static/css/themes"]
message = "Some changes occurred in HTML/CSS themes."
cc = ["@GuillaumeGomez"]
[mentions."src/librustdoc/html/static/css/themes/ayu.css"]
message = "A change occurred in the Ayu theme."
cc = ["@Cldfire"]
[mentions."src/rustdoc-json-types"]
message = """
rustdoc-json-types is a **public** (although nightly-only) API.
If possible, consider changing `src/librustdoc/json/conversions.rs`;
otherwise, make sure you bump the `FORMAT_VERSION` constant.
"""
cc = [
"@CraftSpider",
"@aDotInTheVoid",
]
[mentions."src/tools/cargo"]
cc = ["@ehuss"]
[mentions."src/tools/clippy"]
cc = ["@rust-lang/clippy"]
[mentions."src/tools/miri"]
cc = ["@rust-lang/miri"]
[mentions."src/tools/rustfmt"]
cc = ["@rust-lang/rustfmt"]
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册