1
Fork 0

Auto merge of #108096 - matthiaskrgr:rollup-ncexzf6, r=matthiaskrgr

Rollup of 10 pull requests

Successful merges:

 - #107034 (Migrating rustc_infer to session diagnostics (part 4))
 - #107972 (Fix unintentional UB in ui tests)
 - #108010 (Make `InferCtxt::can_eq` and `InferCtxt::can_sub` return booleans)
 - #108021 (make x look for x.py if shell script does not exist)
 - #108047 (Use `target` instead of `machine` for mir interpreter integer handling.)
 - #108049 (Don't suggest `#[doc(hidden)]` trait methods with matching return type)
 - #108066 (Better names for illegal impl trait positions)
 - #108076 (rustdoc: Use more let chain)
 - #108088 (clarify correctness of `black_box`)
 - #108094 (Demonstrate I/O in File examples)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-02-16 00:12:54 +00:00
commit dc7a676778
109 changed files with 1126 additions and 784 deletions

View file

@ -139,13 +139,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::Cast(expr, ty) => { ExprKind::Cast(expr, ty) => {
let expr = self.lower_expr(expr); let expr = self.lower_expr(expr);
let ty = let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast));
hir::ExprKind::Cast(expr, ty) hir::ExprKind::Cast(expr, ty)
} }
ExprKind::Type(expr, ty) => { ExprKind::Type(expr, ty) => {
let expr = self.lower_expr(expr); let expr = self.lower_expr(expr);
let ty = let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast));
hir::ExprKind::Type(expr, ty) hir::ExprKind::Type(expr, ty)
} }
ExprKind::AddrOf(k, m, ohs) => { ExprKind::AddrOf(k, m, ohs) => {

View file

@ -378,8 +378,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
) )
}); });
let lowered_ty = this let lowered_ty = this.lower_ty(
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); ty,
&ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
);
(trait_ref, lowered_ty) (trait_ref, lowered_ty)
}); });
@ -458,7 +460,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span, span: Span,
body: Option<&Expr>, body: Option<&Expr>,
) -> (&'hir hir::Ty<'hir>, hir::BodyId) { ) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
(ty, self.lower_const_body(span, body)) (ty, self.lower_const_body(span, body))
} }
@ -608,8 +610,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) hir::ForeignItemKind::Fn(fn_dec, fn_args, generics)
} }
ForeignItemKind::Static(t, m, _) => { ForeignItemKind::Static(t, m, _) => {
let ty = let ty = self
self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); .lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy));
hir::ForeignItemKind::Static(ty, *m) hir::ForeignItemKind::Static(ty, *m)
} }
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
@ -679,11 +681,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
qself, qself,
path, path,
ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124)
&ImplTraitContext::Disallowed(ImplTraitPosition::Path), &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy),
); );
self.arena.alloc(t) self.arena.alloc(t)
} else { } else {
self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy))
}; };
let hir_id = self.lower_node_id(f.id); let hir_id = self.lower_node_id(f.id);
self.lower_attrs(hir_id, &f.attrs); self.lower_attrs(hir_id, &f.attrs);
@ -708,7 +710,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind, has_default) = match &i.kind { let (generics, kind, has_default) = match &i.kind {
AssocItemKind::Const(_, ty, default) => { AssocItemKind::Const(_, ty, default) => {
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
} }
@ -746,7 +749,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic), &ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|this| { |this| {
let ty = ty.as_ref().map(|x| { let ty = ty.as_ref().map(|x| {
this.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) this.lower_ty(
x,
&ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy),
)
}); });
hir::TraitItemKind::Type( hir::TraitItemKind::Type(
this.lower_param_bounds( this.lower_param_bounds(
@ -805,7 +811,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (generics, kind) = match &i.kind { let (generics, kind) = match &i.kind {
AssocItemKind::Const(_, ty, expr) => { AssocItemKind::Const(_, ty, expr) => {
let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let ty =
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
( (
hir::Generics::empty(), hir::Generics::empty(),
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
@ -1441,7 +1448,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir_id: self.next_id(), hir_id: self.next_id(),
bound_generic_params: self.lower_generic_params(bound_generic_params), bound_generic_params: self.lower_generic_params(bound_generic_params),
bounded_ty: self bounded_ty: self
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| { bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
self.lower_param_bound( self.lower_param_bound(
bound, bound,
@ -1465,9 +1472,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => { WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
lhs_ty: self lhs_ty: self
.lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
rhs_ty: self rhs_ty: self
.lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
span: self.lower_span(*span), span: self.lower_span(*span),
}) })
} }

View file

@ -253,7 +253,6 @@ enum ImplTraitContext {
enum ImplTraitPosition { enum ImplTraitPosition {
Path, Path,
Variable, Variable,
Type,
Trait, Trait,
AsyncBlock, AsyncBlock,
Bound, Bound,
@ -270,6 +269,13 @@ enum ImplTraitPosition {
FnTraitReturn, FnTraitReturn,
TraitReturn, TraitReturn,
ImplReturn, ImplReturn,
GenericDefault,
ConstTy,
StaticTy,
AssocTy,
FieldTy,
Cast,
ImplSelf,
} }
impl std::fmt::Display for ImplTraitPosition { impl std::fmt::Display for ImplTraitPosition {
@ -277,7 +283,6 @@ impl std::fmt::Display for ImplTraitPosition {
let name = match self { let name = match self {
ImplTraitPosition::Path => "path", ImplTraitPosition::Path => "path",
ImplTraitPosition::Variable => "variable binding", ImplTraitPosition::Variable => "variable binding",
ImplTraitPosition::Type => "type",
ImplTraitPosition::Trait => "trait", ImplTraitPosition::Trait => "trait",
ImplTraitPosition::AsyncBlock => "async block", ImplTraitPosition::AsyncBlock => "async block",
ImplTraitPosition::Bound => "bound", ImplTraitPosition::Bound => "bound",
@ -294,6 +299,13 @@ impl std::fmt::Display for ImplTraitPosition {
ImplTraitPosition::FnTraitReturn => "`Fn` trait return", ImplTraitPosition::FnTraitReturn => "`Fn` trait return",
ImplTraitPosition::TraitReturn => "trait method return", ImplTraitPosition::TraitReturn => "trait method return",
ImplTraitPosition::ImplReturn => "`impl` method return", ImplTraitPosition::ImplReturn => "`impl` method return",
ImplTraitPosition::GenericDefault => "generic parameter default",
ImplTraitPosition::ConstTy => "const type",
ImplTraitPosition::StaticTy => "static type",
ImplTraitPosition::AssocTy => "associated type",
ImplTraitPosition::FieldTy => "field type",
ImplTraitPosition::Cast => "cast type",
ImplTraitPosition::ImplSelf => "impl header",
}; };
write!(f, "{name}") write!(f, "{name}")
@ -2166,7 +2178,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
GenericParamKind::Type { default, .. } => { GenericParamKind::Type { default, .. } => {
let kind = hir::GenericParamKind::Type { let kind = hir::GenericParamKind::Type {
default: default.as_ref().map(|x| { default: default.as_ref().map(|x| {
self.lower_ty(x, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)) self.lower_ty(
x,
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
)
}), }),
synthetic: false, synthetic: false,
}; };
@ -2174,7 +2189,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
(hir::ParamName::Plain(self.lower_ident(param.ident)), kind) (hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
} }
GenericParamKind::Const { ty, kw_span: _, default } => { GenericParamKind::Const { ty, kw_span: _, default } => {
let ty = self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)); let ty = self.lower_ty(
&ty,
&ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
);
let default = default.as_ref().map(|def| self.lower_anon_const(def)); let default = default.as_ref().map(|def| self.lower_anon_const(def));
( (
hir::ParamName::Plain(self.lower_ident(param.ident)), hir::ParamName::Plain(self.lower_ident(param.ident)),

View file

@ -1144,7 +1144,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
LateBoundRegionConversionTime::FnCall, LateBoundRegionConversionTime::FnCall,
tcx.fn_sig(method_did).subst(tcx, method_substs).input(0), tcx.fn_sig(method_did).subst(tcx, method_substs).input(0),
) )
&& infcx.can_eq(self.param_env, ty, self_ty).is_ok() && infcx.can_eq(self.param_env, ty, self_ty)
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(
fn_call_span.shrink_to_lo(), fn_call_span.shrink_to_lo(),

View file

@ -186,7 +186,7 @@ pub(super) fn op_to_const<'tcx>(
0, 0,
), ),
}; };
let len = b.to_machine_usize(ecx).unwrap(); let len = b.to_target_usize(ecx).unwrap();
let start = start.try_into().unwrap(); let start = start.try_into().unwrap();
let len: usize = len.try_into().unwrap(); let len: usize = len.try_into().unwrap();
ConstValue::Slice { data, start, end: start + len } ConstValue::Slice { data, start, end: start + len }

View file

@ -244,7 +244,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
let ptr = self.read_pointer(&args[0])?; let ptr = self.read_pointer(&args[0])?;
let target_align = self.read_scalar(&args[1])?.to_machine_usize(self)?; let target_align = self.read_scalar(&args[1])?.to_target_usize(self)?;
if !target_align.is_power_of_two() { if !target_align.is_power_of_two() {
throw_ub_format!("`align_offset` called with non-power-of-two align: {}", target_align); throw_ub_format!("`align_offset` called with non-power-of-two align: {}", target_align);
@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
Ok(ControlFlow::Break(())) Ok(ControlFlow::Break(()))
} else { } else {
// Not alignable in const, return `usize::MAX`. // Not alignable in const, return `usize::MAX`.
let usize_max = Scalar::from_machine_usize(self.machine_usize_max(), self); let usize_max = Scalar::from_target_usize(self.target_usize_max(), self);
self.write_scalar(usize_max, dest)?; self.write_scalar(usize_max, dest)?;
self.return_to_block(ret)?; self.return_to_block(ret)?;
Ok(ControlFlow::Break(())) Ok(ControlFlow::Break(()))
@ -470,8 +470,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
ecx.write_scalar(Scalar::from_u8(cmp), dest)?; ecx.write_scalar(Scalar::from_u8(cmp), dest)?;
} }
sym::const_allocate => { sym::const_allocate => {
let size = ecx.read_scalar(&args[0])?.to_machine_usize(ecx)?; let size = ecx.read_scalar(&args[0])?.to_target_usize(ecx)?;
let align = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?; let align = ecx.read_scalar(&args[1])?.to_target_usize(ecx)?;
let align = match Align::from_bytes(align) { let align = match Align::from_bytes(align) {
Ok(a) => a, Ok(a) => a,
@ -487,8 +487,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
} }
sym::const_deallocate => { sym::const_deallocate => {
let ptr = ecx.read_pointer(&args[0])?; let ptr = ecx.read_pointer(&args[0])?;
let size = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?; let size = ecx.read_scalar(&args[1])?.to_target_usize(ecx)?;
let align = ecx.read_scalar(&args[2])?.to_machine_usize(ecx)?; let align = ecx.read_scalar(&args[2])?.to_target_usize(ecx)?;
let size = Size::from_bytes(size); let size = Size::from_bytes(size);
let align = match Align::from_bytes(align) { let align = match Align::from_bytes(align) {

View file

@ -155,7 +155,7 @@ pub(crate) fn deref_mir_constant<'tcx>(
// In case of unsized types, figure out the real type behind. // In case of unsized types, figure out the real type behind.
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() { MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
ty::Str => bug!("there's no sized equivalent of a `str`"), ty::Str => bug!("there's no sized equivalent of a `str`"),
ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_machine_usize(&tcx).unwrap()), ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_target_usize(&tcx).unwrap()),
_ => bug!( _ => bug!(
"type {} should not have metadata, but had {:?}", "type {} should not have metadata, but had {:?}",
mplace.layout.ty, mplace.layout.ty,

View file

@ -239,7 +239,7 @@ fn create_pointee_place<'tcx>(
MPlaceTy::from_aligned_ptr_with_meta( MPlaceTy::from_aligned_ptr_with_meta(
ptr.into(), ptr.into(),
layout, layout,
MemPlaceMeta::Meta(Scalar::from_machine_usize(num_elems as u64, &tcx)), MemPlaceMeta::Meta(Scalar::from_target_usize(num_elems as u64, &tcx)),
) )
} else { } else {
create_mplace_from_layout(ecx, ty) create_mplace_from_layout(ecx, ty)
@ -355,7 +355,7 @@ fn valtree_into_mplace<'tcx>(
let imm = match inner_ty.kind() { let imm = match inner_ty.kind() {
ty::Slice(_) | ty::Str => { ty::Slice(_) | ty::Str => {
let len = valtree.unwrap_branch().len(); let len = valtree.unwrap_branch().len();
let len_scalar = Scalar::from_machine_usize(len as u64, &tcx); let len_scalar = Scalar::from_target_usize(len as u64, &tcx);
Immediate::ScalarPair( Immediate::ScalarPair(
Scalar::from_maybe_pointer((*pointee_place).ptr, &tcx), Scalar::from_maybe_pointer((*pointee_place).ptr, &tcx),
@ -426,7 +426,7 @@ fn valtree_into_mplace<'tcx>(
place place
.offset_with_meta( .offset_with_meta(
offset, offset,
MemPlaceMeta::Meta(Scalar::from_machine_usize( MemPlaceMeta::Meta(Scalar::from_target_usize(
num_elems as u64, num_elems as u64,
&tcx, &tcx,
)), )),

View file

@ -231,7 +231,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// First cast to usize. // First cast to usize.
let scalar = src.to_scalar(); let scalar = src.to_scalar();
let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?; let addr = self.cast_from_int_like(scalar, src.layout, self.tcx.types.usize)?;
let addr = addr.to_machine_usize(self)?; let addr = addr.to_target_usize(self)?;
// Then turn address into pointer. // Then turn address into pointer.
let ptr = M::ptr_from_addr_cast(&self, addr)?; let ptr = M::ptr_from_addr_cast(&self, addr)?;

View file

@ -639,7 +639,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
ty::Slice(_) | ty::Str => { ty::Slice(_) | ty::Str => {
let len = metadata.unwrap_meta().to_machine_usize(self)?; let len = metadata.unwrap_meta().to_target_usize(self)?;
let elem = layout.field(self, 0); let elem = layout.field(self, 0);
// Make sure the slice is not too big. // Make sure the slice is not too big.

View file

@ -71,7 +71,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
sym::pref_align_of => { sym::pref_align_of => {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?; let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
ConstValue::from_machine_usize(layout.align.pref.bytes(), &tcx) ConstValue::from_target_usize(layout.align.pref.bytes(), &tcx)
} }
sym::type_id => { sym::type_id => {
ensure_monomorphic_enough(tcx, tp_ty)?; ensure_monomorphic_enough(tcx, tp_ty)?;
@ -79,7 +79,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
} }
sym::variant_count => match tp_ty.kind() { sym::variant_count => match tp_ty.kind() {
// Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
ty::Adt(adt, _) => ConstValue::from_machine_usize(adt.variants().len() as u64, &tcx), ty::Adt(adt, _) => ConstValue::from_target_usize(adt.variants().len() as u64, &tcx),
ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => { ty::Alias(..) | ty::Param(_) | ty::Placeholder(_) | ty::Infer(_) => {
throw_inval!(TooGeneric) throw_inval!(TooGeneric)
} }
@ -104,7 +104,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
| ty::GeneratorWitnessMIR(_, _) | ty::GeneratorWitnessMIR(_, _)
| ty::Never | ty::Never
| ty::Tuple(_) | ty::Tuple(_)
| ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx), | ty::Error(_) => ConstValue::from_target_usize(0u64, &tcx),
}, },
other => bug!("`{}` is not a zero arg intrinsic", other), other => bug!("`{}` is not a zero arg intrinsic", other),
}) })
@ -156,7 +156,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
_ => bug!(), _ => bug!(),
}; };
self.write_scalar(Scalar::from_machine_usize(result, self), dest)?; self.write_scalar(Scalar::from_target_usize(result, self), dest)?;
} }
sym::pref_align_of sym::pref_align_of
@ -302,7 +302,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
sym::offset => { sym::offset => {
let ptr = self.read_pointer(&args[0])?; let ptr = self.read_pointer(&args[0])?;
let offset_count = self.read_machine_isize(&args[1])?; let offset_count = self.read_target_isize(&args[1])?;
let pointee_ty = substs.type_at(0); let pointee_ty = substs.type_at(0);
let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?; let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
@ -310,7 +310,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
} }
sym::arith_offset => { sym::arith_offset => {
let ptr = self.read_pointer(&args[0])?; let ptr = self.read_pointer(&args[0])?;
let offset_count = self.read_machine_isize(&args[1])?; let offset_count = self.read_target_isize(&args[1])?;
let pointee_ty = substs.type_at(0); let pointee_ty = substs.type_at(0);
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap(); let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
@ -376,7 +376,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// The signed form of the intrinsic allows this. If we interpret the // The signed form of the intrinsic allows this. If we interpret the
// difference as isize, we'll get the proper signed difference. If that // difference as isize, we'll get the proper signed difference. If that
// seems *positive*, they were more than isize::MAX apart. // seems *positive*, they were more than isize::MAX apart.
let dist = val.to_machine_isize(self)?; let dist = val.to_target_isize(self)?;
if dist >= 0 { if dist >= 0 {
throw_ub_format!( throw_ub_format!(
"`{}` called when first pointer is too far before second", "`{}` called when first pointer is too far before second",
@ -386,7 +386,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
dist dist
} else { } else {
// b >= a // b >= a
let dist = val.to_machine_isize(self)?; let dist = val.to_target_isize(self)?;
// If converting to isize produced a *negative* result, we had an overflow // If converting to isize produced a *negative* result, we had an overflow
// because they were more than isize::MAX apart. // because they were more than isize::MAX apart.
if dist < 0 { if dist < 0 {
@ -411,10 +411,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Perform division by size to compute return value. // Perform division by size to compute return value.
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned { let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
assert!(0 <= dist && dist <= self.machine_isize_max()); assert!(0 <= dist && dist <= self.target_isize_max());
usize_layout usize_layout
} else { } else {
assert!(self.machine_isize_min() <= dist && dist <= self.machine_isize_max()); assert!(self.target_isize_min() <= dist && dist <= self.target_isize_max());
isize_layout isize_layout
}; };
let pointee_layout = self.layout_of(substs.type_at(0))?; let pointee_layout = self.layout_of(substs.type_at(0))?;
@ -531,12 +531,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
sym::vtable_size => { sym::vtable_size => {
let ptr = self.read_pointer(&args[0])?; let ptr = self.read_pointer(&args[0])?;
let (size, _align) = self.get_vtable_size_and_align(ptr)?; let (size, _align) = self.get_vtable_size_and_align(ptr)?;
self.write_scalar(Scalar::from_machine_usize(size.bytes(), self), dest)?; self.write_scalar(Scalar::from_target_usize(size.bytes(), self), dest)?;
} }
sym::vtable_align => { sym::vtable_align => {
let ptr = self.read_pointer(&args[0])?; let ptr = self.read_pointer(&args[0])?;
let (_size, align) = self.get_vtable_size_and_align(ptr)?; let (_size, align) = self.get_vtable_size_and_align(ptr)?;
self.write_scalar(Scalar::from_machine_usize(align.bytes(), self), dest)?; self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
} }
_ => return Ok(false), _ => return Ok(false),
@ -675,10 +675,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>, count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
nonoverlapping: bool, nonoverlapping: bool,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let count = self.read_machine_usize(&count)?; let count = self.read_target_usize(&count)?;
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?; let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
let (size, align) = (layout.size, layout.align.abi); let (size, align) = (layout.size, layout.align.abi);
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max), // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable. // but no actual allocation can be big enough for the difference to be noticeable.
let size = size.checked_mul(count, self).ok_or_else(|| { let size = size.checked_mul(count, self).ok_or_else(|| {
err_ub_format!( err_ub_format!(
@ -703,9 +703,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let dst = self.read_pointer(&dst)?; let dst = self.read_pointer(&dst)?;
let byte = self.read_scalar(&byte)?.to_u8()?; let byte = self.read_scalar(&byte)?.to_u8()?;
let count = self.read_machine_usize(&count)?; let count = self.read_target_usize(&count)?;
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max), // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable. // but no actual allocation can be big enough for the difference to be noticeable.
let len = layout let len = layout
.size .size

View file

@ -425,7 +425,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
throw_ub!(PointerOutOfBounds { throw_ub!(PointerOutOfBounds {
alloc_id, alloc_id,
alloc_size, alloc_size,
ptr_offset: self.machine_usize_to_isize(offset.bytes()), ptr_offset: self.target_usize_to_isize(offset.bytes()),
ptr_size: size, ptr_size: size,
msg, msg,
}) })

View file

@ -52,7 +52,7 @@ impl<Prov: Provenance> Immediate<Prov> {
} }
pub fn new_slice(val: Scalar<Prov>, len: u64, cx: &impl HasDataLayout) -> Self { pub fn new_slice(val: Scalar<Prov>, len: u64, cx: &impl HasDataLayout) -> Self {
Immediate::ScalarPair(val, Scalar::from_machine_usize(len, cx)) Immediate::ScalarPair(val, Scalar::from_target_usize(len, cx))
} }
pub fn new_dyn_trait( pub fn new_dyn_trait(
@ -414,12 +414,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.read_scalar(op)?.to_pointer(self) self.read_scalar(op)?.to_pointer(self)
} }
/// Read a pointer-sized unsigned integer from a place. /// Read a pointer-sized unsigned integer from a place.
pub fn read_machine_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> { pub fn read_target_usize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, u64> {
self.read_scalar(op)?.to_machine_usize(self) self.read_scalar(op)?.to_target_usize(self)
} }
/// Read a pointer-sized signed integer from a place. /// Read a pointer-sized signed integer from a place.
pub fn read_machine_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> { pub fn read_target_isize(&self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx, i64> {
self.read_scalar(op)?.to_machine_isize(self) self.read_scalar(op)?.to_target_isize(self)
} }
/// Turn the wide MPlace into a string (must already be dereferenced!) /// Turn the wide MPlace into a string (must already be dereferenced!)

View file

@ -229,7 +229,7 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
if self.layout.is_unsized() { if self.layout.is_unsized() {
// We need to consult `meta` metadata // We need to consult `meta` metadata
match self.layout.ty.kind() { match self.layout.ty.kind() {
ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_machine_usize(cx), ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_target_usize(cx),
_ => bug!("len not supported on unsized type {:?}", self.layout.ty), _ => bug!("len not supported on unsized type {:?}", self.layout.ty),
} }
} else { } else {
@ -756,7 +756,7 @@ where
mutbl: Mutability, mutbl: Mutability,
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl)?; let ptr = self.allocate_bytes_ptr(str.as_bytes(), Align::ONE, kind, mutbl)?;
let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self); let meta = Scalar::from_target_usize(u64::try_from(str.len()).unwrap(), self);
let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) }; let mplace = MemPlace { ptr: ptr.into(), meta: MemPlaceMeta::Meta(meta) };
let ty = self.tcx.mk_ref( let ty = self.tcx.mk_ref(

View file

@ -319,7 +319,7 @@ where
// implement this. // implement this.
ty::Array(inner, _) => (MemPlaceMeta::None, self.tcx.mk_array(*inner, inner_len)), ty::Array(inner, _) => (MemPlaceMeta::None, self.tcx.mk_array(*inner, inner_len)),
ty::Slice(..) => { ty::Slice(..) => {
let len = Scalar::from_machine_usize(inner_len, self); let len = Scalar::from_target_usize(inner_len, self);
(MemPlaceMeta::Meta(len), base.layout.ty) (MemPlaceMeta::Meta(len), base.layout.ty)
} }
_ => { _ => {
@ -363,7 +363,7 @@ where
Index(local) => { Index(local) => {
let layout = self.layout_of(self.tcx.types.usize)?; let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.local_to_op(self.frame(), local, Some(layout))?; let n = self.local_to_op(self.frame(), local, Some(layout))?;
let n = self.read_machine_usize(&n)?; let n = self.read_target_usize(&n)?;
self.place_index(base, n)? self.place_index(base, n)?
} }
ConstantIndex { offset, min_length, from_end } => { ConstantIndex { offset, min_length, from_end } => {
@ -392,7 +392,7 @@ where
Index(local) => { Index(local) => {
let layout = self.layout_of(self.tcx.types.usize)?; let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.local_to_op(self.frame(), local, Some(layout))?; let n = self.local_to_op(self.frame(), local, Some(layout))?;
let n = self.read_machine_usize(&n)?; let n = self.read_target_usize(&n)?;
self.operand_index(base, n)? self.operand_index(base, n)?
} }
ConstantIndex { offset, min_length, from_end } => { ConstantIndex { offset, min_length, from_end } => {

View file

@ -242,7 +242,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let src = self.eval_place(place)?; let src = self.eval_place(place)?;
let op = self.place_to_op(&src)?; let op = self.place_to_op(&src)?;
let len = op.len(self)?; let len = op.len(self)?;
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?; self.write_scalar(Scalar::from_target_usize(len, self), &dest)?;
} }
Ref(_, borrow_kind, place) => { Ref(_, borrow_kind, place) => {
@ -297,7 +297,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(),
}; };
self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?; self.write_scalar(Scalar::from_target_usize(val, self), &dest)?;
} }
ShallowInitBox(ref operand, _) => { ShallowInitBox(ref operand, _) => {

View file

@ -348,7 +348,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// FIXME: check if the type/trait match what ty::Dynamic says? // FIXME: check if the type/trait match what ty::Dynamic says?
} }
ty::Slice(..) | ty::Str => { ty::Slice(..) | ty::Str => {
let _len = meta.unwrap_meta().to_machine_usize(self.ecx)?; let _len = meta.unwrap_meta().to_target_usize(self.ecx)?;
// We do not check that `len * elem_size <= isize::MAX`: // We do not check that `len * elem_size <= isize::MAX`:
// that is only required for references, and there it falls out of the // that is only required for references, and there it falls out of the
// "dereferenceable" check performed by Stacked Borrows. // "dereferenceable" check performed by Stacked Borrows.

View file

@ -140,6 +140,18 @@ infer_lifetime_param_suggestion_elided = each elided lifetime in input position
infer_region_explanation = {$pref_kind -> infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$pref_kind}] *[should_not_happen] [{$pref_kind}]
[ref_valid_for] ...the reference is valid for
[content_valid_for] ...but the borrowed content is only valid for
[type_obj_valid_for] object type is valid for
[source_pointer_valid_for] source pointer is only valid for
[type_satisfy] type must satisfy
[type_outlive] type must outlive
[lf_param_instantiated_with] lifetime parameter instantiated with
[lf_param_must_outlive] but lifetime parameter must outlive
[lf_instantiated_with] lifetime instantiated with
[lf_must_outlive] but lifetime must outlive
[pointer_valid_for] the pointer is valid for
[data_valid_for] but the referenced data is only valid for
[empty] {""} [empty] {""}
}{$pref_kind -> }{$pref_kind ->
[empty] {""} [empty] {""}
@ -148,7 +160,6 @@ infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$desc_kind}] *[should_not_happen] [{$desc_kind}]
[restatic] the static lifetime [restatic] the static lifetime
[revar] lifetime {$desc_arg} [revar] lifetime {$desc_arg}
[as_defined] the lifetime `{$desc_arg}` as defined here [as_defined] the lifetime `{$desc_arg}` as defined here
[as_defined_anon] the anonymous lifetime as defined here [as_defined_anon] the anonymous lifetime as defined here
[defined_here] the anonymous lifetime defined here [defined_here] the anonymous lifetime defined here
@ -158,8 +169,16 @@ infer_region_explanation = {$pref_kind ->
*[should_not_happen] [{$suff_kind}] *[should_not_happen] [{$suff_kind}]
[empty]{""} [empty]{""}
[continues] ... [continues] ...
[req_by_binding] {" "}as required by this binding
} }
infer_outlives_content = lifetime of reference outlives lifetime of borrowed content...
infer_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type
infer_fullfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
infer_lf_bound_not_satisfied = lifetime bound not satisfied
infer_borrowed_too_long = a value of type `{$ty}` is borrowed for too long
infer_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references
infer_mismatched_static_lifetime = incompatible lifetime on type infer_mismatched_static_lifetime = incompatible lifetime on type
infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl` infer_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement infer_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement
@ -308,3 +327,21 @@ infer_ril_introduced_here = `'static` requirement introduced here
infer_ril_introduced_by = requirement introduced by this return type infer_ril_introduced_by = requirement introduced by this return type
infer_ril_because_of = because of this returned expression infer_ril_because_of = because of this returned expression
infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
infer_where_remove = remove the `where` clause
infer_where_copy_predicates = copy the `where` clause predicates from the trait
infer_srs_remove_and_box = consider removing this semicolon and boxing the expressions
infer_srs_remove = consider removing this semicolon
infer_srs_add = consider returning the local binding `{$ident}`
infer_srs_add_one = consider returning one of these bindings
infer_await_both_futures = consider `await`ing on both `Future`s
infer_await_future = consider `await`ing on the `Future`
infer_await_note = calling an async function returns a future
infer_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here...
infer_prlf_defined_without_sub = the lifetime defined here...
infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)

View file

@ -2232,7 +2232,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.erase_regions(impl_.self_ty()), tcx.erase_regions(impl_.self_ty()),
tcx.erase_regions(qself_ty), tcx.erase_regions(qself_ty),
) )
.is_ok()
}) })
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
}) })

View file

@ -1106,7 +1106,7 @@ fn compare_self_type<'tcx>(
let infcx = tcx.infer_ctxt().build(); let infcx = tcx.infer_ctxt().build();
let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty).is_ok(); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
match ExplicitSelf::determine(self_arg_ty, can_eq_self) { match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
ExplicitSelf::ByValue => "self".to_owned(), ExplicitSelf::ByValue => "self".to_owned(),
ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),

View file

@ -1716,7 +1716,7 @@ fn receiver_is_valid<'tcx>(
let cause = let cause =
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver); ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty).is_ok(); let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty);
// `self: Self` is always valid. // `self: Self` is always valid.
if can_eq_self(receiver_ty) { if can_eq_self(receiver_ty) {

View file

@ -321,7 +321,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut param_args = FxHashMap::default(); let mut param_args = FxHashMap::default();
let mut param_expected = FxHashMap::default(); let mut param_expected = FxHashMap::default();
let mut param_found = FxHashMap::default(); let mut param_found = FxHashMap::default();
if self.can_eq(self.param_env, ty, found).is_ok() { if self.can_eq(self.param_env, ty, found) {
// We only point at the first place where the found type was inferred. // We only point at the first place where the found type was inferred.
for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() { for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() {
if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() { if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() {
@ -369,7 +369,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (param, (arg, arg_ty)) in param_args.iter() { for (param, (arg, arg_ty)) in param_args.iter() {
let Some(expected) = param_expected.get(param) else { continue; }; let Some(expected) = param_expected.get(param) else { continue; };
let Some(found) = param_found.get(param) else { continue; }; let Some(found) = param_found.get(param) else { continue; };
if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; } if !self.can_eq(self.param_env, *arg_ty, *found) { continue; }
self.emit_coerce_suggestions(err, arg, *found, *expected, None, None); self.emit_coerce_suggestions(err, arg, *found, *expected, None, None);
} }
@ -379,7 +379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
if ty != prev if ty != prev
&& param_args.is_empty() && param_args.is_empty()
&& self.can_eq(self.param_env, ty, found).is_ok() && self.can_eq(self.param_env, ty, found)
{ {
// We only point at the first place where the found type was inferred. // We only point at the first place where the found type was inferred.
if !segment.ident.span.overlaps(mismatch_span) { if !segment.ident.span.overlaps(mismatch_span) {
@ -401,7 +401,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} }
if ty != prev if ty != prev
&& let Some(span) = prev_span && let Some(span) = prev_span
&& self.can_eq(self.param_env, ty, found).is_ok() && self.can_eq(self.param_env, ty, found)
{ {
// We only point at the first place where the found type was inferred. // We only point at the first place where the found type was inferred.
// We use the *previous* span because if the type is known *here* it means // We use the *previous* span because if the type is known *here* it means
@ -764,7 +764,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::Adt(expected_adt, substs) = expected.kind() { if let ty::Adt(expected_adt, substs) = expected.kind() {
if let hir::ExprKind::Field(base, ident) = expr.kind { if let hir::ExprKind::Field(base, ident) = expr.kind {
let base_ty = self.typeck_results.borrow().expr_ty(base); let base_ty = self.typeck_results.borrow().expr_ty(base);
if self.can_eq(self.param_env, base_ty, expected).is_ok() if self.can_eq(self.param_env, base_ty, expected)
&& let Some(base_span) = base.span.find_ancestor_inside(expr.span) && let Some(base_span) = base.span.find_ancestor_inside(expr.span)
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(
@ -1357,7 +1357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr), hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
_, _,
&ty::Ref(_, checked, _), &ty::Ref(_, checked, _),
) if self.can_sub(self.param_env, checked, expected).is_ok() => { ) if self.can_sub(self.param_env, checked, expected) => {
// We have `&T`, check if what was expected was `T`. If so, // We have `&T`, check if what was expected was `T`. If so,
// we may want to suggest removing a `&`. // we may want to suggest removing a `&`.
if sm.is_imported(expr.span) { if sm.is_imported(expr.span) {
@ -2003,7 +2003,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}; };
let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; }; let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; };
let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; }; let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; };
if self.can_eq(self.param_env, expected_ty, ty).is_ok() { if self.can_eq(self.param_env, expected_ty, ty) {
err.span_suggestion_short( err.span_suggestion_short(
stmt.span.with_lo(tail_expr.span.hi()), stmt.span.with_lo(tail_expr.span.hi()),
"remove this semicolon", "remove this semicolon",

View file

@ -1015,7 +1015,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expr_inner_ty = substs.type_at(0); let expr_inner_ty = substs.type_at(0);
let expected_inner_ty = expected_substs.type_at(0); let expected_inner_ty = expected_substs.type_at(0);
if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind() if let ty::Ref(_, ty, hir::Mutability::Not) = expr_inner_ty.kind()
&& self.can_eq(self.param_env, *ty, expected_inner_ty).is_ok() && self.can_eq(self.param_env, *ty, expected_inner_ty)
{ {
let def_path = self.tcx.def_path_str(adt_def.did()); let def_path = self.tcx.def_path_str(adt_def.did());
if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) { if self.type_is_copy_modulo_regions(self.param_env, *ty, expr.span) {
@ -1054,7 +1054,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result) if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result)
&& adt_def.did() == result_did && adt_def.did() == result_did
// Check that the error types are equal // Check that the error types are equal
&& self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1)).is_ok() && self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1))
{ {
return suggest_copied_or_cloned(); return suggest_copied_or_cloned();
} else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option) } else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)

View file

@ -936,7 +936,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
return false; return false;
} }
} }
self.can_sub(self.param_env, fty.output(), expected).is_ok() self.can_sub(self.param_env, fty.output(), expected)
}), }),
_ => false, _ => false,
} }

View file

@ -90,7 +90,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?; self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
if let Some(expr) = ti.origin_expr { if let Some(expr) = ti.origin_expr {
self.suggest_fn_call(&mut diag, expr, expected, |output| { self.suggest_fn_call(&mut diag, expr, expected, |output| {
self.can_eq(self.param_env, output, actual).is_ok() self.can_eq(self.param_env, output, actual)
}); });
} }
Some(diag) Some(diag)
@ -675,7 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) { ) {
match (expected.kind(), actual.kind(), ba) { match (expected.kind(), actual.kind(), ba) {
(ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::NONE) (ty::Ref(_, inner_ty, _), _, hir::BindingAnnotation::NONE)
if self.can_eq(self.param_env, *inner_ty, actual).is_ok() => if self.can_eq(self.param_env, *inner_ty, actual) =>
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(
span.shrink_to_lo(), span.shrink_to_lo(),
@ -685,7 +685,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
); );
} }
(_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::REF) (_, ty::Ref(_, inner_ty, _), hir::BindingAnnotation::REF)
if self.can_eq(self.param_env, expected, *inner_ty).is_ok() => if self.can_eq(self.param_env, expected, *inner_ty) =>
{ {
err.span_suggestion_verbose( err.span_suggestion_verbose(
span.with_hi(span.lo() + BytePos(4)), span.with_hi(span.lo() + BytePos(4)),

View file

@ -933,3 +933,216 @@ pub struct ButNeedsToSatisfy {
pub has_lifetime: bool, pub has_lifetime: bool,
pub lifetime: String, pub lifetime: String,
} }
#[derive(Diagnostic)]
#[diag(infer_outlives_content, code = "E0312")]
pub struct OutlivesContent<'a> {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Diagnostic)]
#[diag(infer_outlives_bound, code = "E0476")]
pub struct OutlivesBound<'a> {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Diagnostic)]
#[diag(infer_fullfill_req_lifetime, code = "E0477")]
pub struct FullfillReqLifetime<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
#[subdiagnostic]
pub note: Option<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Diagnostic)]
#[diag(infer_lf_bound_not_satisfied, code = "E0478")]
pub struct LfBoundNotSatisfied<'a> {
#[primary_span]
pub span: Span,
#[subdiagnostic]
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Diagnostic)]
#[diag(infer_ref_longer_than_data, code = "E0491")]
pub struct RefLongerThanData<'a> {
#[primary_span]
pub span: Span,
pub ty: Ty<'a>,
#[subdiagnostic]
pub notes: Vec<note_and_explain::RegionExplanation<'a>>,
}
#[derive(Subdiagnostic)]
pub enum WhereClauseSuggestions {
#[suggestion(
infer_where_remove,
code = "",
applicability = "machine-applicable",
style = "verbose"
)]
Remove {
#[primary_span]
span: Span,
},
#[suggestion(
infer_where_copy_predicates,
code = "{space}where {trait_predicates}",
applicability = "machine-applicable",
style = "verbose"
)]
CopyPredicates {
#[primary_span]
span: Span,
space: &'static str,
trait_predicates: String,
},
}
#[derive(Subdiagnostic)]
pub enum SuggestRemoveSemiOrReturnBinding {
#[multipart_suggestion(infer_srs_remove_and_box, applicability = "machine-applicable")]
RemoveAndBox {
#[suggestion_part(code = "Box::new(")]
first_lo: Span,
#[suggestion_part(code = ")")]
first_hi: Span,
#[suggestion_part(code = "Box::new(")]
second_lo: Span,
#[suggestion_part(code = ")")]
second_hi: Span,
#[suggestion_part(code = "")]
sp: Span,
},
#[suggestion(
infer_srs_remove,
style = "short",
code = "",
applicability = "machine-applicable"
)]
Remove {
#[primary_span]
sp: Span,
},
#[suggestion(
infer_srs_add,
style = "verbose",
code = "{code}",
applicability = "maybe-incorrect"
)]
Add {
#[primary_span]
sp: Span,
code: String,
ident: Ident,
},
#[note(infer_srs_add_one)]
AddOne {
#[primary_span]
spans: MultiSpan,
},
}
#[derive(Subdiagnostic)]
pub enum ConsiderAddingAwait {
#[help(infer_await_both_futures)]
BothFuturesHelp,
#[multipart_suggestion(infer_await_both_futures, applicability = "maybe-incorrect")]
BothFuturesSugg {
#[suggestion_part(code = ".await")]
first: Span,
#[suggestion_part(code = ".await")]
second: Span,
},
#[suggestion(
infer_await_future,
code = ".await",
style = "verbose",
applicability = "maybe-incorrect"
)]
FutureSugg {
#[primary_span]
span: Span,
},
#[note(infer_await_note)]
FutureSuggNote {
#[primary_span]
span: Span,
},
#[multipart_suggestion(
infer_await_future,
style = "verbose",
applicability = "maybe-incorrect"
)]
FutureSuggMultiple {
#[suggestion_part(code = ".await")]
spans: Vec<Span>,
},
}
#[derive(Diagnostic)]
pub enum PlaceholderRelationLfNotSatisfied {
#[diag(infer_lf_bound_not_satisfied)]
HasBoth {
#[primary_span]
span: Span,
#[note(infer_prlf_defined_with_sub)]
sub_span: Span,
#[note(infer_prlf_must_oultive_with_sup)]
sup_span: Span,
sub_symbol: Symbol,
sup_symbol: Symbol,
#[note(infer_prlf_known_limitation)]
note: (),
},
#[diag(infer_lf_bound_not_satisfied)]
HasSub {
#[primary_span]
span: Span,
#[note(infer_prlf_defined_with_sub)]
sub_span: Span,
#[note(infer_prlf_must_oultive_without_sup)]
sup_span: Span,
sub_symbol: Symbol,
#[note(infer_prlf_known_limitation)]
note: (),
},
#[diag(infer_lf_bound_not_satisfied)]
HasSup {
#[primary_span]
span: Span,
#[note(infer_prlf_defined_without_sub)]
sub_span: Span,
#[note(infer_prlf_must_oultive_with_sup)]
sup_span: Span,
sup_symbol: Symbol,
#[note(infer_prlf_known_limitation)]
note: (),
},
#[diag(infer_lf_bound_not_satisfied)]
HasNone {
#[primary_span]
span: Span,
#[note(infer_prlf_defined_without_sub)]
sub_span: Span,
#[note(infer_prlf_must_oultive_without_sup)]
sup_span: Span,
#[note(infer_prlf_known_limitation)]
note: (),
},
#[diag(infer_lf_bound_not_satisfied)]
OnlyPrimarySpan {
#[primary_span]
span: Span,
#[note(infer_prlf_known_limitation)]
note: (),
},
}

View file

@ -121,16 +121,42 @@ impl<'a> DescriptionCtx<'a> {
pub enum PrefixKind { pub enum PrefixKind {
Empty, Empty,
RefValidFor,
ContentValidFor,
TypeObjValidFor,
SourcePointerValidFor,
TypeSatisfy,
TypeOutlive,
LfParamInstantiatedWith,
LfParamMustOutlive,
LfInstantiatedWith,
LfMustOutlive,
PointerValidFor,
DataValidFor,
} }
pub enum SuffixKind { pub enum SuffixKind {
Empty,
Continues, Continues,
ReqByBinding,
} }
impl IntoDiagnosticArg for PrefixKind { impl IntoDiagnosticArg for PrefixKind {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
let kind = match self { let kind = match self {
Self::Empty => "empty", Self::Empty => "empty",
Self::RefValidFor => "ref_valid_for",
Self::ContentValidFor => "content_valid_for",
Self::TypeObjValidFor => "type_obj_valid_for",
Self::SourcePointerValidFor => "source_pointer_valid_for",
Self::TypeSatisfy => "type_satisfy",
Self::TypeOutlive => "type_outlive",
Self::LfParamInstantiatedWith => "lf_param_instantiated_with",
Self::LfParamMustOutlive => "lf_param_must_outlive",
Self::LfInstantiatedWith => "lf_instantiated_with",
Self::LfMustOutlive => "lf_must_outlive",
Self::PointerValidFor => "pointer_valid_for",
Self::DataValidFor => "data_valid_for",
} }
.into(); .into();
rustc_errors::DiagnosticArgValue::Str(kind) rustc_errors::DiagnosticArgValue::Str(kind)
@ -140,7 +166,9 @@ impl IntoDiagnosticArg for PrefixKind {
impl IntoDiagnosticArg for SuffixKind { impl IntoDiagnosticArg for SuffixKind {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
let kind = match self { let kind = match self {
Self::Empty => "empty",
Self::Continues => "continues", Self::Continues => "continues",
Self::ReqByBinding => "req_by_binding",
} }
.into(); .into();
rustc_errors::DiagnosticArgValue::Str(kind) rustc_errors::DiagnosticArgValue::Str(kind)
@ -166,17 +194,19 @@ impl RegionExplanation<'_> {
} }
impl AddToDiagnostic for RegionExplanation<'_> { impl AddToDiagnostic for RegionExplanation<'_> {
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
where where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{ {
if let Some(span) = self.desc.span {
diag.span_note(span, fluent::infer_region_explanation);
} else {
diag.note(fluent::infer_region_explanation);
}
self.desc.add_to(diag);
diag.set_arg("pref_kind", self.prefix); diag.set_arg("pref_kind", self.prefix);
diag.set_arg("suff_kind", self.suffix); diag.set_arg("suff_kind", self.suffix);
let desc_span = self.desc.span;
self.desc.add_to(diag);
let msg = f(diag, fluent::infer_region_explanation.into());
if let Some(span) = desc_span {
diag.span_note(span, msg);
} else {
diag.note(msg);
}
} }
} }

View file

@ -751,15 +751,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}; };
let msg = "`match` arms have incompatible types"; let msg = "`match` arms have incompatible types";
err.span_label(outer, msg); err.span_label(outer, msg);
self.suggest_remove_semi_or_return_binding( if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
err,
prior_arm_block_id, prior_arm_block_id,
prior_arm_ty, prior_arm_ty,
prior_arm_span, prior_arm_span,
arm_block_id, arm_block_id,
arm_ty, arm_ty,
arm_span, arm_span,
); ) {
err.subdiagnostic(subdiag);
}
if let Some(ret_sp) = opt_suggest_box_span { if let Some(ret_sp) = opt_suggest_box_span {
// Get return type span and point to it. // Get return type span and point to it.
self.suggest_boxing_for_return_impl_trait( self.suggest_boxing_for_return_impl_trait(
@ -784,15 +785,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
if let Some(sp) = outer_span { if let Some(sp) = outer_span {
err.span_label(sp, "`if` and `else` have incompatible types"); err.span_label(sp, "`if` and `else` have incompatible types");
} }
self.suggest_remove_semi_or_return_binding( if let Some(subdiag) = self.suggest_remove_semi_or_return_binding(
err,
Some(then_id), Some(then_id),
then_ty, then_ty,
then_span, then_span,
Some(else_id), Some(else_id),
else_ty, else_ty,
else_span, else_span,
); ) {
err.subdiagnostic(subdiag);
}
if let Some(ret_sp) = opt_suggest_box_span { if let Some(ret_sp) = opt_suggest_box_span {
self.suggest_boxing_for_return_impl_trait( self.suggest_boxing_for_return_impl_trait(
err, err,

View file

@ -1,5 +1,8 @@
use crate::infer::{ use crate::{
error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin, errors::PlaceholderRelationLfNotSatisfied,
infer::{
error_reporting::nice_region_error::NiceRegionError, RegionResolutionError, SubregionOrigin,
},
}; };
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
@ -16,8 +19,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)), Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)),
Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)), Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)),
)) => { )) => {
let msg = "lifetime bound not satisfied"; let span = *span;
let mut err = self.tcx().sess.struct_span_err(*span, msg);
let (sub_span, sub_symbol) = match sub_name { let (sub_span, sub_symbol) = match sub_name {
ty::BrNamed(def_id, symbol) => { ty::BrNamed(def_id, symbol) => {
(Some(self.tcx().def_span(def_id)), Some(symbol)) (Some(self.tcx().def_span(def_id)), Some(symbol))
@ -32,41 +34,47 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
ty::BrAnon(_, span) => (*span, None), ty::BrAnon(_, span) => (*span, None),
ty::BrEnv => (None, None), ty::BrEnv => (None, None),
}; };
match (sub_span, sup_span, sub_symbol, sup_symbol) { let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
(Some(sub_span), Some(sup_span), Some(sub_symbol), Some(sup_symbol)) => { (Some(sub_span), Some(sup_span), Some(&sub_symbol), Some(&sup_symbol)) => {
err.span_note( PlaceholderRelationLfNotSatisfied::HasBoth {
span,
sub_span, sub_span,
format!("the lifetime `{sub_symbol}` defined here..."),
);
err.span_note(
sup_span, sup_span,
format!("...must outlive the lifetime `{sup_symbol}` defined here"), sub_symbol,
); sup_symbol,
note: (),
}
} }
(Some(sub_span), Some(sup_span), _, Some(sup_symbol)) => { (Some(sub_span), Some(sup_span), _, Some(&sup_symbol)) => {
err.span_note(sub_span, "the lifetime defined here..."); PlaceholderRelationLfNotSatisfied::HasSup {
err.span_note( span,
sup_span,
format!("...must outlive the lifetime `{sup_symbol}` defined here"),
);
}
(Some(sub_span), Some(sup_span), Some(sub_symbol), _) => {
err.span_note(
sub_span, sub_span,
format!("the lifetime `{sub_symbol}` defined here..."), sup_span,
); sup_symbol,
err.span_note(sup_span, "...must outlive the lifetime defined here"); note: (),
}
}
(Some(sub_span), Some(sup_span), Some(&sub_symbol), _) => {
PlaceholderRelationLfNotSatisfied::HasSub {
span,
sub_span,
sup_span,
sub_symbol,
note: (),
}
} }
(Some(sub_span), Some(sup_span), _, _) => { (Some(sub_span), Some(sup_span), _, _) => {
err.span_note(sub_span, "the lifetime defined here..."); PlaceholderRelationLfNotSatisfied::HasNone {
err.span_note(sup_span, "...must outlive the lifetime defined here"); span,
sub_span,
sup_span,
note: (),
}
} }
_ => {} _ => PlaceholderRelationLfNotSatisfied::OnlyPrimarySpan { span, note: () },
} };
err.note("this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)"); Some(self.tcx().sess.create_err(diag))
Some(err)
} }
_ => None, _ => None,
} }
} }

View file

@ -1,9 +1,11 @@
use crate::errors::RegionOriginNote; use crate::errors::{
note_and_explain, FullfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent,
RefLongerThanData, RegionOriginNote, WhereClauseSuggestions,
};
use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
use crate::infer::{self, SubregionOrigin}; use crate::infer::{self, SubregionOrigin};
use rustc_errors::{ use rustc_errors::{
fluent, struct_span_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, fluent, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
ErrorGuaranteed,
}; };
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::traits::ObligationCauseCode; use rustc_middle::traits::ObligationCauseCode;
@ -119,130 +121,105 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err err
} }
infer::Reborrow(span) => { infer::Reborrow(span) => {
let mut err = struct_span_err!( let reference_valid = note_and_explain::RegionExplanation::new(
self.tcx.sess,
span,
E0312,
"lifetime of reference outlives lifetime of borrowed content..."
);
note_and_explain_region(
self.tcx, self.tcx,
&mut err,
"...the reference is valid for ",
sub, sub,
"...",
None, None,
note_and_explain::PrefixKind::RefValidFor,
note_and_explain::SuffixKind::Continues,
); );
note_and_explain_region( let content_valid = note_and_explain::RegionExplanation::new(
self.tcx, self.tcx,
&mut err,
"...but the borrowed content is only valid for ",
sup, sup,
"",
None, None,
note_and_explain::PrefixKind::ContentValidFor,
note_and_explain::SuffixKind::Empty,
); );
err OutlivesContent {
span,
notes: reference_valid.into_iter().chain(content_valid).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
} }
infer::RelateObjectBound(span) => { infer::RelateObjectBound(span) => {
let mut err = struct_span_err!( let object_valid = note_and_explain::RegionExplanation::new(
self.tcx.sess,
span,
E0476,
"lifetime of the source pointer does not outlive lifetime bound of the \
object type"
);
note_and_explain_region(
self.tcx, self.tcx,
&mut err,
"object type is valid for ",
sub, sub,
"",
None, None,
note_and_explain::PrefixKind::TypeObjValidFor,
note_and_explain::SuffixKind::Empty,
); );
note_and_explain_region( let pointer_valid = note_and_explain::RegionExplanation::new(
self.tcx, self.tcx,
&mut err,
"source pointer is only valid for ",
sup, sup,
"",
None, None,
note_and_explain::PrefixKind::SourcePointerValidFor,
note_and_explain::SuffixKind::Empty,
); );
err OutlivesBound {
span,
notes: object_valid.into_iter().chain(pointer_valid).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
} }
infer::RelateParamBound(span, ty, opt_span) => { infer::RelateParamBound(span, ty, opt_span) => {
let mut err = struct_span_err!( let prefix = match *sub {
self.tcx.sess, ty::ReStatic => note_and_explain::PrefixKind::TypeSatisfy,
span, _ => note_and_explain::PrefixKind::TypeOutlive,
E0477, };
"the type `{}` does not fulfill the required lifetime", let suffix = if opt_span.is_some() {
self.ty_to_string(ty) note_and_explain::SuffixKind::ReqByBinding
} else {
note_and_explain::SuffixKind::Empty
};
let note = note_and_explain::RegionExplanation::new(
self.tcx, sub, opt_span, prefix, suffix,
); );
match *sub { FullfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note }
ty::ReStatic => note_and_explain_region( .into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
self.tcx,
&mut err,
"type must satisfy ",
sub,
if opt_span.is_some() { " as required by this binding" } else { "" },
opt_span,
),
_ => note_and_explain_region(
self.tcx,
&mut err,
"type must outlive ",
sub,
if opt_span.is_some() { " as required by this binding" } else { "" },
opt_span,
),
}
err
} }
infer::RelateRegionParamBound(span) => { infer::RelateRegionParamBound(span) => {
let mut err = let param_instantiated = note_and_explain::RegionExplanation::new(
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
note_and_explain_region(
self.tcx, self.tcx,
&mut err,
"lifetime parameter instantiated with ",
sup, sup,
"",
None, None,
note_and_explain::PrefixKind::LfParamInstantiatedWith,
note_and_explain::SuffixKind::Empty,
); );
note_and_explain_region( let param_must_outlive = note_and_explain::RegionExplanation::new(
self.tcx, self.tcx,
&mut err,
"but lifetime parameter must outlive ",
sub, sub,
"",
None, None,
note_and_explain::PrefixKind::LfParamMustOutlive,
note_and_explain::SuffixKind::Empty,
); );
err LfBoundNotSatisfied {
span,
notes: param_instantiated.into_iter().chain(param_must_outlive).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
} }
infer::ReferenceOutlivesReferent(ty, span) => { infer::ReferenceOutlivesReferent(ty, span) => {
let mut err = struct_span_err!( let pointer_valid = note_and_explain::RegionExplanation::new(
self.tcx.sess,
span,
E0491,
"in type `{}`, reference has a longer lifetime than the data it references",
self.ty_to_string(ty)
);
note_and_explain_region(
self.tcx, self.tcx,
&mut err,
"the pointer is valid for ",
sub, sub,
"",
None, None,
note_and_explain::PrefixKind::PointerValidFor,
note_and_explain::SuffixKind::Empty,
); );
note_and_explain_region( let data_valid = note_and_explain::RegionExplanation::new(
self.tcx, self.tcx,
&mut err,
"but the referenced data is only valid for ",
sup, sup,
"",
None, None,
note_and_explain::PrefixKind::DataValidFor,
note_and_explain::SuffixKind::Empty,
); );
err RefLongerThanData {
span,
ty: self.resolve_vars_if_possible(ty),
notes: pointer_valid.into_iter().chain(data_valid).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
} }
infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
let mut err = self.report_extra_impl_obligation( let mut err = self.report_extra_impl_obligation(
@ -279,25 +256,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err err
} }
infer::AscribeUserTypeProvePredicate(span) => { infer::AscribeUserTypeProvePredicate(span) => {
let mut err = let instantiated = note_and_explain::RegionExplanation::new(
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
note_and_explain_region(
self.tcx, self.tcx,
&mut err,
"lifetime instantiated with ",
sup, sup,
"",
None, None,
note_and_explain::PrefixKind::LfInstantiatedWith,
note_and_explain::SuffixKind::Empty,
); );
note_and_explain_region( let must_outlive = note_and_explain::RegionExplanation::new(
self.tcx, self.tcx,
&mut err,
"but lifetime must outlive ",
sub, sub,
"",
None, None,
note_and_explain::PrefixKind::LfMustOutlive,
note_and_explain::SuffixKind::Empty,
); );
err LfBoundNotSatisfied {
span,
notes: instantiated.into_iter().chain(must_outlive).collect(),
}
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic)
} }
}; };
if sub.is_error() || sup.is_error() { if sub.is_error() || sup.is_error() {
@ -347,22 +324,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; }; let Some(generics) = self.tcx.hir().get_generics(impl_item_def_id) else { return; };
if trait_predicates.is_empty() { let suggestion = if trait_predicates.is_empty() {
err.span_suggestion_verbose( WhereClauseSuggestions::Remove { span: generics.where_clause_span }
generics.where_clause_span,
"remove the `where` clause",
String::new(),
Applicability::MachineApplicable,
);
} else { } else {
let space = if generics.where_clause_span.is_empty() { " " } else { "" }; let space = if generics.where_clause_span.is_empty() { " " } else { "" };
err.span_suggestion_verbose( WhereClauseSuggestions::CopyPredicates {
generics.where_clause_span, span: generics.where_clause_span,
"copy the `where` clause predicates from the trait", space,
format!("{space}where {}", trait_predicates.join(", ")), trait_predicates: trait_predicates.join(", "),
Applicability::MachineApplicable, }
); };
} err.subdiagnostic(suggestion);
} }
pub(super) fn report_placeholder_failure( pub(super) fn report_placeholder_failure(

View file

@ -504,7 +504,9 @@ fn foo(&self) -> Self::T { String::new() }
let methods: Vec<(Span, String)> = items let methods: Vec<(Span, String)> = items
.in_definition_order() .in_definition_order()
.filter(|item| { .filter(|item| {
ty::AssocKind::Fn == item.kind && Some(item.name) != current_method_ident ty::AssocKind::Fn == item.kind
&& Some(item.name) != current_method_ident
&& !tcx.is_doc_hidden(item.def_id)
}) })
.filter_map(|item| { .filter_map(|item| {
let method = tcx.fn_sig(item.def_id).subst_identity(); let method = tcx.fn_sig(item.def_id).subst_identity();
@ -576,7 +578,7 @@ fn foo(&self) -> Self::T { String::new() }
tcx.impl_defaultness(item.id.owner_id) tcx.impl_defaultness(item.id.owner_id)
{ {
let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity(); let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity();
if self.infcx.can_eq(param_env, assoc_ty, found).is_ok() { if self.infcx.can_eq(param_env, assoc_ty, found) {
diag.span_label( diag.span_label(
item.span, item.span,
"associated type defaults can't be assumed inside the \ "associated type defaults can't be assumed inside the \
@ -598,7 +600,7 @@ fn foo(&self) -> Self::T { String::new() }
if let hir::AssocItemKind::Type = item.kind { if let hir::AssocItemKind::Type = item.kind {
let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity(); let assoc_ty = tcx.bound_type_of(item.id.owner_id).subst_identity();
if self.infcx.can_eq(param_env, assoc_ty, found).is_ok() { if self.infcx.can_eq(param_env, assoc_ty, found) {
diag.span_label(item.span, "expected this associated type"); diag.span_label(item.span, "expected this associated type");
return true; return true;
} }

View file

@ -11,21 +11,22 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable}; use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TypeVisitable};
use rustc_span::{sym, BytePos, Span}; use rustc_span::{sym, BytePos, Span};
use crate::errors::SuggAddLetForLetChains; use crate::errors::{
ConsiderAddingAwait, SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding,
};
use super::TypeErrCtxt; use super::TypeErrCtxt;
impl<'tcx> TypeErrCtxt<'_, 'tcx> { impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub(super) fn suggest_remove_semi_or_return_binding( pub(super) fn suggest_remove_semi_or_return_binding(
&self, &self,
err: &mut Diagnostic,
first_id: Option<hir::HirId>, first_id: Option<hir::HirId>,
first_ty: Ty<'tcx>, first_ty: Ty<'tcx>,
first_span: Span, first_span: Span,
second_id: Option<hir::HirId>, second_id: Option<hir::HirId>,
second_ty: Ty<'tcx>, second_ty: Ty<'tcx>,
second_span: Span, second_span: Span,
) { ) -> Option<SuggestRemoveSemiOrReturnBinding> {
let remove_semicolon = [ let remove_semicolon = [
(first_id, self.resolve_vars_if_possible(second_ty)), (first_id, self.resolve_vars_if_possible(second_ty)),
(second_id, self.resolve_vars_if_possible(first_ty)), (second_id, self.resolve_vars_if_possible(first_ty)),
@ -37,35 +38,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}); });
match remove_semicolon { match remove_semicolon {
Some((sp, StatementAsExpression::NeedsBoxing)) => { Some((sp, StatementAsExpression::NeedsBoxing)) => {
err.multipart_suggestion( Some(SuggestRemoveSemiOrReturnBinding::RemoveAndBox {
"consider removing this semicolon and boxing the expressions", first_lo: first_span.shrink_to_lo(),
vec![ first_hi: first_span.shrink_to_hi(),
(first_span.shrink_to_lo(), "Box::new(".to_string()), second_lo: second_span.shrink_to_lo(),
(first_span.shrink_to_hi(), ")".to_string()), second_hi: second_span.shrink_to_hi(),
(second_span.shrink_to_lo(), "Box::new(".to_string()), sp,
(second_span.shrink_to_hi(), ")".to_string()), })
(sp, String::new()),
],
Applicability::MachineApplicable,
);
} }
Some((sp, StatementAsExpression::CorrectType)) => { Some((sp, StatementAsExpression::CorrectType)) => {
err.span_suggestion_short( Some(SuggestRemoveSemiOrReturnBinding::Remove { sp })
sp,
"consider removing this semicolon",
"",
Applicability::MachineApplicable,
);
} }
None => { None => {
let mut ret = None;
for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] { for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
if let Some(id) = id if let Some(id) = id
&& let hir::Node::Block(blk) = self.tcx.hir().get(id) && let hir::Node::Block(blk) = self.tcx.hir().get(id)
&& self.consider_returning_binding(blk, ty, err) && let Some(diag) = self.consider_returning_binding_diag(blk, ty)
{ {
ret = Some(diag);
break; break;
} }
} }
ret
} }
} }
} }
@ -198,7 +193,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
return; return;
} }
match ( let subdiag = match (
self.get_impl_future_output_ty(exp_found.expected), self.get_impl_future_output_ty(exp_found.expected),
self.get_impl_future_output_ty(exp_found.found), self.get_impl_future_output_ty(exp_found.found),
) { ) {
@ -207,65 +202,56 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
{ {
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => { ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id); let then_span = self.find_block_span_from_hir_id(*then_id);
diag.multipart_suggestion( Some(ConsiderAddingAwait::BothFuturesSugg {
"consider `await`ing on both `Future`s", first: then_span.shrink_to_hi(),
vec![ second: exp_span.shrink_to_hi(),
(then_span.shrink_to_hi(), ".await".to_string()), })
(exp_span.shrink_to_hi(), ".await".to_string()),
],
Applicability::MaybeIncorrect,
);
} }
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
prior_arms, prior_arms,
.. ..
}) => { }) => {
if let [.., arm_span] = &prior_arms[..] { if let [.., arm_span] = &prior_arms[..] {
diag.multipart_suggestion( Some(ConsiderAddingAwait::BothFuturesSugg {
"consider `await`ing on both `Future`s", first: arm_span.shrink_to_hi(),
vec![ second: exp_span.shrink_to_hi(),
(arm_span.shrink_to_hi(), ".await".to_string()), })
(exp_span.shrink_to_hi(), ".await".to_string()),
],
Applicability::MaybeIncorrect,
);
} else { } else {
diag.help("consider `await`ing on both `Future`s"); Some(ConsiderAddingAwait::BothFuturesHelp)
} }
} }
_ => { _ => Some(ConsiderAddingAwait::BothFuturesHelp),
diag.help("consider `await`ing on both `Future`s");
}
}, },
(_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => { (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
self.suggest_await_on_future(diag, exp_span); // FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic
diag.span_note(exp_span, "calling an async function returns a future"); diag.subdiagnostic(ConsiderAddingAwait::FutureSugg {
span: exp_span.shrink_to_hi(),
});
Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span })
} }
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
{ {
ObligationCauseCode::Pattern { span: Some(then_span), .. } => { ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
self.suggest_await_on_future(diag, then_span.shrink_to_hi()); Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
} }
ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => { ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
let then_span = self.find_block_span_from_hir_id(*then_id); let then_span = self.find_block_span_from_hir_id(*then_id);
self.suggest_await_on_future(diag, then_span.shrink_to_hi()); Some(ConsiderAddingAwait::FutureSugg { span: then_span.shrink_to_hi() })
} }
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
ref prior_arms, ref prior_arms,
.. ..
}) => { }) => Some({
diag.multipart_suggestion_verbose( ConsiderAddingAwait::FutureSuggMultiple {
"consider `await`ing on the `Future`", spans: prior_arms.iter().map(|arm| arm.shrink_to_hi()).collect(),
prior_arms }
.iter() }),
.map(|arm| (arm.shrink_to_hi(), ".await".to_string())) _ => None,
.collect(),
Applicability::MaybeIncorrect,
);
}
_ => {}
}, },
_ => {} _ => None,
};
if let Some(subdiag) = subdiag {
diag.subdiagnostic(subdiag);
} }
} }
@ -655,16 +641,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// Suggest returning a local binding with a compatible type if the block /// Suggest returning a local binding with a compatible type if the block
/// has no return expression. /// has no return expression.
pub fn consider_returning_binding( pub fn consider_returning_binding_diag(
&self, &self,
blk: &'tcx hir::Block<'tcx>, blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>, expected_ty: Ty<'tcx>,
err: &mut Diagnostic, ) -> Option<SuggestRemoveSemiOrReturnBinding> {
) -> bool {
let blk = blk.innermost_block(); let blk = blk.innermost_block();
// Do not suggest if we have a tail expr. // Do not suggest if we have a tail expr.
if blk.expr.is_some() { if blk.expr.is_some() {
return false; return None;
} }
let mut shadowed = FxIndexSet::default(); let mut shadowed = FxIndexSet::default();
let mut candidate_idents = vec![]; let mut candidate_idents = vec![];
@ -733,7 +718,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
match &candidate_idents[..] { match &candidate_idents[..] {
[(ident, _ty)] => { [(ident, _ty)] => {
let sm = self.tcx.sess.source_map(); let sm = self.tcx.sess.source_map();
if let Some(stmt) = blk.stmts.last() { let (span, sugg) = if let Some(stmt) = blk.stmts.last() {
let stmt_span = sm.stmt_span(stmt.span, blk.span); let stmt_span = sm.stmt_span(stmt.span, blk.span);
let sugg = if sm.is_multiline(blk.span) let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(stmt_span) && let Some(spacing) = sm.indentation_before(stmt_span)
@ -742,12 +727,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} else { } else {
format!(" {ident}") format!(" {ident}")
}; };
err.span_suggestion_verbose( (stmt_span.shrink_to_hi(), sugg)
stmt_span.shrink_to_hi(),
format!("consider returning the local binding `{ident}`"),
sugg,
Applicability::MaybeIncorrect,
);
} else { } else {
let sugg = if sm.is_multiline(blk.span) let sugg = if sm.is_multiline(blk.span)
&& let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo()) && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
@ -757,21 +737,34 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
format!(" {ident} ") format!(" {ident} ")
}; };
let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi(); let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
err.span_suggestion_verbose( (
sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span), sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
format!("consider returning the local binding `{ident}`"),
sugg, sugg,
Applicability::MaybeIncorrect, )
); };
} Some(SuggestRemoveSemiOrReturnBinding::Add { sp: span, code: sugg, ident: *ident })
true
} }
values if (1..3).contains(&values.len()) => { values if (1..3).contains(&values.len()) => {
let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>(); let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
err.span_note(spans, "consider returning one of these bindings"); Some(SuggestRemoveSemiOrReturnBinding::AddOne { spans: spans.into() })
}
_ => None,
}
}
pub fn consider_returning_binding(
&self,
blk: &'tcx hir::Block<'tcx>,
expected_ty: Ty<'tcx>,
err: &mut Diagnostic,
) -> bool {
let diag = self.consider_returning_binding_diag(blk, expected_ty);
match diag {
Some(diag) => {
err.subdiagnostic(diag);
true true
} }
_ => false, None => false,
} }
} }
} }

View file

@ -880,30 +880,20 @@ impl<'tcx> InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup); self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
} }
pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx> pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where where
T: at::ToTrace<'tcx>, T: at::ToTrace<'tcx>,
{ {
let origin = &ObligationCause::dummy(); let origin = &ObligationCause::dummy();
self.probe(|_| { self.probe(|_| self.at(origin, param_env).sub(a, b).is_ok())
self.at(origin, param_env).sub(a, b).map(|InferOk { obligations: _, .. }| {
// Ignore obligations, since we are unrolling
// everything anyway.
})
})
} }
pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx> pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> bool
where where
T: at::ToTrace<'tcx>, T: at::ToTrace<'tcx>,
{ {
let origin = &ObligationCause::dummy(); let origin = &ObligationCause::dummy();
self.probe(|_| { self.probe(|_| self.at(origin, param_env).eq(a, b).is_ok())
self.at(origin, param_env).eq(a, b).map(|InferOk { obligations: _, .. }| {
// Ignore obligations, since we are unrolling
// everything anyway.
})
})
} }
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]

View file

@ -19,29 +19,29 @@ pub trait PointerArithmetic: HasDataLayout {
#[inline(always)] #[inline(always)]
fn max_size_of_val(&self) -> Size { fn max_size_of_val(&self) -> Size {
Size::from_bytes(self.machine_isize_max()) Size::from_bytes(self.target_isize_max())
} }
#[inline] #[inline]
fn machine_usize_max(&self) -> u64 { fn target_usize_max(&self) -> u64 {
self.pointer_size().unsigned_int_max().try_into().unwrap() self.pointer_size().unsigned_int_max().try_into().unwrap()
} }
#[inline] #[inline]
fn machine_isize_min(&self) -> i64 { fn target_isize_min(&self) -> i64 {
self.pointer_size().signed_int_min().try_into().unwrap() self.pointer_size().signed_int_min().try_into().unwrap()
} }
#[inline] #[inline]
fn machine_isize_max(&self) -> i64 { fn target_isize_max(&self) -> i64 {
self.pointer_size().signed_int_max().try_into().unwrap() self.pointer_size().signed_int_max().try_into().unwrap()
} }
#[inline] #[inline]
fn machine_usize_to_isize(&self, val: u64) -> i64 { fn target_usize_to_isize(&self, val: u64) -> i64 {
let val = val as i64; let val = val as i64;
// Now wrap-around into the machine_isize range. // Now wrap-around into the machine_isize range.
if val > self.machine_isize_max() { if val > self.target_isize_max() {
// This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into // This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into
// i64. // i64.
debug_assert!(self.pointer_size().bits() < 64); debug_assert!(self.pointer_size().bits() < 64);
@ -76,11 +76,11 @@ pub trait PointerArithmetic: HasDataLayout {
let n = i.unsigned_abs(); let n = i.unsigned_abs();
if i >= 0 { if i >= 0 {
let (val, over) = self.overflowing_offset(val, n); let (val, over) = self.overflowing_offset(val, n);
(val, over || i > self.machine_isize_max()) (val, over || i > self.target_isize_max())
} else { } else {
let res = val.overflowing_sub(n); let res = val.overflowing_sub(n);
let (val, over) = self.truncate_to_ptr(res); let (val, over) = self.truncate_to_ptr(res);
(val, over || i < self.machine_isize_min()) (val, over || i < self.target_isize_min())
} }
} }

View file

@ -75,8 +75,8 @@ impl<'tcx> ConstValue<'tcx> {
self.try_to_scalar_int()?.try_into().ok() self.try_to_scalar_int()?.try_into().ok()
} }
pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> { pub fn try_to_target_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int()?.try_to_machine_usize(tcx).ok() self.try_to_scalar_int()?.try_to_target_usize(tcx).ok()
} }
pub fn try_to_bits_for_ty( pub fn try_to_bits_for_ty(
@ -97,8 +97,8 @@ impl<'tcx> ConstValue<'tcx> {
ConstValue::Scalar(Scalar::from_u64(i)) ConstValue::Scalar(Scalar::from_u64(i))
} }
pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self { pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
ConstValue::Scalar(Scalar::from_machine_usize(i, cx)) ConstValue::Scalar(Scalar::from_target_usize(i, cx))
} }
} }
@ -241,7 +241,7 @@ impl<Prov> Scalar<Prov> {
} }
#[inline] #[inline]
pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self { pub fn from_target_usize(i: u64, cx: &impl HasDataLayout) -> Self {
Self::from_uint(i, cx.data_layout().pointer_size) Self::from_uint(i, cx.data_layout().pointer_size)
} }
@ -268,7 +268,7 @@ impl<Prov> Scalar<Prov> {
} }
#[inline] #[inline]
pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self { pub fn from_target_isize(i: i64, cx: &impl HasDataLayout) -> Self {
Self::from_int(i, cx.data_layout().pointer_size) Self::from_int(i, cx.data_layout().pointer_size)
} }
@ -429,7 +429,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized unsigned integer. /// Converts the scalar to produce a machine-pointer-sized unsigned integer.
/// Fails if the scalar is a pointer. /// Fails if the scalar is a pointer.
pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> { pub fn to_target_usize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> {
let b = self.to_uint(cx.data_layout().pointer_size)?; let b = self.to_uint(cx.data_layout().pointer_size)?;
Ok(u64::try_from(b).unwrap()) Ok(u64::try_from(b).unwrap())
} }
@ -469,7 +469,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
/// Converts the scalar to produce a machine-pointer-sized signed integer. /// Converts the scalar to produce a machine-pointer-sized signed integer.
/// Fails if the scalar is a pointer. /// Fails if the scalar is a pointer.
pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> { pub fn to_target_isize(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, i64> {
let b = self.to_int(cx.data_layout().pointer_size)?; let b = self.to_int(cx.data_layout().pointer_size)?;
Ok(i64::try_from(b).unwrap()) Ok(i64::try_from(b).unwrap())
} }

View file

@ -2357,10 +2357,10 @@ impl<'tcx> ConstantKind<'tcx> {
) -> Option<u64> { ) -> Option<u64> {
match self { match self {
Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env), Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env),
Self::Val(val, _) => val.try_to_machine_usize(tcx), Self::Val(val, _) => val.try_to_target_usize(tcx),
Self::Unevaluated(uneval, _) => { Self::Unevaluated(uneval, _) => {
match tcx.const_eval_resolve(param_env, *uneval, None) { match tcx.const_eval_resolve(param_env, *uneval, None) {
Ok(val) => val.try_to_machine_usize(tcx), Ok(val) => val.try_to_target_usize(tcx),
Err(_) => None, Err(_) => None,
} }
} }

View file

@ -206,7 +206,7 @@ impl<'tcx> Const<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>, param_env: ParamEnv<'tcx>,
) -> Option<u64> { ) -> Option<u64> {
self.kind().eval(tcx, param_env).try_to_machine_usize(tcx) self.kind().eval(tcx, param_env).try_to_target_usize(tcx)
} }
#[inline] #[inline]

View file

@ -232,7 +232,7 @@ impl ScalarInt {
} }
#[inline] #[inline]
pub fn try_to_machine_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> { pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64) Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
} }

View file

@ -125,8 +125,8 @@ impl<'tcx> ConstKind<'tcx> {
} }
#[inline] #[inline]
pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_value()?.try_to_machine_usize(tcx) self.try_to_value()?.try_to_target_usize(tcx)
} }
} }

View file

@ -78,8 +78,8 @@ impl<'tcx> ValTree<'tcx> {
} }
} }
pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> { pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten() self.try_to_scalar_int().map(|s| s.try_to_target_usize(tcx).ok()).flatten()
} }
/// Get the values inside the ValTree as a slice of bytes. This only works for /// Get the values inside the ValTree as a slice of bytes. This only works for

View file

@ -159,7 +159,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
match self { match self {
Self::ConstIsZero(c) => { Self::ConstIsZero(c) => {
let c = ty::EarlyBinder(c).subst(tcx, substs); let c = ty::EarlyBinder(c).subst(tcx, substs);
let pred = match c.kind().try_to_machine_usize(tcx) { let pred = match c.kind().try_to_target_usize(tcx) {
Some(0) => Self::True, Some(0) => Self::True,
Some(1..) => Self::False, Some(1..) => Self::False,
None => Self::ConstIsZero(c), None => Self::ConstIsZero(c),

View file

@ -191,7 +191,7 @@ fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedP
// If we can evaluate the array length before having a `ParamEnv`, then // If we can evaluate the array length before having a `ParamEnv`, then
// we can simplify the predicate. This is an optimization. // we can simplify the predicate. This is an optimization.
Array(ty, len) => match len.kind().try_to_machine_usize(tcx) { Array(ty, len) => match len.kind().try_to_target_usize(tcx) {
Some(0) => InhabitedPredicate::True, Some(0) => InhabitedPredicate::True,
Some(1..) => ty.inhabited_predicate(tcx), Some(1..) => ty.inhabited_predicate(tcx),
None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)), None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),

View file

@ -1628,7 +1628,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Eventually I'll need to implement param-env-aware // Eventually I'll need to implement param-env-aware
// `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
if self.can_sub(param_env, error, implication).is_ok() { if self.can_sub(param_env, error, implication) {
debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
return true; return true;
} }

View file

@ -72,7 +72,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let impl_self_ty = impl_trait_ref.self_ty(); let impl_self_ty = impl_trait_ref.self_ty();
if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) { if self.can_eq(param_env, trait_self_ty, impl_self_ty) {
self_match_impls.push((def_id, impl_substs)); self_match_impls.push((def_id, impl_substs));
if iter::zip( if iter::zip(
@ -261,7 +261,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]` // Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
if let ty::Array(aty, len) = self_ty.kind() { if let ty::Array(aty, len) = self_ty.kind() {
flags.push((sym::_Self, Some("[]".to_string()))); flags.push((sym::_Self, Some("[]".to_string())));
let len = len.kind().try_to_value().and_then(|v| v.try_to_machine_usize(self.tcx)); let len = len.kind().try_to_value().and_then(|v| v.try_to_target_usize(self.tcx));
flags.push((sym::_Self, Some(format!("[{}; _]", aty)))); flags.push((sym::_Self, Some(format!("[{}; _]", aty))));
if let Some(n) = len { if let Some(n) = len {
flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n)))); flags.push((sym::_Self, Some(format!("[{}; {}]", aty, n))));

View file

@ -748,10 +748,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let real_ty = real_trait_pred.self_ty(); let real_ty = real_trait_pred.self_ty();
// We `erase_late_bound_regions` here because `make_subregion` does not handle // We `erase_late_bound_regions` here because `make_subregion` does not handle
// `ReLateBound`, and we don't particularly care about the regions. // `ReLateBound`, and we don't particularly care about the regions.
if self if !self.can_eq(
.can_eq(obligation.param_env, self.tcx.erase_late_bound_regions(real_ty), arg_ty) obligation.param_env,
.is_err() self.tcx.erase_late_bound_regions(real_ty),
{ arg_ty,
) {
continue; continue;
} }
@ -3690,7 +3691,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let Some((span, (assoc, ty))) = entry else { continue; }; let Some((span, (assoc, ty))) = entry else { continue; };
if primary_spans.is_empty() || type_diffs.iter().any(|diff| { if primary_spans.is_empty() || type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else { return false; }; let Sorts(expected_found) = diff else { return false; };
self.can_eq(param_env, expected_found.found, ty).is_ok() self.can_eq(param_env, expected_found.found, ty)
}) { }) {
// FIXME: this doesn't quite work for `Iterator::collect` // FIXME: this doesn't quite work for `Iterator::collect`
// because we have `Vec<i32>` and `()`, but we'd want `i32` // because we have `Vec<i32>` and `()`, but we'd want `i32`
@ -3717,10 +3718,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty)); let ty_str = with_forced_trimmed_paths!(self.ty_to_string(ty));
let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc)); let assoc = with_forced_trimmed_paths!(self.tcx.def_path_str(assoc));
if self.can_eq(param_env, ty, *prev_ty).is_err() { if !self.can_eq(param_env, ty, *prev_ty) {
if type_diffs.iter().any(|diff| { if type_diffs.iter().any(|diff| {
let Sorts(expected_found) = diff else { return false; }; let Sorts(expected_found) = diff else { return false; };
self.can_eq(param_env, expected_found.found, ty).is_ok() self.can_eq(param_env, expected_found.found, ty)
}) { }) {
primary_spans.push(span); primary_spans.push(span);
} }
@ -3868,7 +3869,7 @@ fn hint_missing_borrow<'tcx>(
let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg); let (found_ty, found_refs) = get_deref_type_and_refs(*found_arg);
let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg); let (expected_ty, expected_refs) = get_deref_type_and_refs(*expected_arg);
if infcx.can_eq(param_env, found_ty, expected_ty).is_ok() { if infcx.can_eq(param_env, found_ty, expected_ty) {
// FIXME: This could handle more exotic cases like mutability mismatches too! // FIXME: This could handle more exotic cases like mutability mismatches too!
if found_refs.len() < expected_refs.len() if found_refs.len() < expected_refs.len()
&& found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..] && found_refs[..] == expected_refs[expected_refs.len() - found_refs.len()..]

View file

@ -216,7 +216,8 @@ pub fn spin_loop() {
/// ///
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
/// extent to which it can block optimisations may vary depending upon the platform and code-gen /// extent to which it can block optimisations may vary depending upon the platform and code-gen
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way. /// backend used. Programs cannot rely on `black_box` for *correctness*, beyond it behaving as the
/// identity function.
/// ///
/// [`std::convert::identity`]: crate::convert::identity /// [`std::convert::identity`]: crate::convert::identity
/// ///

View file

@ -334,6 +334,10 @@ impl File {
/// ///
/// See the [`OpenOptions::open`] method for more details. /// See the [`OpenOptions::open`] method for more details.
/// ///
/// If you only need to read the entire file contents,
/// consider [`std::fs::read()`][self::read] or
/// [`std::fs::read_to_string()`][self::read_to_string] instead.
///
/// # Errors /// # Errors
/// ///
/// This function will return an error if `path` does not already exist. /// This function will return an error if `path` does not already exist.
@ -343,9 +347,12 @@ impl File {
/// ///
/// ```no_run /// ```no_run
/// use std::fs::File; /// use std::fs::File;
/// use std::io::Read;
/// ///
/// fn main() -> std::io::Result<()> { /// fn main() -> std::io::Result<()> {
/// let mut f = File::open("foo.txt")?; /// let mut f = File::open("foo.txt")?;
/// let mut data = vec![];
/// f.read_to_end(&mut data)?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
@ -361,16 +368,20 @@ impl File {
/// ///
/// Depending on the platform, this function may fail if the /// Depending on the platform, this function may fail if the
/// full directory path does not exist. /// full directory path does not exist.
///
/// See the [`OpenOptions::open`] function for more details. /// See the [`OpenOptions::open`] function for more details.
/// ///
/// See also [`std::fs::write()`][self::write] for a simple function to
/// create a file with a given data.
///
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// use std::fs::File; /// use std::fs::File;
/// use std::io::Write;
/// ///
/// fn main() -> std::io::Result<()> { /// fn main() -> std::io::Result<()> {
/// let mut f = File::create("foo.txt")?; /// let mut f = File::create("foo.txt")?;
/// f.write_all(&1234_u32.to_be_bytes())?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
@ -397,9 +408,11 @@ impl File {
/// #![feature(file_create_new)] /// #![feature(file_create_new)]
/// ///
/// use std::fs::File; /// use std::fs::File;
/// use std::io::Write;
/// ///
/// fn main() -> std::io::Result<()> { /// fn main() -> std::io::Result<()> {
/// let mut f = File::create_new("foo.txt")?; /// let mut f = File::create_new("foo.txt")?;
/// f.write_all("Hello, world!".as_bytes())?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
@ -426,9 +439,11 @@ impl File {
/// ///
/// ```no_run /// ```no_run
/// use std::fs::File; /// use std::fs::File;
/// use std::io::Write;
/// ///
/// fn main() -> std::io::Result<()> { /// fn main() -> std::io::Result<()> {
/// let mut f = File::options().append(true).open("example.log")?; /// let mut f = File::options().append(true).open("example.log")?;
/// writeln!(&mut f, "new line")?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
@ -966,6 +981,9 @@ impl OpenOptions {
/// In order for the file to be created, [`OpenOptions::write`] or /// In order for the file to be created, [`OpenOptions::write`] or
/// [`OpenOptions::append`] access must be used. /// [`OpenOptions::append`] access must be used.
/// ///
/// See also [`std::fs::write()`][self::write] for a simple function to
/// create a file with a given data.
///
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run

View file

@ -164,10 +164,10 @@ impl Cfg {
/// Renders the configuration for human display, as a short HTML description. /// Renders the configuration for human display, as a short HTML description.
pub(crate) fn render_short_html(&self) -> String { pub(crate) fn render_short_html(&self) -> String {
let mut msg = Display(self, Format::ShortHtml).to_string(); let mut msg = Display(self, Format::ShortHtml).to_string();
if self.should_capitalize_first_letter() { if self.should_capitalize_first_letter() &&
if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) { let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric())
msg[i..i + 1].make_ascii_uppercase(); {
} msg[i..i + 1].make_ascii_uppercase();
} }
msg msg
} }

View file

@ -390,18 +390,17 @@ pub(crate) fn build_impl(
// Only inline impl if the implemented trait is // Only inline impl if the implemented trait is
// reachable in rustdoc generated documentation // reachable in rustdoc generated documentation
if !did.is_local() { if !did.is_local() && let Some(traitref) = associated_trait {
if let Some(traitref) = associated_trait { let did = traitref.def_id;
let did = traitref.def_id; if !cx.cache.effective_visibilities.is_directly_public(tcx, did) {
if !cx.cache.effective_visibilities.is_directly_public(tcx, did) { return;
return; }
}
if let Some(stab) = tcx.lookup_stability(did) { if let Some(stab) = tcx.lookup_stability(did) &&
if stab.is_unstable() && stab.feature == sym::rustc_private { stab.is_unstable() &&
return; stab.feature == sym::rustc_private
} {
} return;
} }
} }
@ -525,10 +524,8 @@ pub(crate) fn build_impl(
} }
while let Some(ty) = stack.pop() { while let Some(ty) = stack.pop() {
if let Some(did) = ty.def_id(&cx.cache) { if let Some(did) = ty.def_id(&cx.cache) && tcx.is_doc_hidden(did) {
if tcx.is_doc_hidden(did) { return;
return;
}
} }
if let Some(generics) = ty.generics() { if let Some(generics) = ty.generics() {
stack.extend(generics); stack.extend(generics);

View file

@ -787,43 +787,43 @@ fn clean_ty_generics<'tcx>(
None None
})(); })();
if let Some(param_idx) = param_idx { if let Some(param_idx) = param_idx
if let Some(b) = impl_trait.get_mut(&param_idx.into()) { && let Some(b) = impl_trait.get_mut(&param_idx.into())
let p: WherePredicate = clean_predicate(*p, cx)?; {
let p: WherePredicate = clean_predicate(*p, cx)?;
b.extend( b.extend(
p.get_bounds() p.get_bounds()
.into_iter()
.flatten()
.cloned()
.filter(|b| !b.is_sized_bound(cx)),
);
let proj = projection.map(|p| {
(
clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
p.map_bound(|p| p.term),
)
});
if let Some(((_, trait_did, name), rhs)) = proj
.as_ref()
.and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
{
// FIXME(...): Remove this unwrap()
impl_trait_proj.entry(param_idx).or_default().push((
trait_did,
name,
rhs.map_bound(|rhs| rhs.ty().unwrap()),
p.get_bound_params()
.into_iter() .into_iter()
.flatten() .flatten()
.cloned() .map(|param| GenericParamDef::lifetime(param.0))
.filter(|b| !b.is_sized_bound(cx)), .collect(),
); ));
let proj = projection.map(|p| {
(
clean_projection(p.map_bound(|p| p.projection_ty), cx, None),
p.map_bound(|p| p.term),
)
});
if let Some(((_, trait_did, name), rhs)) = proj
.as_ref()
.and_then(|(lhs, rhs): &(Type, _)| Some((lhs.projection()?, rhs)))
{
// FIXME(...): Remove this unwrap()
impl_trait_proj.entry(param_idx).or_default().push((
trait_did,
name,
rhs.map_bound(|rhs| rhs.ty().unwrap()),
p.get_bound_params()
.into_iter()
.flatten()
.map(|param| GenericParamDef::lifetime(param.0))
.collect(),
));
}
return None;
} }
return None;
} }
Some(p) Some(p)
@ -886,7 +886,7 @@ fn clean_ty_generics<'tcx>(
// `?Sized` bound for each one we didn't find to be `Sized`. // `?Sized` bound for each one we didn't find to be `Sized`.
for tp in &stripped_params { for tp in &stripped_params {
if let types::GenericParamDefKind::Type { .. } = tp.kind if let types::GenericParamDefKind::Type { .. } = tp.kind
&& !sized_params.contains(&tp.name) && !sized_params.contains(&tp.name)
{ {
where_predicates.push(WherePredicate::BoundPredicate { where_predicates.push(WherePredicate::BoundPredicate {
ty: Type::Generic(tp.name), ty: Type::Generic(tp.name),
@ -1461,10 +1461,10 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
// Try to normalize `<X as Y>::T` to a type // Try to normalize `<X as Y>::T` to a type
let ty = hir_ty_to_ty(cx.tcx, hir_ty); let ty = hir_ty_to_ty(cx.tcx, hir_ty);
// `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>` // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>`
if !ty.has_escaping_bound_vars() { if !ty.has_escaping_bound_vars()
if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) { && let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty))
return clean_middle_ty(normalized_value, cx, None); {
} return clean_middle_ty(normalized_value, cx, None);
} }
let trait_segments = &p.segments[..p.segments.len() - 1]; let trait_segments = &p.segments[..p.segments.len() - 1];
@ -1878,11 +1878,9 @@ fn clean_middle_opaque_bounds<'tcx>(
_ => return None, _ => return None,
}; };
if let Some(sized) = cx.tcx.lang_items().sized_trait() { if let Some(sized) = cx.tcx.lang_items().sized_trait() && trait_ref.def_id() == sized {
if trait_ref.def_id() == sized { has_sized = true;
has_sized = true; return None;
return None;
}
} }
let bindings: ThinVec<_> = bounds let bindings: ThinVec<_> = bounds
@ -2392,17 +2390,15 @@ fn clean_use_statement_inner<'tcx>(
let is_visible_from_parent_mod = let is_visible_from_parent_mod =
visibility.is_accessible_from(parent_mod, cx.tcx) && !current_mod.is_top_level_module(); visibility.is_accessible_from(parent_mod, cx.tcx) && !current_mod.is_top_level_module();
if pub_underscore { if pub_underscore && let Some(ref inline) = inline_attr {
if let Some(ref inline) = inline_attr { rustc_errors::struct_span_err!(
rustc_errors::struct_span_err!( cx.tcx.sess,
cx.tcx.sess, inline.span(),
inline.span(), E0780,
E0780, "anonymous imports cannot be inlined"
"anonymous imports cannot be inlined" )
) .span_label(import.span, "anonymous import")
.span_label(import.span, "anonymous import") .emit();
.emit();
}
} }
// We consider inlining the documentation of `pub use` statements, but we // We consider inlining the documentation of `pub use` statements, but we
@ -2438,14 +2434,13 @@ fn clean_use_statement_inner<'tcx>(
} }
Import::new_glob(resolve_use_source(cx, path), true) Import::new_glob(resolve_use_source(cx, path), true)
} else { } else {
if inline_attr.is_none() { if inline_attr.is_none()
if let Res::Def(DefKind::Mod, did) = path.res { && let Res::Def(DefKind::Mod, did) = path.res
if !did.is_local() && did.is_crate_root() { && !did.is_local() && did.is_crate_root()
// if we're `pub use`ing an extern crate root, don't inline it unless we {
// were specifically asked for it // if we're `pub use`ing an extern crate root, don't inline it unless we
denied = true; // were specifically asked for it
} denied = true;
}
} }
if !denied { if !denied {
let mut visited = DefIdSet::default(); let mut visited = DefIdSet::default();

View file

@ -182,10 +182,8 @@ impl ExternalCrate {
return Local; return Local;
} }
if extern_url_takes_precedence { if extern_url_takes_precedence && let Some(url) = extern_url {
if let Some(url) = extern_url { return to_remote(url);
return to_remote(url);
}
} }
// Failing that, see if there's an attribute specifying where to find this // Failing that, see if there's an attribute specifying where to find this
@ -1176,10 +1174,10 @@ impl GenericBound {
pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
use rustc_hir::TraitBoundModifier as TBM; use rustc_hir::TraitBoundModifier as TBM;
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self &&
if Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() { Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait()
return true; {
} return true;
} }
false false
} }

View file

@ -345,10 +345,10 @@ pub(crate) fn is_literal_expr(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
return true; return true;
} }
if let hir::ExprKind::Unary(hir::UnOp::Neg, expr) = &expr.kind { if let hir::ExprKind::Unary(hir::UnOp::Neg, expr) = &expr.kind &&
if let hir::ExprKind::Lit(_) = &expr.kind { let hir::ExprKind::Lit(_) = &expr.kind
return true; {
} return true;
} }
} }

View file

@ -229,11 +229,11 @@ fn scrape_test_config(attrs: &[ast::Attribute]) -> GlobalTestOptions {
if attr.has_name(sym::no_crate_inject) { if attr.has_name(sym::no_crate_inject) {
opts.no_crate_inject = true; opts.no_crate_inject = true;
} }
if attr.has_name(sym::attr) { if attr.has_name(sym::attr)
if let Some(l) = attr.meta_item_list() { && let Some(l) = attr.meta_item_list()
for item in l { {
opts.attrs.push(pprust::meta_list_item_to_string(item)); for item in l {
} opts.attrs.push(pprust::meta_list_item_to_string(item));
} }
} }
} }
@ -594,31 +594,28 @@ pub(crate) fn make_test(
loop { loop {
match parser.parse_item(ForceCollect::No) { match parser.parse_item(ForceCollect::No) {
Ok(Some(item)) => { Ok(Some(item)) => {
if !found_main { if !found_main &&
if let ast::ItemKind::Fn(..) = item.kind { let ast::ItemKind::Fn(..) = item.kind &&
if item.ident.name == sym::main { item.ident.name == sym::main
found_main = true; {
} found_main = true;
}
if !found_extern_crate &&
let ast::ItemKind::ExternCrate(original) = item.kind
{
// This code will never be reached if `crate_name` is none because
// `found_extern_crate` is initialized to `true` if it is none.
let crate_name = crate_name.unwrap();
match original {
Some(name) => found_extern_crate = name.as_str() == crate_name,
None => found_extern_crate = item.ident.as_str() == crate_name,
} }
} }
if !found_extern_crate { if !found_macro && let ast::ItemKind::MacCall(..) = item.kind {
if let ast::ItemKind::ExternCrate(original) = item.kind { found_macro = true;
// This code will never be reached if `crate_name` is none because
// `found_extern_crate` is initialized to `true` if it is none.
let crate_name = crate_name.unwrap();
match original {
Some(name) => found_extern_crate = name.as_str() == crate_name,
None => found_extern_crate = item.ident.as_str() == crate_name,
}
}
}
if !found_macro {
if let ast::ItemKind::MacCall(..) = item.kind {
found_macro = true;
}
} }
if found_main && found_extern_crate { if found_main && found_extern_crate {
@ -972,14 +969,12 @@ impl Collector {
fn get_filename(&self) -> FileName { fn get_filename(&self) -> FileName {
if let Some(ref source_map) = self.source_map { if let Some(ref source_map) = self.source_map {
let filename = source_map.span_to_filename(self.position); let filename = source_map.span_to_filename(self.position);
if let FileName::Real(ref filename) = filename { if let FileName::Real(ref filename) = filename &&
if let Ok(cur_dir) = env::current_dir() { let Ok(cur_dir) = env::current_dir() &&
if let Some(local_path) = filename.local_path() { let Some(local_path) = filename.local_path() &&
if let Ok(path) = local_path.strip_prefix(&cur_dir) { let Ok(path) = local_path.strip_prefix(&cur_dir)
return path.to_owned().into(); {
} return path.to_owned().into();
}
}
} }
filename filename
} else if let Some(ref filename) = self.filename { } else if let Some(ref filename) = self.filename {

View file

@ -229,16 +229,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
} }
// Collect all the implementors of traits. // Collect all the implementors of traits.
if let clean::ImplItem(ref i) = *item.kind { if let clean::ImplItem(ref i) = *item.kind &&
if let Some(trait_) = &i.trait_ { let Some(trait_) = &i.trait_ &&
if !i.kind.is_blanket() { !i.kind.is_blanket()
self.cache {
.implementors self.cache
.entry(trait_.def_id()) .implementors
.or_default() .entry(trait_.def_id())
.push(Impl { impl_item: item.clone() }); .or_default()
} .push(Impl { impl_item: item.clone() });
}
} }
// Index this method for searching later on. // Index this method for searching later on.

View file

@ -710,11 +710,9 @@ pub(crate) fn href_with_root_path(
} }
} }
}; };
if !is_remote { if !is_remote && let Some(root_path) = root_path {
if let Some(root_path) = root_path { let root = root_path.trim_end_matches('/');
let root = root_path.trim_end_matches('/'); url_parts.push_front(root);
url_parts.push_front(root);
}
} }
debug!(?url_parts); debug!(?url_parts);
match shortty { match shortty {

View file

@ -466,10 +466,8 @@ impl<'a> PeekIter<'a> {
} }
/// Returns the next item after the current one. It doesn't interfere with `peek_next` output. /// Returns the next item after the current one. It doesn't interfere with `peek_next` output.
fn peek(&mut self) -> Option<&(TokenKind, &'a str)> { fn peek(&mut self) -> Option<&(TokenKind, &'a str)> {
if self.stored.is_empty() { if self.stored.is_empty() && let Some(next) = self.iter.next() {
if let Some(next) = self.iter.next() { self.stored.push_back(next);
self.stored.push_back(next);
}
} }
self.stored.front() self.stored.front()
} }

View file

@ -705,14 +705,12 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
shared.fs.write(scrape_examples_help_file, v)?; shared.fs.write(scrape_examples_help_file, v)?;
} }
if let Some(ref redirections) = shared.redirections { if let Some(ref redirections) = shared.redirections && !redirections.borrow().is_empty() {
if !redirections.borrow().is_empty() { let redirect_map_path =
let redirect_map_path = self.dst.join(crate_name.as_str()).join("redirect-map.json");
self.dst.join(crate_name.as_str()).join("redirect-map.json"); let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
let paths = serde_json::to_string(&*redirections.borrow()).unwrap(); shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
shared.ensure_dir(&self.dst.join(crate_name.as_str()))?; shared.fs.write(redirect_map_path, paths)?;
shared.fs.write(redirect_map_path, paths)?;
}
} }
// No need for it anymore. // No need for it anymore.

View file

@ -2225,14 +2225,13 @@ fn sidebar_deref_methods(
}) })
{ {
debug!("found target, real_target: {:?} {:?}", target, real_target); debug!("found target, real_target: {:?} {:?}", target, real_target);
if let Some(did) = target.def_id(c) { if let Some(did) = target.def_id(c) &&
if let Some(type_did) = impl_.inner_impl().for_.def_id(c) { let Some(type_did) = impl_.inner_impl().for_.def_id(c) &&
// `impl Deref<Target = S> for S` // `impl Deref<Target = S> for S`
if did == type_did || !derefs.insert(did) { (did == type_did || !derefs.insert(did))
// Avoid infinite cycles {
return; // Avoid infinite cycles
} return;
}
} }
let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait()); let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait());
let inner_impl = target let inner_impl = target
@ -2266,25 +2265,24 @@ fn sidebar_deref_methods(
} }
// Recurse into any further impls that might exist for `target` // Recurse into any further impls that might exist for `target`
if let Some(target_did) = target.def_id(c) { if let Some(target_did) = target.def_id(c) &&
if let Some(target_impls) = c.impls.get(&target_did) { let Some(target_impls) = c.impls.get(&target_did) &&
if let Some(target_deref_impl) = target_impls.iter().find(|i| { let Some(target_deref_impl) = target_impls.iter().find(|i| {
i.inner_impl() i.inner_impl()
.trait_ .trait_
.as_ref() .as_ref()
.map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait()) .map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait())
.unwrap_or(false) .unwrap_or(false)
}) { })
sidebar_deref_methods( {
cx, sidebar_deref_methods(
out, cx,
target_deref_impl, out,
target_impls, target_deref_impl,
derefs, target_impls,
used_links, derefs,
); used_links,
} );
}
} }
} }
} }

View file

@ -80,12 +80,11 @@ impl<'tcx> JsonRenderer<'tcx> {
// document primitive items in an arbitrary crate by using // document primitive items in an arbitrary crate by using
// `doc(primitive)`. // `doc(primitive)`.
let mut is_primitive_impl = false; let mut is_primitive_impl = false;
if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind { if let clean::types::ItemKind::ImplItem(ref impl_) = *item.kind &&
if impl_.trait_.is_none() { impl_.trait_.is_none() &&
if let clean::types::Type::Primitive(_) = impl_.for_ { let clean::types::Type::Primitive(_) = impl_.for_
is_primitive_impl = true; {
} is_primitive_impl = true;
}
} }
if item.item_id.is_local() || is_primitive_impl { if item.item_id.is_local() || is_primitive_impl {

View file

@ -82,18 +82,17 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
let def_id = item.item_id.expect_def_id().expect_local(); let def_id = item.item_id.expect_def_id().expect_local();
// check if parent is trait impl // check if parent is trait impl
if let Some(parent_def_id) = cx.tcx.opt_local_parent(def_id) { if let Some(parent_def_id) = cx.tcx.opt_local_parent(def_id) &&
if let Some(parent_node) = cx.tcx.hir().find_by_def_id(parent_def_id) { let Some(parent_node) = cx.tcx.hir().find_by_def_id(parent_def_id) &&
if matches!( matches!(
parent_node, parent_node,
hir::Node::Item(hir::Item { hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }), kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }),
.. ..
}) })
) { )
return false; {
} return false;
}
} }
if cx.tcx.is_doc_hidden(def_id.to_def_id()) if cx.tcx.is_doc_hidden(def_id.to_def_id())

View file

@ -156,39 +156,38 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) ->
// scan through included items ahead of time to splice in Deref targets to the "valid" sets // scan through included items ahead of time to splice in Deref targets to the "valid" sets
for it in new_items_external.iter().chain(new_items_local.iter()) { for it in new_items_external.iter().chain(new_items_local.iter()) {
if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind { if let ImplItem(box Impl { ref for_, ref trait_, ref items, .. }) = *it.kind &&
if trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait() &&
&& cleaner.keep_impl(for_, true) cleaner.keep_impl(for_, true)
{ {
let target = items let target = items
.iter() .iter()
.find_map(|item| match *item.kind { .find_map(|item| match *item.kind {
AssocTypeItem(ref t, _) => Some(&t.type_), AssocTypeItem(ref t, _) => Some(&t.type_),
_ => None, _ => None,
}) })
.expect("Deref impl without Target type"); .expect("Deref impl without Target type");
if let Some(prim) = target.primitive_type() { if let Some(prim) = target.primitive_type() {
cleaner.prims.insert(prim); cleaner.prims.insert(prim);
} else if let Some(did) = target.def_id(&cx.cache) { } else if let Some(did) = target.def_id(&cx.cache) {
cleaner.items.insert(did.into()); cleaner.items.insert(did.into());
} }
if let Some(for_did) = for_.def_id(&cx.cache) { if let Some(for_did) = for_.def_id(&cx.cache) {
if type_did_to_deref_target.insert(for_did, target).is_none() { if type_did_to_deref_target.insert(for_did, target).is_none() {
// Since only the `DefId` portion of the `Type` instances is known to be same for both the // Since only the `DefId` portion of the `Type` instances is known to be same for both the
// `Deref` target type and the impl for type positions, this map of types is keyed by // `Deref` target type and the impl for type positions, this map of types is keyed by
// `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly. // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
if cleaner.keep_impl_with_def_id(for_did.into()) { if cleaner.keep_impl_with_def_id(for_did.into()) {
let mut targets = DefIdSet::default(); let mut targets = DefIdSet::default();
targets.insert(for_did); targets.insert(for_did);
add_deref_target( add_deref_target(
cx, cx,
&type_did_to_deref_target, &type_did_to_deref_target,
&mut cleaner, &mut cleaner,
&mut targets, &mut targets,
for_did, for_did,
); );
}
} }
} }
} }

View file

@ -210,11 +210,9 @@ fn extract_path_backwards(text: &str, end_pos: usize) -> Option<usize> {
.take_while(|(_, c)| is_id_start(*c) || is_id_continue(*c)) .take_while(|(_, c)| is_id_start(*c) || is_id_continue(*c))
.reduce(|_accum, item| item) .reduce(|_accum, item| item)
.and_then(|(new_pos, c)| is_id_start(c).then_some(new_pos)); .and_then(|(new_pos, c)| is_id_start(c).then_some(new_pos));
if let Some(new_pos) = new_pos { if let Some(new_pos) = new_pos && current_pos != new_pos {
if current_pos != new_pos { current_pos = new_pos;
current_pos = new_pos; continue;
continue;
}
} }
break; break;
} }

View file

@ -201,27 +201,25 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
// Because we don't inline in `maybe_inline_local` if the output format is JSON, // Because we don't inline in `maybe_inline_local` if the output format is JSON,
// we need to make a special check for JSON output: we want to keep it unless it has // we need to make a special check for JSON output: we want to keep it unless it has
// a `#[doc(hidden)]` attribute if the `for_` type is exported. // a `#[doc(hidden)]` attribute if the `for_` type is exported.
if let Some(did) = imp.for_.def_id(self.cache) { if let Some(did) = imp.for_.def_id(self.cache) &&
if !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did) { !imp.for_.is_assoc_ty() && !self.should_keep_impl(&i, did)
debug!("ImplStripper: impl item for stripped type; removing"); {
return None; debug!("ImplStripper: impl item for stripped type; removing");
} return None;
} }
if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) { if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id()) &&
if !self.should_keep_impl(&i, did) { !self.should_keep_impl(&i, did) {
debug!("ImplStripper: impl item for stripped trait; removing"); debug!("ImplStripper: impl item for stripped trait; removing");
return None; return None;
}
} }
if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
for typaram in generics { for typaram in generics {
if let Some(did) = typaram.def_id(self.cache) { if let Some(did) = typaram.def_id(self.cache) && !self.should_keep_impl(&i, did)
if !self.should_keep_impl(&i, did) { {
debug!( debug!(
"ImplStripper: stripped item in trait's generics; removing impl" "ImplStripper: stripped item in trait's generics; removing impl"
); );
return None; return None;
}
} }
} }
} }

View file

@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
let ty = hir_ty_to_ty(cx.tcx, hir_ty); let ty = hir_ty_to_ty(cx.tcx, hir_ty);
if let ty::Array(element_type, cst) = ty.kind(); if let ty::Array(element_type, cst) = ty.kind();
if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind(); if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx); if let Ok(element_count) = element_count.try_to_target_usize(cx.tcx);
if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()); if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size); if self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size);

View file

@ -41,7 +41,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
if let ExprKind::Repeat(_, _) = expr.kind if let ExprKind::Repeat(_, _) = expr.kind
&& let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind() && let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind()
&& let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind() && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind()
&& let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx) && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& !cx.tcx.hir().parent_iter(expr.hir_id) && !cx.tcx.hir().parent_iter(expr.hir_id)
.any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. }))) .any(|(_, node)| matches!(node, Node::Item(Item { kind: ItemKind::Static(..), .. })))

View file

@ -640,7 +640,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
}, },
mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() {
ty::Array(sub_type, len) => match sub_type.kind() { ty::Array(sub_type, len) => match sub_type.kind() {
ty::Float(FloatTy::F32) => match len.kind().try_to_machine_usize(tcx) { ty::Float(FloatTy::F32) => match len.kind().try_to_target_usize(tcx) {
Some(len) => alloc Some(len) => alloc
.inner() .inner()
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap())) .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * usize::try_from(len).unwrap()))
@ -651,7 +651,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -
.map(Constant::Vec), .map(Constant::Vec),
_ => None, _ => None,
}, },
ty::Float(FloatTy::F64) => match len.kind().try_to_machine_usize(tcx) { ty::Float(FloatTy::F64) => match len.kind().try_to_target_usize(tcx) {
Some(len) => alloc Some(len) => alloc
.inner() .inner()
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap())) .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * usize::try_from(len).unwrap()))

View file

@ -718,7 +718,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
throw_ub!(PointerOutOfBounds { throw_ub!(PointerOutOfBounds {
alloc_id, alloc_id,
alloc_size, alloc_size,
ptr_offset: this.machine_usize_to_isize(base_offset.bytes()), ptr_offset: this.target_usize_to_isize(base_offset.bytes()),
ptr_size: size, ptr_size: size,
msg: CheckInAllocMsg::InboundsTest msg: CheckInAllocMsg::InboundsTest
}); });

View file

@ -236,7 +236,7 @@ impl MainThreadState {
this.machine.main_fn_ret_place.unwrap().ptr, this.machine.main_fn_ret_place.unwrap().ptr,
this.machine.layouts.isize, this.machine.layouts.isize,
); );
let exit_code = this.read_machine_isize(&ret_place.into())?; let exit_code = this.read_target_isize(&ret_place.into())?;
// Need to call this ourselves since we are not going to return to the scheduler // Need to call this ourselves since we are not going to return to the scheduler
// loop, and we want the main thread TLS to not show up as memory leaks. // loop, and we want the main thread TLS to not show up as memory leaks.
this.terminate_active_thread()?; this.terminate_active_thread()?;
@ -287,7 +287,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
// First argument is constructed later, because it's skipped if the entry function uses #[start]. // First argument is constructed later, because it's skipped if the entry function uses #[start].
// Second argument (argc): length of `config.args`. // Second argument (argc): length of `config.args`.
let argc = Scalar::from_machine_usize(u64::try_from(config.args.len()).unwrap(), &ecx); let argc = Scalar::from_target_usize(u64::try_from(config.args.len()).unwrap(), &ecx);
// Third argument (`argv`): created from `config.args`. // Third argument (`argv`): created from `config.args`.
let argv = { let argv = {
// Put each argument in memory, collect pointers. // Put each argument in memory, collect pointers.

View file

@ -758,10 +758,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let seconds_place = this.mplace_field(tp, 0)?; let seconds_place = this.mplace_field(tp, 0)?;
let seconds_scalar = this.read_scalar(&seconds_place.into())?; let seconds_scalar = this.read_scalar(&seconds_place.into())?;
let seconds = seconds_scalar.to_machine_isize(this)?; let seconds = seconds_scalar.to_target_isize(this)?;
let nanoseconds_place = this.mplace_field(tp, 1)?; let nanoseconds_place = this.mplace_field(tp, 1)?;
let nanoseconds_scalar = this.read_scalar(&nanoseconds_place.into())?; let nanoseconds_scalar = this.read_scalar(&nanoseconds_place.into())?;
let nanoseconds = nanoseconds_scalar.to_machine_isize(this)?; let nanoseconds = nanoseconds_scalar.to_target_isize(this)?;
Ok(try { Ok(try {
// tv_sec must be non-negative. // tv_sec must be non-negative.

View file

@ -207,7 +207,7 @@ impl<'mir, 'tcx> GlobalStateInner {
.checked_add(max(size.bytes(), 1)) .checked_add(max(size.bytes(), 1))
.ok_or_else(|| err_exhaust!(AddressSpaceFull))?; .ok_or_else(|| err_exhaust!(AddressSpaceFull))?;
// Even if `Size` didn't overflow, we might still have filled up the address space. // Even if `Size` didn't overflow, we might still have filled up the address space.
if global_state.next_base_addr > ecx.machine_usize_max() { if global_state.next_base_addr > ecx.target_usize_max() {
throw_exhaust!(AddressSpaceFull); throw_exhaust!(AddressSpaceFull);
} }
// Given that `next_base_addr` increases in each allocation, pushing the // Given that `next_base_addr` increases in each allocation, pushing the

View file

@ -56,7 +56,7 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> {
Offset => { Offset => {
assert!(left.layout.ty.is_unsafe_ptr()); assert!(left.layout.ty.is_unsafe_ptr());
let ptr = left.to_scalar().to_pointer(self)?; let ptr = left.to_scalar().to_pointer(self)?;
let offset = right.to_scalar().to_machine_isize(self)?; let offset = right.to_scalar().to_target_isize(self)?;
let pointee_ty = let pointee_ty =
left.layout.ty.builtin_deref(true).expect("Offset called on non-ptr type").ty; left.layout.ty.builtin_deref(true).expect("Offset called on non-ptr type").ty;
@ -73,14 +73,14 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriInterpCx<'mir, 'tcx> {
// We do the actual operation with usize-typed scalars. // We do the actual operation with usize-typed scalars.
let left = ImmTy::from_uint(ptr.addr().bytes(), self.machine.layouts.usize); let left = ImmTy::from_uint(ptr.addr().bytes(), self.machine.layouts.usize);
let right = ImmTy::from_uint( let right = ImmTy::from_uint(
right.to_scalar().to_machine_usize(self)?, right.to_scalar().to_target_usize(self)?,
self.machine.layouts.usize, self.machine.layouts.usize,
); );
let (result, overflowing, _ty) = let (result, overflowing, _ty) =
self.overflowing_binary_op(bin_op, &left, &right)?; self.overflowing_binary_op(bin_op, &left, &right)?;
// Construct a new pointer with the provenance of `ptr` (the LHS). // Construct a new pointer with the provenance of `ptr` (the LHS).
let result_ptr = let result_ptr =
Pointer::new(ptr.provenance, Size::from_bytes(result.to_machine_usize(self)?)); Pointer::new(ptr.provenance, Size::from_bytes(result.to_target_usize(self)?));
(Scalar::from_maybe_pointer(result_ptr, self), overflowing, left.layout.ty) (Scalar::from_maybe_pointer(result_ptr, self), overflowing, left.layout.ty)
} }

View file

@ -24,7 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let frame_count = this.active_thread_stack().len(); let frame_count = this.active_thread_stack().len();
this.write_scalar(Scalar::from_machine_usize(frame_count.try_into().unwrap(), this), dest) this.write_scalar(Scalar::from_target_usize(frame_count.try_into().unwrap(), this), dest)
} }
fn handle_miri_get_backtrace( fn handle_miri_get_backtrace(
@ -205,11 +205,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
1 => { 1 => {
this.write_scalar( this.write_scalar(
Scalar::from_machine_usize(name.len().try_into().unwrap(), this), Scalar::from_target_usize(name.len().try_into().unwrap(), this),
&this.mplace_field(&dest, 0)?.into(), &this.mplace_field(&dest, 0)?.into(),
)?; )?;
this.write_scalar( this.write_scalar(
Scalar::from_machine_usize(filename.len().try_into().unwrap(), this), Scalar::from_target_usize(filename.len().try_into().unwrap(), this),
&this.mplace_field(&dest, 1)?.into(), &this.mplace_field(&dest, 1)?.into(),
)?; )?;
} }

View file

@ -323,7 +323,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.assert_target_os_is_unix("getcwd"); this.assert_target_os_is_unix("getcwd");
let buf = this.read_pointer(buf_op)?; let buf = this.read_pointer(buf_op)?;
let size = this.read_machine_usize(size_op)?; let size = this.read_target_usize(size_op)?;
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`getcwd`", reject_with)?; this.reject_in_isolation("`getcwd`", reject_with)?;

View file

@ -36,7 +36,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
ty::Int(IntTy::Isize) => { ty::Int(IntTy::Isize) => {
// This will fail if host != target, but then the entire FFI thing probably won't work well // This will fail if host != target, but then the entire FFI thing probably won't work well
// in that situation. // in that situation.
return Ok(CArg::ISize(k.to_machine_isize(cx)?.try_into().unwrap())); return Ok(CArg::ISize(k.to_target_isize(cx)?.try_into().unwrap()));
} }
// the uints // the uints
ty::Uint(UintTy::U8) => { ty::Uint(UintTy::U8) => {
@ -54,7 +54,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
ty::Uint(UintTy::Usize) => { ty::Uint(UintTy::Usize) => {
// This will fail if host != target, but then the entire FFI thing probably won't work well // This will fail if host != target, but then the entire FFI thing probably won't work well
// in that situation. // in that situation.
return Ok(CArg::USize(k.to_machine_usize(cx)?.try_into().unwrap())); return Ok(CArg::USize(k.to_target_usize(cx)?.try_into().unwrap()));
} }
_ => {} _ => {}
} }

View file

@ -449,7 +449,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [ptr, out, out_size] = this.check_shim(abi, Abi::Rust, link_name, args)?; let [ptr, out, out_size] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let out = this.read_pointer(out)?; let out = this.read_pointer(out)?;
let out_size = this.read_scalar(out_size)?.to_machine_usize(this)?; let out_size = this.read_scalar(out_size)?.to_target_usize(this)?;
// The host affects program behavior here, so this requires isolation to be disabled. // The host affects program behavior here, so this requires isolation to be disabled.
this.check_no_isolation("`miri_host_to_target_path`")?; this.check_no_isolation("`miri_host_to_target_path`")?;
@ -490,7 +490,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [bytes] = this.check_shim(abi, Abi::Rust, link_name, args)?; let [bytes] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let (ptr, len) = this.read_immediate(bytes)?.to_scalar_pair(); let (ptr, len) = this.read_immediate(bytes)?.to_scalar_pair();
let ptr = ptr.to_pointer(this)?; let ptr = ptr.to_pointer(this)?;
let len = len.to_machine_usize(this)?; let len = len.to_target_usize(this)?;
let msg = this.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?; let msg = this.read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(len))?;
// Note: we're ignoring errors writing to host stdout/stderr. // Note: we're ignoring errors writing to host stdout/stderr.
@ -504,15 +504,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Standard C allocation // Standard C allocation
"malloc" => { "malloc" => {
let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let size = this.read_machine_usize(size)?; let size = this.read_target_usize(size)?;
let res = this.malloc(size, /*zero_init:*/ false, MiriMemoryKind::C)?; let res = this.malloc(size, /*zero_init:*/ false, MiriMemoryKind::C)?;
this.write_pointer(res, dest)?; this.write_pointer(res, dest)?;
} }
"calloc" => { "calloc" => {
let [items, len] = let [items, len] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let items = this.read_machine_usize(items)?; let items = this.read_target_usize(items)?;
let len = this.read_machine_usize(len)?; let len = this.read_target_usize(len)?;
let size = items let size = items
.checked_mul(len) .checked_mul(len)
.ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?; .ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?;
@ -528,7 +528,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [old_ptr, new_size] = let [old_ptr, new_size] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let old_ptr = this.read_pointer(old_ptr)?; let old_ptr = this.read_pointer(old_ptr)?;
let new_size = this.read_machine_usize(new_size)?; let new_size = this.read_target_usize(new_size)?;
let res = this.realloc(old_ptr, new_size, MiriMemoryKind::C)?; let res = this.realloc(old_ptr, new_size, MiriMemoryKind::C)?;
this.write_pointer(res, dest)?; this.write_pointer(res, dest)?;
} }
@ -536,8 +536,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Rust allocation // Rust allocation
"__rust_alloc" | "miri_alloc" => { "__rust_alloc" | "miri_alloc" => {
let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let size = this.read_machine_usize(size)?; let size = this.read_target_usize(size)?;
let align = this.read_machine_usize(align)?; let align = this.read_target_usize(align)?;
let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
Self::check_alloc_request(size, align)?; Self::check_alloc_request(size, align)?;
@ -569,8 +569,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
"__rust_alloc_zeroed" => { "__rust_alloc_zeroed" => {
let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let [size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let size = this.read_machine_usize(size)?; let size = this.read_target_usize(size)?;
let align = this.read_machine_usize(align)?; let align = this.read_target_usize(align)?;
return this.emulate_allocator(Symbol::intern("__rg_alloc_zeroed"), |this| { return this.emulate_allocator(Symbol::intern("__rg_alloc_zeroed"), |this| {
Self::check_alloc_request(size, align)?; Self::check_alloc_request(size, align)?;
@ -593,8 +593,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"__rust_dealloc" | "miri_dealloc" => { "__rust_dealloc" | "miri_dealloc" => {
let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?; let [ptr, old_size, align] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let old_size = this.read_machine_usize(old_size)?; let old_size = this.read_target_usize(old_size)?;
let align = this.read_machine_usize(align)?; let align = this.read_target_usize(align)?;
let default = |this: &mut MiriInterpCx<'mir, 'tcx>| { let default = |this: &mut MiriInterpCx<'mir, 'tcx>| {
let memory_kind = match link_name.as_str() { let memory_kind = match link_name.as_str() {
@ -625,9 +625,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [ptr, old_size, align, new_size] = let [ptr, old_size, align, new_size] =
this.check_shim(abi, Abi::Rust, link_name, args)?; this.check_shim(abi, Abi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let old_size = this.read_machine_usize(old_size)?; let old_size = this.read_target_usize(old_size)?;
let align = this.read_machine_usize(align)?; let align = this.read_target_usize(align)?;
let new_size = this.read_machine_usize(new_size)?; let new_size = this.read_target_usize(new_size)?;
// No need to check old_size; we anyway check that they match the allocation. // No need to check old_size; we anyway check that they match the allocation.
return this.emulate_allocator(Symbol::intern("__rg_realloc"), |this| { return this.emulate_allocator(Symbol::intern("__rg_realloc"), |this| {
@ -651,7 +651,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let left = this.read_pointer(left)?; let left = this.read_pointer(left)?;
let right = this.read_pointer(right)?; let right = this.read_pointer(right)?;
let n = Size::from_bytes(this.read_machine_usize(n)?); let n = Size::from_bytes(this.read_target_usize(n)?);
let result = { let result = {
let left_bytes = this.read_bytes_ptr_strip_provenance(left, n)?; let left_bytes = this.read_bytes_ptr_strip_provenance(left, n)?;
@ -672,7 +672,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let val = this.read_scalar(val)?.to_i32()?; let val = this.read_scalar(val)?.to_i32()?;
let num = this.read_machine_usize(num)?; let num = this.read_target_usize(num)?;
// The docs say val is "interpreted as unsigned char". // The docs say val is "interpreted as unsigned char".
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
let val = val as u8; let val = val as u8;
@ -696,7 +696,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let val = this.read_scalar(val)?.to_i32()?; let val = this.read_scalar(val)?.to_i32()?;
let num = this.read_machine_usize(num)?; let num = this.read_target_usize(num)?;
// The docs say val is "interpreted as unsigned char". // The docs say val is "interpreted as unsigned char".
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)] #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
let val = val as u8; let val = val as u8;
@ -717,7 +717,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let n = this.read_c_str(ptr)?.len(); let n = this.read_c_str(ptr)?.len();
this.write_scalar( this.write_scalar(
Scalar::from_machine_usize(u64::try_from(n).unwrap(), this), Scalar::from_target_usize(u64::try_from(n).unwrap(), this),
dest, dest,
)?; )?;
} }

View file

@ -111,8 +111,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let ty_layout = this.layout_of(ty)?; let ty_layout = this.layout_of(ty)?;
let val_byte = this.read_scalar(val_byte)?.to_u8()?; let val_byte = this.read_scalar(val_byte)?.to_u8()?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let count = this.read_machine_usize(count)?; let count = this.read_target_usize(count)?;
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max), // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
// but no actual allocation can be big enough for the difference to be noticeable. // but no actual allocation can be big enough for the difference to be noticeable.
let byte_count = ty_layout.size.checked_mul(count, this).ok_or_else(|| { let byte_count = ty_layout.size.checked_mul(count, this).ok_or_else(|| {
err_ub_format!("overflow computing total size of `{intrinsic_name}`") err_ub_format!("overflow computing total size of `{intrinsic_name}`")
@ -124,7 +124,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [ptr, mask] = check_arg_count(args)?; let [ptr, mask] = check_arg_count(args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let mask = this.read_machine_usize(mask)?; let mask = this.read_target_usize(mask)?;
let masked_addr = Size::from_bytes(ptr.addr().bytes() & mask); let masked_addr = Size::from_bytes(ptr.addr().bytes() & mask);

View file

@ -202,7 +202,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
Op::WrappingOffset => { Op::WrappingOffset => {
let ptr = left.to_scalar().to_pointer(this)?; let ptr = left.to_scalar().to_pointer(this)?;
let offset_count = right.to_scalar().to_machine_isize(this)?; let offset_count = right.to_scalar().to_target_isize(this)?;
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty; let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
let pointee_size = i64::try_from(this.layout_of(pointee_ty)?.size.bytes()).unwrap(); let pointee_size = i64::try_from(this.layout_of(pointee_ty)?.size.bytes()).unwrap();

View file

@ -80,7 +80,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
return Ok(false); return Ok(false);
} }
let req_align = this.read_machine_usize(align_op)?; let req_align = this.read_target_usize(align_op)?;
// Stop if the alignment is not a power of two. // Stop if the alignment is not a power of two.
if !req_align.is_power_of_two() { if !req_align.is_power_of_two() {
@ -106,7 +106,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
// Return error result (usize::MAX), and jump to caller. // Return error result (usize::MAX), and jump to caller.
this.write_scalar(Scalar::from_machine_usize(this.machine_usize_max(), this), dest)?; this.write_scalar(Scalar::from_target_usize(this.target_usize_max(), this), dest)?;
this.go_to_block(ret); this.go_to_block(ret);
Ok(true) Ok(true)
} }

View file

@ -108,7 +108,7 @@ impl<'tcx> TlsData<'tcx> {
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
match self.keys.get_mut(&key) { match self.keys.get_mut(&key) {
Some(TlsEntry { data, .. }) => { Some(TlsEntry { data, .. }) => {
if new_data.to_machine_usize(cx)? != 0 { if new_data.to_target_usize(cx)? != 0 {
trace!("TLS key {} for thread {:?} stored: {:?}", key, thread_id, new_data); trace!("TLS key {} for thread {:?} stored: {:?}", key, thread_id, new_data);
data.insert(thread_id, new_data); data.insert(thread_id, new_data);
} else { } else {
@ -356,7 +356,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
state.last_key = Some(key); state.last_key = Some(key);
trace!("Running TLS dtor {:?} on {:?} at {:?}", instance, ptr, active_thread); trace!("Running TLS dtor {:?} on {:?} at {:?}", instance, ptr, active_thread);
assert!( assert!(
!ptr.to_machine_usize(this).unwrap() != 0, !ptr.to_target_usize(this).unwrap() != 0,
"data can't be NULL when dtor is called!" "data can't be NULL when dtor is called!"
); );

View file

@ -78,19 +78,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [fd, buf, count] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [fd, buf, count] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let count = this.read_machine_usize(count)?; let count = this.read_target_usize(count)?;
let result = this.read(fd, buf, count)?; let result = this.read(fd, buf, count)?;
this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
} }
"write" => { "write" => {
let [fd, buf, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [fd, buf, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let count = this.read_machine_usize(n)?; let count = this.read_target_usize(n)?;
trace!("Called write({:?}, {:?}, {:?})", fd, buf, count); trace!("Called write({:?}, {:?}, {:?})", fd, buf, count);
let result = this.write(fd, buf, count)?; let result = this.write(fd, buf, count)?;
// Now, `result` is the value we return back to the program. // Now, `result` is the value we return back to the program.
this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
} }
"unlink" => { "unlink" => {
let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@ -151,14 +151,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"readlink" => { "readlink" => {
let [pathname, buf, bufsize] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [pathname, buf, bufsize] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let result = this.readlink(pathname, buf, bufsize)?; let result = this.readlink(pathname, buf, bufsize)?;
this.write_scalar(Scalar::from_machine_isize(result, this), dest)?; this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
} }
"posix_fadvise" => { "posix_fadvise" => {
let [fd, offset, len, advice] = let [fd, offset, len, advice] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
this.read_scalar(fd)?.to_i32()?; this.read_scalar(fd)?.to_i32()?;
this.read_machine_isize(offset)?; this.read_target_isize(offset)?;
this.read_machine_isize(len)?; this.read_target_isize(len)?;
this.read_scalar(advice)?.to_i32()?; this.read_scalar(advice)?.to_i32()?;
// fadvise is only informational, we can ignore it. // fadvise is only informational, we can ignore it.
this.write_null(dest)?; this.write_null(dest)?;
@ -191,8 +191,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"posix_memalign" => { "posix_memalign" => {
let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let ret = this.deref_operand(ret)?; let ret = this.deref_operand(ret)?;
let align = this.read_machine_usize(align)?; let align = this.read_target_usize(align)?;
let size = this.read_machine_usize(size)?; let size = this.read_target_usize(size)?;
// Align must be power of 2, and also at least ptr-sized (POSIX rules). // Align must be power of 2, and also at least ptr-sized (POSIX rules).
// But failure to adhere to this is not UB, it's an error condition. // But failure to adhere to this is not UB, it's an error condition.
if !align.is_power_of_two() || align < this.pointer_size().bytes() { if !align.is_power_of_two() || align < this.pointer_size().bytes() {
@ -216,7 +216,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Dynamic symbol loading // Dynamic symbol loading
"dlsym" => { "dlsym" => {
let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [handle, symbol] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
this.read_machine_usize(handle)?; this.read_target_usize(handle)?;
let symbol = this.read_pointer(symbol)?; let symbol = this.read_pointer(symbol)?;
let symbol_name = this.read_c_str(symbol)?; let symbol_name = this.read_c_str(symbol)?;
if let Some(dlsym) = Dlsym::from_str(symbol_name, &this.tcx.sess.target.os)? { if let Some(dlsym) = Dlsym::from_str(symbol_name, &this.tcx.sess.target.os)? {
@ -472,7 +472,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [errnum, buf, buflen] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [errnum, buf, buflen] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let errnum = this.read_scalar(errnum)?; let errnum = this.read_scalar(errnum)?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let buflen = this.read_machine_usize(buflen)?; let buflen = this.read_target_usize(buflen)?;
let error = this.try_errnum_to_io_error(errnum)?; let error = this.try_errnum_to_io_error(errnum)?;
let formatted = match error { let formatted = match error {
@ -565,7 +565,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let uid = this.read_scalar(uid)?.to_u32()?; let uid = this.read_scalar(uid)?.to_u32()?;
let pwd = this.deref_operand(pwd)?; let pwd = this.deref_operand(pwd)?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let buflen = this.read_machine_usize(buflen)?; let buflen = this.read_target_usize(buflen)?;
let result = this.deref_operand(result)?; let result = this.deref_operand(result)?;
// Must be for "us". // Must be for "us".

View file

@ -754,7 +754,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// We cap the number of read bytes to the largest value that we are able to fit in both the // We cap the number of read bytes to the largest value that we are able to fit in both the
// host's and target's `isize`. This saves us from having to handle overflows later. // host's and target's `isize`. This saves us from having to handle overflows later.
let count = count let count = count
.min(u64::try_from(this.machine_isize_max()).unwrap()) .min(u64::try_from(this.target_isize_max()).unwrap())
.min(u64::try_from(isize::MAX).unwrap()); .min(u64::try_from(isize::MAX).unwrap());
let communicate = this.machine.communicate(); let communicate = this.machine.communicate();
@ -807,7 +807,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// We cap the number of written bytes to the largest value that we are able to fit in both the // We cap the number of written bytes to the largest value that we are able to fit in both the
// host's and target's `isize`. This saves us from having to handle overflows later. // host's and target's `isize`. This saves us from having to handle overflows later.
let count = count let count = count
.min(u64::try_from(this.machine_isize_max()).unwrap()) .min(u64::try_from(this.target_isize_max()).unwrap())
.min(u64::try_from(isize::MAX).unwrap()); .min(u64::try_from(isize::MAX).unwrap());
let communicate = this.machine.communicate(); let communicate = this.machine.communicate();
@ -1290,7 +1290,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// The libc API for opendir says that this method returns a pointer to an opaque // The libc API for opendir says that this method returns a pointer to an opaque
// structure, but we are returning an ID number. Thus, pass it as a scalar of // structure, but we are returning an ID number. Thus, pass it as a scalar of
// pointer width. // pointer width.
Ok(Scalar::from_machine_usize(id, this)) Ok(Scalar::from_target_usize(id, this))
} }
Err(e) => { Err(e) => {
this.set_last_error_from_io_error(e.kind())?; this.set_last_error_from_io_error(e.kind())?;
@ -1307,7 +1307,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.assert_target_os("linux", "readdir64"); this.assert_target_os("linux", "readdir64");
let dirp = this.read_machine_usize(dirp_op)?; let dirp = this.read_target_usize(dirp_op)?;
// Reject if isolation is enabled. // Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
@ -1399,7 +1399,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.assert_target_os("macos", "readdir_r"); this.assert_target_os("macos", "readdir_r");
let dirp = this.read_machine_usize(dirp_op)?; let dirp = this.read_target_usize(dirp_op)?;
// Reject if isolation is enabled. // Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
@ -1492,7 +1492,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn closedir(&mut self, dirp_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> { fn closedir(&mut self, dirp_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let dirp = this.read_machine_usize(dirp_op)?; let dirp = this.read_target_usize(dirp_op)?;
// Reject if isolation is enabled. // Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
@ -1656,7 +1656,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let pathname = this.read_path_from_c_str(this.read_pointer(pathname_op)?)?; let pathname = this.read_path_from_c_str(this.read_pointer(pathname_op)?)?;
let buf = this.read_pointer(buf_op)?; let buf = this.read_pointer(buf_op)?;
let bufsize = this.read_machine_usize(bufsize_op)?; let bufsize = this.read_target_usize(bufsize_op)?;
// Reject if isolation is enabled. // Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
@ -1727,7 +1727,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.reject_in_isolation("`realpath`", reject_with)?; this.reject_in_isolation("`realpath`", reject_with)?;
let eacc = this.eval_libc("EACCES"); let eacc = this.eval_libc("EACCES");
this.set_last_error(eacc)?; this.set_last_error(eacc)?;
return Ok(Scalar::from_machine_usize(0, this)); return Ok(Scalar::from_target_usize(0, this));
} }
let result = std::fs::canonicalize(pathname); let result = std::fs::canonicalize(pathname);
@ -1758,7 +1758,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// seems like a bit of a mess anyway: <https://eklitzke.org/path-max-is-tricky>. // seems like a bit of a mess anyway: <https://eklitzke.org/path-max-is-tricky>.
let enametoolong = this.eval_libc("ENAMETOOLONG"); let enametoolong = this.eval_libc("ENAMETOOLONG");
this.set_last_error(enametoolong)?; this.set_last_error(enametoolong)?;
return Ok(Scalar::from_machine_usize(0, this)); return Ok(Scalar::from_target_usize(0, this));
} }
processed_ptr processed_ptr
}; };
@ -1767,7 +1767,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
Err(e) => { Err(e) => {
this.set_last_error_from_io_error(e.kind())?; this.set_last_error_from_io_error(e.kind())?;
Ok(Scalar::from_machine_usize(0, this)) Ok(Scalar::from_target_usize(0, this))
} }
} }
} }

View file

@ -119,18 +119,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// argument, we have to also check all arguments *before* it to ensure that they // argument, we have to also check all arguments *before* it to ensure that they
// have the right type. // have the right type.
let sys_getrandom = this.eval_libc("SYS_getrandom").to_machine_usize(this)?; let sys_getrandom = this.eval_libc("SYS_getrandom").to_target_usize(this)?;
let sys_statx = this.eval_libc("SYS_statx").to_machine_usize(this)?; let sys_statx = this.eval_libc("SYS_statx").to_target_usize(this)?;
let sys_futex = this.eval_libc("SYS_futex").to_machine_usize(this)?; let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?;
if args.is_empty() { if args.is_empty() {
throw_ub_format!( throw_ub_format!(
"incorrect number of arguments for syscall: got 0, expected at least 1" "incorrect number of arguments for syscall: got 0, expected at least 1"
); );
} }
match this.read_machine_usize(&args[0])? { match this.read_target_usize(&args[0])? {
// `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)` // `libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)`
// is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>). // is called if a `HashMap` is created the regular way (e.g. HashMap<K, V>).
id if id == sys_getrandom => { id if id == sys_getrandom => {
@ -155,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
let result = let result =
this.linux_statx(&args[1], &args[2], &args[3], &args[4], &args[5])?; this.linux_statx(&args[1], &args[2], &args[3], &args[4], &args[5])?;
this.write_scalar(Scalar::from_machine_isize(result.into(), this), dest)?; this.write_scalar(Scalar::from_target_isize(result.into(), this), dest)?;
} }
// `futex` is used by some synchonization primitives. // `futex` is used by some synchonization primitives.
id if id == sys_futex => { id if id == sys_futex => {
@ -178,7 +178,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [pid, cpusetsize, mask] = let [pid, cpusetsize, mask] =
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
this.read_scalar(pid)?.to_i32()?; this.read_scalar(pid)?.to_i32()?;
this.read_machine_usize(cpusetsize)?; this.read_target_usize(cpusetsize)?;
this.deref_operand(mask)?; this.deref_operand(mask)?;
// FIXME: we just return an error; `num_cpus` then falls back to `sysconf`. // FIXME: we just return an error; `num_cpus` then falls back to `sysconf`.
let einval = this.eval_libc("EINVAL"); let einval = this.eval_libc("EINVAL");
@ -210,7 +210,7 @@ fn getrandom<'tcx>(
dest: &PlaceTy<'tcx, Provenance>, dest: &PlaceTy<'tcx, Provenance>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let len = this.read_machine_usize(len)?; let len = this.read_target_usize(len)?;
// The only supported flags are GRND_RANDOM and GRND_NONBLOCK, // The only supported flags are GRND_RANDOM and GRND_NONBLOCK,
// neither of which have any effect on our current PRNG. // neither of which have any effect on our current PRNG.
@ -218,6 +218,6 @@ fn getrandom<'tcx>(
let _flags = this.read_scalar(flags)?.to_i32(); let _flags = this.read_scalar(flags)?.to_i32();
this.gen_random(ptr, len)?; this.gen_random(ptr, len)?;
this.write_scalar(Scalar::from_machine_usize(len, this), dest)?; this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
Ok(()) Ok(())
} }

View file

@ -81,7 +81,7 @@ pub fn futex<'tcx>(
if bitset == 0 { if bitset == 0 {
let einval = this.eval_libc("EINVAL"); let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?; this.set_last_error(einval)?;
this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?; this.write_scalar(Scalar::from_target_isize(-1, this), dest)?;
return Ok(()); return Ok(());
} }
@ -101,7 +101,7 @@ pub fn futex<'tcx>(
None => { None => {
let einval = this.eval_libc("EINVAL"); let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?; this.set_last_error(einval)?;
this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?; this.write_scalar(Scalar::from_target_isize(-1, this), dest)?;
return Ok(()); return Ok(());
} }
}; };
@ -173,7 +173,7 @@ pub fn futex<'tcx>(
this.block_thread(thread); this.block_thread(thread);
this.futex_wait(addr_usize, thread, bitset); this.futex_wait(addr_usize, thread, bitset);
// Succesfully waking up from FUTEX_WAIT always returns zero. // Succesfully waking up from FUTEX_WAIT always returns zero.
this.write_scalar(Scalar::from_machine_isize(0, this), dest)?; this.write_scalar(Scalar::from_target_isize(0, this), dest)?;
// Register a timeout callback if a timeout was specified. // Register a timeout callback if a timeout was specified.
// This callback will override the return value when the timeout triggers. // This callback will override the return value when the timeout triggers.
if let Some(timeout_time) = timeout_time { if let Some(timeout_time) = timeout_time {
@ -196,7 +196,7 @@ pub fn futex<'tcx>(
this.futex_remove_waiter(self.addr_usize, self.thread); this.futex_remove_waiter(self.addr_usize, self.thread);
let etimedout = this.eval_libc("ETIMEDOUT"); let etimedout = this.eval_libc("ETIMEDOUT");
this.set_last_error(etimedout)?; this.set_last_error(etimedout)?;
this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?; this.write_scalar(Scalar::from_target_isize(-1, this), &self.dest)?;
Ok(()) Ok(())
} }
@ -213,7 +213,7 @@ pub fn futex<'tcx>(
// right away without sleeping: -1 and errno set to EAGAIN. // right away without sleeping: -1 and errno set to EAGAIN.
let eagain = this.eval_libc("EAGAIN"); let eagain = this.eval_libc("EAGAIN");
this.set_last_error(eagain)?; this.set_last_error(eagain)?;
this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?; this.write_scalar(Scalar::from_target_isize(-1, this), dest)?;
} }
} }
// FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val) // FUTEX_WAKE: (int *addr, int op = FUTEX_WAKE, int val)
@ -239,7 +239,7 @@ pub fn futex<'tcx>(
if bitset == 0 { if bitset == 0 {
let einval = this.eval_libc("EINVAL"); let einval = this.eval_libc("EINVAL");
this.set_last_error(einval)?; this.set_last_error(einval)?;
this.write_scalar(Scalar::from_machine_isize(-1, this), dest)?; this.write_scalar(Scalar::from_target_isize(-1, this), dest)?;
return Ok(()); return Ok(());
} }
// Together with the SeqCst fence in futex_wait, this makes sure that futex_wait // Together with the SeqCst fence in futex_wait, this makes sure that futex_wait
@ -257,7 +257,7 @@ pub fn futex<'tcx>(
break; break;
} }
} }
this.write_scalar(Scalar::from_machine_isize(n, this), dest)?; this.write_scalar(Scalar::from_target_isize(n, this), dest)?;
} }
op => throw_unsup_format!("Miri does not support `futex` syscall with op={}", op), op => throw_unsup_format!("Miri does not support `futex` syscall with op={}", op),
} }

View file

@ -39,7 +39,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
Dlsym::getentropy => { Dlsym::getentropy => {
let [ptr, len] = check_arg_count(args)?; let [ptr, len] = check_arg_count(args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let len = this.read_machine_usize(len)?; let len = this.read_target_usize(len)?;
this.gen_random(ptr, len)?; this.gen_random(ptr, len)?;
this.write_null(dest)?; this.write_null(dest)?;
} }

View file

@ -161,13 +161,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// Querying system information // Querying system information
"pthread_get_stackaddr_np" => { "pthread_get_stackaddr_np" => {
let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
this.read_machine_usize(thread)?; this.read_target_usize(thread)?;
let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size()); let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size());
this.write_scalar(stack_addr, dest)?; this.write_scalar(stack_addr, dest)?;
} }
"pthread_get_stacksize_np" => { "pthread_get_stacksize_np" => {
let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [thread] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
this.read_machine_usize(thread)?; this.read_target_usize(thread)?;
let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size()); let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size());
this.write_scalar(stack_size, dest)?; this.write_scalar(stack_size, dest)?;
} }
@ -176,7 +176,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"pthread_setname_np" => { "pthread_setname_np" => {
let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let thread = this.pthread_self()?; let thread = this.pthread_self()?;
let max_len = this.eval_libc("MAXTHREADNAMESIZE").to_machine_usize(this)?; let max_len = this.eval_libc("MAXTHREADNAMESIZE").to_target_usize(this)?;
let res = this.pthread_setname_np( let res = this.pthread_setname_np(
thread, thread,
this.read_scalar(name)?, this.read_scalar(name)?,

View file

@ -42,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
throw_unsup_format!("Miri supports pthread_join only with retval==NULL"); throw_unsup_format!("Miri supports pthread_join only with retval==NULL");
} }
let thread_id = this.read_machine_usize(thread)?; let thread_id = this.read_target_usize(thread)?;
this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?; this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?;
Ok(0) Ok(0)
@ -51,7 +51,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
fn pthread_detach(&mut self, thread: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> { fn pthread_detach(&mut self, thread: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let thread_id = this.read_machine_usize(thread)?; let thread_id = this.read_target_usize(thread)?;
this.detach_thread( this.detach_thread(
thread_id.try_into().expect("thread ID should fit in u32"), thread_id.try_into().expect("thread ID should fit in u32"),
/*allow_terminated_joined*/ false, /*allow_terminated_joined*/ false,
@ -64,7 +64,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let thread_id = this.get_active_thread(); let thread_id = this.get_active_thread();
Ok(Scalar::from_machine_usize(thread_id.into(), this)) Ok(Scalar::from_target_usize(thread_id.into(), this))
} }
/// Set the name of the current thread. `max_name_len` is the maximal length of the name /// Set the name of the current thread. `max_name_len` is the maximal length of the name
@ -77,7 +77,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, Scalar<Provenance>> { ) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let thread = ThreadId::try_from(thread.to_machine_usize(this)?).unwrap(); let thread = ThreadId::try_from(thread.to_target_usize(this)?).unwrap();
let name = name.to_pointer(this)?; let name = name.to_pointer(this)?;
let name = this.read_c_str(name)?.to_owned(); let name = this.read_c_str(name)?.to_owned();
@ -100,9 +100,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
) -> InterpResult<'tcx, Scalar<Provenance>> { ) -> InterpResult<'tcx, Scalar<Provenance>> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let thread = ThreadId::try_from(thread.to_machine_usize(this)?).unwrap(); let thread = ThreadId::try_from(thread.to_target_usize(this)?).unwrap();
let name_out = name_out.to_pointer(this)?; let name_out = name_out.to_pointer(this)?;
let len = len.to_machine_usize(this)?; let len = len.to_target_usize(this)?;
let name = this.get_thread_name(thread).to_owned(); let name = this.get_thread_name(thread).to_owned();
let (success, _written) = this.write_c_str(&name, name_out, len)?; let (success, _written) = this.write_c_str(&name, name_out, len)?;

View file

@ -67,10 +67,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
byte_offset, byte_offset,
_key, _key,
] = check_arg_count(args)?; ] = check_arg_count(args)?;
let handle = this.read_machine_isize(handle)?; let handle = this.read_target_isize(handle)?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let n = this.read_scalar(n)?.to_u32()?; let n = this.read_scalar(n)?.to_u32()?;
let byte_offset = this.read_machine_usize(byte_offset)?; // is actually a pointer let byte_offset = this.read_target_usize(byte_offset)?; // is actually a pointer
let io_status_block = this.deref_operand(io_status_block)?; let io_status_block = this.deref_operand(io_status_block)?;
if byte_offset != 0 { if byte_offset != 0 {
@ -104,7 +104,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let io_status_information = let io_status_information =
this.mplace_field_named(&io_status_block, "Information")?; this.mplace_field_named(&io_status_block, "Information")?;
this.write_scalar( this.write_scalar(
Scalar::from_machine_usize(n.into(), this), Scalar::from_target_usize(n.into(), this),
&io_status_information.into(), &io_status_information.into(),
)?; )?;
} }

View file

@ -73,9 +73,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"HeapAlloc" => { "HeapAlloc" => {
let [handle, flags, size] = let [handle, flags, size] =
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
this.read_machine_isize(handle)?; this.read_target_isize(handle)?;
let flags = this.read_scalar(flags)?.to_u32()?; let flags = this.read_scalar(flags)?.to_u32()?;
let size = this.read_machine_usize(size)?; let size = this.read_target_usize(size)?;
let heap_zero_memory = 0x00000008; // HEAP_ZERO_MEMORY let heap_zero_memory = 0x00000008; // HEAP_ZERO_MEMORY
let zero_init = (flags & heap_zero_memory) == heap_zero_memory; let zero_init = (flags & heap_zero_memory) == heap_zero_memory;
let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap)?; let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap)?;
@ -84,7 +84,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"HeapFree" => { "HeapFree" => {
let [handle, flags, ptr] = let [handle, flags, ptr] =
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
this.read_machine_isize(handle)?; this.read_target_isize(handle)?;
this.read_scalar(flags)?.to_u32()?; this.read_scalar(flags)?.to_u32()?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
this.free(ptr, MiriMemoryKind::WinHeap)?; this.free(ptr, MiriMemoryKind::WinHeap)?;
@ -93,10 +93,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"HeapReAlloc" => { "HeapReAlloc" => {
let [handle, flags, ptr, size] = let [handle, flags, ptr, size] =
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
this.read_machine_isize(handle)?; this.read_target_isize(handle)?;
this.read_scalar(flags)?.to_u32()?; this.read_scalar(flags)?.to_u32()?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let size = this.read_machine_usize(size)?; let size = this.read_target_usize(size)?;
let res = this.realloc(ptr, size, MiriMemoryKind::WinHeap)?; let res = this.realloc(ptr, size, MiriMemoryKind::WinHeap)?;
this.write_pointer(res, dest)?; this.write_pointer(res, dest)?;
} }
@ -299,7 +299,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [hModule, lpProcName] = let [hModule, lpProcName] =
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
this.read_machine_isize(hModule)?; this.read_target_isize(hModule)?;
let name = this.read_c_str(this.read_pointer(lpProcName)?)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?;
if let Some(dlsym) = Dlsym::from_str(name, &this.tcx.sess.target.os)? { if let Some(dlsym) = Dlsym::from_str(name, &this.tcx.sess.target.os)? {
let ptr = this.create_fn_alloc_ptr(FnVal::Other(dlsym)); let ptr = this.create_fn_alloc_ptr(FnVal::Other(dlsym));
@ -323,7 +323,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let [algorithm, ptr, len, flags] = let [algorithm, ptr, len, flags] =
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
let algorithm = this.read_scalar(algorithm)?; let algorithm = this.read_scalar(algorithm)?;
let algorithm = algorithm.to_machine_usize(this)?; let algorithm = algorithm.to_target_usize(this)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let len = this.read_scalar(len)?.to_u32()?; let len = this.read_scalar(len)?.to_u32()?;
let flags = this.read_scalar(flags)?.to_u32()?; let flags = this.read_scalar(flags)?.to_u32()?;
@ -357,7 +357,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// `term` needs this, so we fake it. // `term` needs this, so we fake it.
let [console, buffer_info] = let [console, buffer_info] =
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
this.read_machine_isize(console)?; this.read_target_isize(console)?;
this.deref_operand(buffer_info)?; this.deref_operand(buffer_info)?;
// Indicate an error. // Indicate an error.
// FIXME: we should set last_error, but to what? // FIXME: we should set last_error, but to what?
@ -371,7 +371,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// one it is. This is very fake, but libtest needs it so we cannot make it a // one it is. This is very fake, but libtest needs it so we cannot make it a
// std-only shim. // std-only shim.
// FIXME: this should return real HANDLEs when io support is added // FIXME: this should return real HANDLEs when io support is added
this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?; this.write_scalar(Scalar::from_target_isize(which.into(), this), dest)?;
} }
"CloseHandle" => { "CloseHandle" => {
let [handle] = let [handle] =
@ -386,7 +386,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
this.check_no_isolation("`GetModuleFileNameW`")?; this.check_no_isolation("`GetModuleFileNameW`")?;
let handle = this.read_machine_usize(handle)?; let handle = this.read_target_usize(handle)?;
let filename = this.read_pointer(filename)?; let filename = this.read_pointer(filename)?;
let size = this.read_scalar(size)?.to_u32()?; let size = this.read_scalar(size)?.to_u32()?;
@ -473,7 +473,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
"GetConsoleMode" if this.frame_in_std() => { "GetConsoleMode" if this.frame_in_std() => {
let [console, mode] = let [console, mode] =
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
this.read_machine_isize(console)?; this.read_target_isize(console)?;
this.deref_operand(mode)?; this.deref_operand(mode)?;
// Indicate an error. // Indicate an error.
this.write_null(dest)?; this.write_null(dest)?;

View file

@ -124,14 +124,14 @@ impl Handle {
// see https://docs.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication // see https://docs.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
#[allow(clippy::cast_possible_wrap)] // we want it to wrap #[allow(clippy::cast_possible_wrap)] // we want it to wrap
let signed_handle = self.to_packed() as i32; let signed_handle = self.to_packed() as i32;
Scalar::from_machine_isize(signed_handle.into(), cx) Scalar::from_target_isize(signed_handle.into(), cx)
} }
pub fn from_scalar<'tcx>( pub fn from_scalar<'tcx>(
handle: Scalar<Provenance>, handle: Scalar<Provenance>,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,
) -> InterpResult<'tcx, Option<Self>> { ) -> InterpResult<'tcx, Option<Self>> {
let sign_extended_handle = handle.to_machine_isize(cx)?; let sign_extended_handle = handle.to_target_isize(cx)?;
#[allow(clippy::cast_sign_loss)] // we want to lose the sign #[allow(clippy::cast_sign_loss)] // we want to lose the sign
let handle = if let Ok(signed_handle) = i32::try_from(sign_extended_handle) { let handle = if let Ok(signed_handle) = i32::try_from(sign_extended_handle) {

View file

@ -273,7 +273,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let ptr = this.read_pointer(ptr_op)?; let ptr = this.read_pointer(ptr_op)?;
let compare = this.read_pointer(compare_op)?; let compare = this.read_pointer(compare_op)?;
let size = this.read_machine_usize(size_op)?; let size = this.read_target_usize(size_op)?;
let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?; let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?;
let thread = this.get_active_thread(); let thread = this.get_active_thread();

View file

@ -21,7 +21,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let security = this.read_pointer(security_op)?; let security = this.read_pointer(security_op)?;
// stacksize is ignored, but still needs to be a valid usize // stacksize is ignored, but still needs to be a valid usize
this.read_machine_usize(stacksize_op)?; this.read_target_usize(stacksize_op)?;
let start_routine = this.read_pointer(start_op)?; let start_routine = this.read_pointer(start_op)?;
let func_arg = this.read_immediate(arg_op)?; let func_arg = this.read_immediate(arg_op)?;
let flags = this.read_scalar(flags_op)?.to_u32()?; let flags = this.read_scalar(flags_op)?.to_u32()?;

View file

@ -1,6 +1,6 @@
[package] [package]
name = "x" name = "x"
version = "0.1.0" version = "0.1.1"
description = "Run x.py slightly more conveniently" description = "Run x.py slightly more conveniently"
edition = "2021" edition = "2021"
publish = false publish = false

View file

@ -9,11 +9,47 @@
//! We also don't use `pwsh` on Windows, because it is not installed by default; //! We also don't use `pwsh` on Windows, because it is not installed by default;
use std::{ use std::{
env, io, env::{self, consts::EXE_EXTENSION},
io,
path::Path, path::Path,
process::{self, Command, ExitStatus}, process::{self, Command, ExitStatus},
}; };
const PYTHON: &str = "python";
const PYTHON2: &str = "python2";
const PYTHON3: &str = "python3";
fn python() -> &'static str {
let val = match env::var_os("PATH") {
Some(val) => val,
None => return PYTHON,
};
let mut python2 = false;
let mut python3 = false;
for dir in env::split_paths(&val) {
// `python` should always take precedence over python2 / python3 if it exists
if dir.join(PYTHON).with_extension(EXE_EXTENSION).exists() {
return PYTHON;
}
python2 |= dir.join(PYTHON2).with_extension(EXE_EXTENSION).exists();
python3 |= dir.join(PYTHON3).with_extension(EXE_EXTENSION).exists();
}
// try 3 before 2
if python3 {
PYTHON3
} else if python2 {
PYTHON2
} else {
// Python was not found on path, so exit
eprintln!("Unable to find python in your PATH. Please check it is installed.");
process::exit(1);
}
}
#[cfg(windows)] #[cfg(windows)]
fn x_command(dir: &Path) -> Command { fn x_command(dir: &Path) -> Command {
let mut cmd = Command::new("powershell.exe"); let mut cmd = Command::new("powershell.exe");
@ -51,6 +87,17 @@ fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
command.status() command.status()
} }
fn handle_result(result: io::Result<ExitStatus>, cmd: Command) {
match result {
Err(error) => {
eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
}
Ok(status) => {
process::exit(status.code().unwrap_or(1));
}
}
}
fn main() { fn main() {
match env::args().skip(1).next().as_deref() { match env::args().skip(1).next().as_deref() {
Some("--wrapper-version") => { Some("--wrapper-version") => {
@ -70,22 +117,19 @@ fn main() {
for dir in current.ancestors() { for dir in current.ancestors() {
let candidate = dir.join("x.py"); let candidate = dir.join("x.py");
if candidate.exists() { if candidate.exists() {
let mut cmd = x_command(dir); let shell_script_candidate = dir.join("x");
let mut cmd: Command;
cmd.args(env::args().skip(1)).current_dir(dir); if shell_script_candidate.exists() {
cmd = x_command(dir);
let result = exec_or_status(&mut cmd); cmd.args(env::args().skip(1)).current_dir(dir);
} else {
match result { // For older checkouts that do not have the x shell script, default to python
Err(error) => { cmd = Command::new(python());
eprintln!("Failed to invoke `{:?}`: {}", cmd, error); cmd.arg(&candidate).args(env::args().skip(1)).current_dir(dir);
}
Ok(status) => {
process::exit(status.code().unwrap_or(1));
}
} }
let result = exec_or_status(&mut cmd);
handle_result(result, cmd);
} }
} }

View file

@ -33,7 +33,7 @@ LL | fn main<A: TraitWAssocConst<A=32>>() {
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in impl header
--> $DIR/issue-105330.rs:6:27 --> $DIR/issue-105330.rs:6:27
| |
LL | impl TraitWAssocConst for impl Demo { LL | impl TraitWAssocConst for impl Demo {

View file

@ -26,7 +26,7 @@ fn test_send_trait() {
//~| HELP: add a dummy let to cause `fptr` to be fully captured //~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20; *fptr.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0` //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
} }); } }).join().unwrap();
} }
/* Test Sync Trait Migration */ /* Test Sync Trait Migration */
@ -47,7 +47,7 @@ fn test_sync_trait() {
//~| HELP: add a dummy let to cause `fptr` to be fully captured //~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20; *fptr.0.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0` //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
} }); } }).join().unwrap();
} }
/* Test Clone Trait Migration */ /* Test Clone Trait Migration */

View file

@ -26,7 +26,7 @@ fn test_send_trait() {
//~| HELP: add a dummy let to cause `fptr` to be fully captured //~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20; *fptr.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0` //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
}); }).join().unwrap();
} }
/* Test Sync Trait Migration */ /* Test Sync Trait Migration */
@ -47,7 +47,7 @@ fn test_sync_trait() {
//~| HELP: add a dummy let to cause `fptr` to be fully captured //~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20; *fptr.0.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0` //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
}); }).join().unwrap();
} }
/* Test Clone Trait Migration */ /* Test Clone Trait Migration */

View file

@ -19,7 +19,7 @@ LL ~ thread::spawn(move || { let _ = &fptr; unsafe {
LL | LL |
... ...
LL | LL |
LL ~ } }); LL ~ } }).join().unwrap();
| |
error: changes to closure capture in Rust 2021 will affect which traits the closure implements error: changes to closure capture in Rust 2021 will affect which traits the closure implements
@ -41,7 +41,7 @@ LL ~ thread::spawn(move || { let _ = &fptr; unsafe {
LL | LL |
... ...
LL | LL |
LL ~ } }); LL ~ } }).join().unwrap();
| |
error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements

View file

@ -145,7 +145,7 @@ fn test_multi_traits_issues() {
//~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0` //~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
*fptr2.0 = 20; *fptr2.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0` //~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
} }); } }).join().unwrap();
} }
fn main() { fn main() {

View file

@ -141,7 +141,7 @@ fn test_multi_traits_issues() {
//~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0` //~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
*fptr2.0 = 20; *fptr2.0 = 20;
//~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0` //~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
}); }).join().unwrap();
} }
fn main() { fn main() {

View file

@ -111,7 +111,7 @@ LL ~ thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
LL | LL |
... ...
LL | LL |
LL ~ } }); LL ~ } }).join().unwrap();
| |
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

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