Skip to content

Commit 56fd680

Browse files
committed
Auto merge of #96046 - oli-obk:const_typeck, r=cjgillot
Move various checks to typeck so them failing causes the typeck result to get tainted Fixes #69487 fixes #79047 cc `@RalfJung` this gets rid of the `Transmute` invalid program error variant
2 parents 4614711 + 4332c2f commit 56fd680

Some content is hidden

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

57 files changed

+875
-518
lines changed

compiler/rustc_const_eval/src/interpret/place.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -906,16 +906,12 @@ where
906906
}
907907
// We still require the sizes to match.
908908
if src.layout.size != dest.layout.size {
909-
// FIXME: This should be an assert instead of an error, but if we transmute within an
910-
// array length computation, `typeck` may not have yet been run and errored out. In fact
911-
// most likely we *are* running `typeck` right now. Investigate whether we can bail out
912-
// on `typeck_results().has_errors` at all const eval entry points.
913-
debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
914-
self.tcx.sess.delay_span_bug(
909+
span_bug!(
915910
self.cur_span(),
916-
"size-changing transmute, should have been caught by transmute checking",
911+
"size-changing transmute, should have been caught by transmute checking: {:#?}\ndest: {:#?}",
912+
src,
913+
dest
917914
);
918-
throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
919915
}
920916
// Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want
921917
// to avoid that here.

compiler/rustc_interface/src/passes.rs

-1
Original file line numberDiff line numberDiff line change
@@ -937,7 +937,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
937937
//
938938
// maybe move the check to a MIR pass?
939939
tcx.ensure().check_mod_liveness(module);
940-
tcx.ensure().check_mod_intrinsics(module);
941940
});
942941
});
943942
}

compiler/rustc_middle/src/mir/interpret/error.rs

-7
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,6 @@ pub enum InvalidProgramInfo<'tcx> {
149149
/// (which unfortunately typeck does not reject).
150150
/// Not using `FnAbiError` as that contains a nested `LayoutError`.
151151
FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError),
152-
/// An invalid transmute happened.
153-
TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
154152
/// SizeOf of unsized type was requested.
155153
SizeOfUnsizedType(Ty<'tcx>),
156154
}
@@ -166,11 +164,6 @@ impl fmt::Display for InvalidProgramInfo<'_> {
166164
}
167165
Layout(ref err) => write!(f, "{}", err),
168166
FnAbiAdjustForForeignAbi(ref err) => write!(f, "{}", err),
169-
TransmuteSizeDiff(from_ty, to_ty) => write!(
170-
f,
171-
"transmuting `{}` to `{}` is not possible, because these types do not have the same size",
172-
from_ty, to_ty
173-
),
174167
SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{}`", ty),
175168
}
176169
}

compiler/rustc_middle/src/query/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -804,10 +804,6 @@ rustc_queries! {
804804
desc { |tcx| "checking privacy in {}", describe_as_module(key, tcx) }
805805
}
806806

807-
query check_mod_intrinsics(key: LocalDefId) -> () {
808-
desc { |tcx| "checking intrinsics in {}", describe_as_module(key, tcx) }
809-
}
810-
811807
query check_mod_liveness(key: LocalDefId) -> () {
812808
desc { |tcx| "checking liveness of variables in {}", describe_as_module(key, tcx) }
813809
}

compiler/rustc_passes/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ mod diagnostic_items;
3030
pub mod entry;
3131
pub mod hir_id_validator;
3232
pub mod hir_stats;
33-
mod intrinsicck;
3433
mod lang_items;
3534
pub mod layout_test;
3635
mod lib_features;
@@ -54,7 +53,6 @@ pub fn provide(providers: &mut Providers) {
5453
loops::provide(providers);
5554
naked_functions::provide(providers);
5655
liveness::provide(providers);
57-
intrinsicck::provide(providers);
5856
reachable::provide(providers);
5957
stability::provide(providers);
6058
upvars::provide(providers);

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
273273
error: &SelectionError<'tcx>,
274274
fallback_has_occurred: bool,
275275
) {
276+
self.set_tainted_by_errors();
276277
let tcx = self.tcx;
277278
let mut span = obligation.cause.span;
278279

compiler/rustc_typeck/src/check/check.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::check::wfcheck::for_item;
2+
13
use super::coercion::CoerceMany;
24
use super::compare_method::check_type_bounds;
35
use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
@@ -871,6 +873,14 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
871873
}
872874
}
873875
}
876+
DefKind::GlobalAsm => {
877+
let it = tcx.hir().item(id);
878+
let hir::ItemKind::GlobalAsm(asm) = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) };
879+
for_item(tcx, it).with_fcx(|fcx| {
880+
fcx.check_asm(asm, it.hir_id());
881+
Default::default()
882+
})
883+
}
874884
_ => {}
875885
}
876886
}

compiler/rustc_typeck/src/check/expr.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use rustc_span::lev_distance::find_best_match_for_name;
5151
use rustc_span::source_map::Span;
5252
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5353
use rustc_span::{BytePos, Pos};
54+
use rustc_target::spec::abi::Abi::RustIntrinsic;
5455
use rustc_trait_selection::infer::InferCtxtExt;
5556
use rustc_trait_selection::traits::{self, ObligationCauseCode};
5657

@@ -294,7 +295,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
294295
self.check_lang_item_path(lang_item, expr, hir_id)
295296
}
296297
ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
297-
ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
298+
ExprKind::InlineAsm(asm) => {
299+
// We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars).
300+
self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id));
301+
self.check_expr_asm(asm)
302+
}
298303
ExprKind::Break(destination, ref expr_opt) => {
299304
self.check_expr_break(destination, expr_opt.as_deref(), expr)
300305
}
@@ -530,8 +535,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
530535
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
531536
};
532537

533-
if let ty::FnDef(..) = ty.kind() {
538+
if let ty::FnDef(did, ..) = *ty.kind() {
534539
let fn_sig = ty.fn_sig(tcx);
540+
if tcx.fn_sig(did).abi() == RustIntrinsic && tcx.item_name(did) == sym::transmute {
541+
let from = fn_sig.inputs().skip_binder()[0];
542+
let to = fn_sig.output().skip_binder();
543+
// We defer the transmute to the end of typeck, once all inference vars have
544+
// been resolved or we errored. This is important as we can only check transmute
545+
// on concrete types, but the output type may not be known yet (it would only
546+
// be known if explicitly specified via turbofish).
547+
self.deferred_transmute_checks.borrow_mut().push((from, to, expr.span));
548+
}
535549
if !tcx.features().unsized_fn_params {
536550
// We want to remove some Sized bounds from std functions,
537551
// but don't want to expose the removal to stable Rust.

compiler/rustc_typeck/src/check/fn_ctxt/checks.rs

+17
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4747
}
4848
}
4949

50+
pub(in super::super) fn check_transmutes(&self) {
51+
let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
52+
debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
53+
for (from, to, span) in deferred_transmute_checks.drain(..) {
54+
self.check_transmute(span, from, to);
55+
}
56+
}
57+
58+
pub(in super::super) fn check_asms(&self) {
59+
let mut deferred_asm_checks = self.deferred_asm_checks.borrow_mut();
60+
debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
61+
for (asm, hir_id) in deferred_asm_checks.drain(..) {
62+
let enclosing_id = self.tcx.hir().enclosing_body_owner(hir_id);
63+
self.check_asm(asm, enclosing_id);
64+
}
65+
}
66+
5067
pub(in super::super) fn check_method_argument_types(
5168
&self,
5269
sp: Span,

compiler/rustc_typeck/src/check/inherited.rs

+6
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ pub struct Inherited<'a, 'tcx> {
5050

5151
pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>,
5252

53+
pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, Span)>>,
54+
55+
pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
56+
5357
pub(super) deferred_generator_interiors:
5458
RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
5559

@@ -113,6 +117,8 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
113117
deferred_sized_obligations: RefCell::new(Vec::new()),
114118
deferred_call_resolutions: RefCell::new(Default::default()),
115119
deferred_cast_checks: RefCell::new(Vec::new()),
120+
deferred_transmute_checks: RefCell::new(Vec::new()),
121+
deferred_asm_checks: RefCell::new(Vec::new()),
116122
deferred_generator_interiors: RefCell::new(Vec::new()),
117123
diverging_type_vars: RefCell::new(Default::default()),
118124
body_id,

0 commit comments

Comments
 (0)