Skip to content

Commit

Permalink
Make x.py check work
Browse files Browse the repository at this point in the history
  • Loading branch information
eholk committed Sep 13, 2022
1 parent ddfcca4 commit 3c2d20e
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 134 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,10 @@ fn codegen_stmt<'tcx>(
let operand = codegen_operand(fx, operand);
operand.unsize_value(fx, lval);
}
Rvalue::Cast(CastKind::DynStar, _, _) => {
// FIXME(dyn-star)
unimplemented!()
}
Rvalue::Discriminant(place) => {
let place = codegen_place(fx, place);
let value = place.to_cvalue(fx);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/value_and_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ pub(crate) fn assert_assignable<'tcx>(
);
// fn(&T) -> for<'l> fn(&'l T) is allowed
}
(&ty::Dynamic(from_traits, _), &ty::Dynamic(to_traits, _)) => {
(&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => {
for (from, to) in from_traits.iter().zip(to_traits) {
let from =
fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Ref(_, _, _)
| ty::FnDef(_, _)
| ty::FnPtr(_)
| ty::Dynamic(_, _)
| ty::Dynamic(_, _, _)
| ty::Closure(_, _)
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
})
}
ty::Dynamic(data, _, ty::TraitObjectRepresentation::Unsized) => {
ty::Dynamic(data, _, ty::Dyn) => {
data.iter().find_map(|pred| {
if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
&& Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
Expand Down
29 changes: 20 additions & 9 deletions src/tools/clippy/clippy_lints/src/transmute/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty::{cast::CastKind, Ty};
use rustc_span::DUMMY_SP;
use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited};
use rustc_typeck::check::{
cast::{self, CastCheckResult},
FnCtxt, Inherited,
};

// check if the component types of the transmuted collection and the result have different ABI,
// size or alignment
pub(super) fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<'tcx>) -> bool {
pub(super) fn is_layout_incompatible<'tcx>(
cx: &LateContext<'tcx>,
from: Ty<'tcx>,
to: Ty<'tcx>,
) -> bool {
if let Ok(from) = cx.tcx.try_normalize_erasing_regions(cx.param_env, from)
&& let Ok(to) = cx.tcx.try_normalize_erasing_regions(cx.param_env, to)
&& let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from))
Expand All @@ -29,7 +36,9 @@ pub(super) fn can_be_expressed_as_pointer_cast<'tcx>(
from_ty: Ty<'tcx>,
to_ty: Ty<'tcx>,
) -> bool {
use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
use CastKind::{
AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast,
};
matches!(
check_cast(cx, e, from_ty, to_ty),
Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast)
Expand All @@ -40,20 +49,22 @@ pub(super) fn can_be_expressed_as_pointer_cast<'tcx>(
/// the cast. In certain cases, including some invalid casts from array references
/// to pointers, this may cause additional errors to be emitted and/or ICE error
/// messages. This function will panic if that occurs.
fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option<CastKind> {
fn check_cast<'tcx>(
cx: &LateContext<'tcx>,
e: &'tcx Expr<'_>,
from_ty: Ty<'tcx>,
to_ty: Ty<'tcx>,
) -> Option<CastKind> {
let hir_id = e.hir_id;
let local_def_id = hir_id.owner;

Inherited::build(cx.tcx, local_def_id).enter(|inherited| {
let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, hir_id);

// If we already have errors, we can't be sure we can pointer cast.
assert!(
!fn_ctxt.errors_reported_since_creation(),
"Newly created FnCtxt contained errors"
);
assert!(!fn_ctxt.errors_reported_since_creation(), "Newly created FnCtxt contained errors");

if let Ok(check) = CastCheck::new(
if let CastCheckResult::Deferred(check) = cast::check_cast(
&fn_ctxt, e, from_ty, to_ty,
// We won't show any error to the user, so we don't care what the span is here.
DUMMY_SP, DUMMY_SP,
Expand Down
141 changes: 86 additions & 55 deletions src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ use std::borrow::Cow;

type McfResult = Result<(), (Span, Cow<'static, str>)>;

pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option<RustcVersion>) -> McfResult {
pub fn is_min_const_fn<'a, 'tcx>(
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
msrv: Option<RustcVersion>,
) -> McfResult {
let def_id = body.source.def_id();
let mut current = def_id;
loop {
Expand All @@ -33,10 +37,18 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv:
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Trait(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {:#?}", predicate),
ty::PredicateKind::ObjectSafe(_) => {
panic!("object safe predicate on function: {:#?}", predicate)
}
ty::PredicateKind::ClosureKind(..) => {
panic!("closure kind predicate on function: {:#?}", predicate)
}
ty::PredicateKind::Subtype(_) => {
panic!("subtype predicate on function: {:#?}", predicate)
}
ty::PredicateKind::Coerce(_) => {
panic!("coerce predicate on function: {:#?}", predicate)
}
}
}
match predicates.parent {
Expand Down Expand Up @@ -77,22 +89,23 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
match ty.kind() {
ty::Ref(_, _, hir::Mutability::Mut) => {
return Err((span, "mutable references in const fn are unstable".into()));
},
}
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
ty::FnPtr(..) => {
return Err((span, "function pointers in const fn are unstable".into()));
},
ty::Dynamic(preds, _) => {
}
ty::Dynamic(preds, _, _) => {
for pred in preds.iter() {
match pred.skip_binder() {
ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => {
ty::ExistentialPredicate::AutoTrait(_)
| ty::ExistentialPredicate::Projection(_) => {
return Err((
span,
"trait bounds other than `Sized` \
on const fn parameters are unstable"
.into(),
));
},
}
ty::ExistentialPredicate::Trait(trait_ref) => {
if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() {
return Err((
Expand All @@ -102,11 +115,11 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
.into(),
));
}
},
}
}
}
},
_ => {},
}
_ => {}
}
}
Ok(())
Expand All @@ -120,10 +133,13 @@ fn check_rvalue<'tcx>(
span: Span,
) -> McfResult {
match rvalue {
Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())),
Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
check_place(tcx, *place, span, body)
},
Rvalue::ThreadLocalRef(_) => {
Err((span, "cannot access thread local storage in const fn".into()))
}
Rvalue::Len(place)
| Rvalue::Discriminant(place)
| Rvalue::Ref(_, _, place)
| Rvalue::AddressOf(_, place) => check_place(tcx, *place, span, body),
Rvalue::CopyForDeref(place) => check_place(tcx, *place, span, body),
Rvalue::Repeat(operand, _)
| Rvalue::Use(operand)
Expand All @@ -136,7 +152,9 @@ fn check_rvalue<'tcx>(
) => check_operand(tcx, operand, span, body),
Rvalue::Cast(
CastKind::Pointer(
PointerCast::UnsafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer,
PointerCast::UnsafeFnPointer
| PointerCast::ClosureFnPointer(_)
| PointerCast::ReifyFnPointer,
),
_,
_,
Expand All @@ -146,7 +164,10 @@ fn check_rvalue<'tcx>(
deref_ty.ty
} else {
// We cannot allow this for now.
return Err((span, "unsizing casts are only allowed for references right now".into()));
return Err((
span,
"unsizing casts are only allowed for references right now".into(),
));
};
let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
Expand All @@ -157,10 +178,14 @@ fn check_rvalue<'tcx>(
// We just can't allow trait objects until we have figured out trait method calls.
Err((span, "unsizing casts are not allowed in const fn".into()))
}
},
}
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
Err((span, "casting pointers to ints is unstable in const fn".into()))
},
}
Rvalue::Cast(CastKind::DynStar, _, _) => {
// FIXME(dyn-star)
unimplemented!()
}
// binops are fine on integers
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
check_operand(tcx, lhs, span, body)?;
Expand All @@ -169,27 +194,26 @@ fn check_rvalue<'tcx>(
if ty.is_integral() || ty.is_bool() || ty.is_char() {
Ok(())
} else {
Err((
span,
"only int, `bool` and `char` operations are stable in const fn".into(),
))
Err((span, "only int, `bool` and `char` operations are stable in const fn".into()))
}
},
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => Ok(()),
}
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::ShallowInitBox(_, _) => {
Ok(())
}
Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(body, tcx);
if ty.is_integral() || ty.is_bool() {
check_operand(tcx, operand, span, body)
} else {
Err((span, "only int and `bool` operations are stable in const fn".into()))
}
},
}
Rvalue::Aggregate(_, operands) => {
for operand in operands {
check_operand(tcx, operand, span, body)?;
}
Ok(())
},
}
}
}

Expand All @@ -204,7 +228,7 @@ fn check_statement<'tcx>(
StatementKind::Assign(box (place, rval)) => {
check_place(tcx, *place, span, body)?;
check_rvalue(tcx, body, def_id, rval, span)
},
}

StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body),
// just an assignment
Expand All @@ -214,14 +238,15 @@ fn check_statement<'tcx>(

StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => check_operand(tcx, op, span, body),

StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
rustc_middle::mir::CopyNonOverlapping { dst, src, count },
)) => {
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
dst,
src,
count,
}) => {
check_operand(tcx, dst, span, body)?;
check_operand(tcx, src, span, body)?;
check_operand(tcx, count, span, body)
},

}
// These are all NOPs
StatementKind::StorageLive(_)
| StatementKind::StorageDead(_)
Expand All @@ -232,7 +257,12 @@ fn check_statement<'tcx>(
}
}

fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
fn check_operand<'tcx>(
tcx: TyCtxt<'tcx>,
operand: &Operand<'tcx>,
span: Span,
body: &Body<'tcx>,
) -> McfResult {
match operand {
Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body),
Operand::Constant(c) => match c.check_static_ptr(tcx) {
Expand All @@ -242,7 +272,12 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b
}
}

fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
fn check_place<'tcx>(
tcx: TyCtxt<'tcx>,
place: Place<'tcx>,
span: Span,
body: &Body<'tcx>,
) -> McfResult {
let mut cursor = place.projection.as_ref();
while let [ref proj_base @ .., elem] = *cursor {
cursor = proj_base;
Expand All @@ -255,12 +290,12 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B
return Err((span, "accessing union fields is unstable".into()));
}
}
},
}
ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Downcast(..)
| ProjectionElem::Subslice { .. }
| ProjectionElem::Deref
| ProjectionElem::Index(_) => {},
| ProjectionElem::Index(_) => {}
}
}

Expand All @@ -286,18 +321,16 @@ fn check_terminator<'a, 'tcx>(
TerminatorKind::DropAndReplace { place, value, .. } => {
check_place(tcx, *place, span, body)?;
check_operand(tcx, value, span, body)
},
}

TerminatorKind::SwitchInt {
discr,
switch_ty: _,
targets: _,
} => check_operand(tcx, discr, span, body),
TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
check_operand(tcx, discr, span, body)
}

TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
Err((span, "const fn generators are unstable".into()))
},
}

TerminatorKind::Call {
func,
Expand Down Expand Up @@ -342,17 +375,15 @@ fn check_terminator<'a, 'tcx>(
} else {
Err((span, "can only call other const fns within const fn".into()))
}
},
}

TerminatorKind::Assert {
cond,
expected: _,
msg: _,
target: _,
cleanup: _,
} => check_operand(tcx, cond, span, body),
TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => {
check_operand(tcx, cond, span, body)
}

TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
TerminatorKind::InlineAsm { .. } => {
Err((span, "cannot use inline assembly in const fn".into()))
}
}
}

Expand Down
Loading

0 comments on commit 3c2d20e

Please sign in to comment.