Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ff39457

Browse files
committed
avoid raising interpreter errors from interning
1 parent 8e48a30 commit ff39457

File tree

8 files changed

+50
-30
lines changed

8 files changed

+50
-30
lines changed

src/librustc_mir/const_eval/eval_queries.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
6666
intern_kind,
6767
ret,
6868
body.ignore_interior_mut_in_const_validation,
69-
)?;
69+
);
7070

7171
debug!("eval_body_using_ecx done: {:?}", *ret);
7272
Ok(ret)

src/librustc_mir/const_eval/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub(crate) fn const_caller_location(
5353
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
5454

5555
let loc_place = ecx.alloc_caller_location(file, line, col);
56-
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap();
56+
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false);
5757
ConstValue::Scalar(loc_place.ptr)
5858
}
5959

src/librustc_mir/interpret/intern.rs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55
66
use super::validity::RefTracking;
77
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
8-
use rustc_errors::ErrorReported;
98
use rustc_hir as hir;
10-
use rustc_middle::mir::interpret::{ErrorHandled, InterpResult};
9+
use rustc_middle::mir::interpret::InterpResult;
1110
use rustc_middle::ty::{self, query::TyCtxtAt, Ty};
1211

1312
use rustc_ast::ast::Mutability;
@@ -64,6 +63,7 @@ enum InternMode {
6463
struct IsStaticOrFn;
6564

6665
fn mutable_memory_in_const(tcx: TyCtxtAt<'_>, kind: &str) {
66+
// FIXME: show this in validation instead so we can point at where in the value the error is?
6767
tcx.sess.span_err(tcx.span, &format!("mutable memory ({}) is not allowed in constant", kind));
6868
}
6969

@@ -79,7 +79,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
7979
alloc_id: AllocId,
8080
mode: InternMode,
8181
ty: Option<Ty<'tcx>>,
82-
) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
82+
) -> Option<IsStaticOrFn> {
8383
trace!("intern_shallow {:?} with {:?}", alloc_id, mode);
8484
// remove allocation
8585
let tcx = ecx.tcx;
@@ -97,7 +97,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
9797
}
9898
// treat dangling pointers like other statics
9999
// just to stop trying to recurse into them
100-
return Ok(Some(IsStaticOrFn));
100+
return Some(IsStaticOrFn);
101101
}
102102
};
103103
// This match is just a canary for future changes to `MemoryKind`, which most likely need
@@ -136,7 +136,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
136136
let alloc = tcx.intern_const_alloc(alloc);
137137
leftover_allocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc));
138138
tcx.set_alloc_id_memory(alloc_id, alloc);
139-
Ok(None)
139+
None
140140
}
141141

142142
impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir, 'tcx, M> {
@@ -145,7 +145,7 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir
145145
alloc_id: AllocId,
146146
mode: InternMode,
147147
ty: Option<Ty<'tcx>>,
148-
) -> InterpResult<'tcx, Option<IsStaticOrFn>> {
148+
) -> Option<IsStaticOrFn> {
149149
intern_shallow(
150150
self.ecx,
151151
self.leftover_allocations,
@@ -213,7 +213,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
213213
if let Scalar::Ptr(vtable) = mplace.meta.unwrap_meta() {
214214
// Explicitly choose const mode here, since vtables are immutable, even
215215
// if the reference of the fat pointer is mutable.
216-
self.intern_shallow(vtable.alloc_id, InternMode::ConstInner, None)?;
216+
self.intern_shallow(vtable.alloc_id, InternMode::ConstInner, None);
217217
} else {
218218
// Let validation show the error message, but make sure it *does* error.
219219
tcx.sess.delay_span_bug(
@@ -277,7 +277,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
277277
InternMode::ConstInner
278278
}
279279
};
280-
match self.intern_shallow(ptr.alloc_id, ref_mode, Some(referenced_ty))? {
280+
match self.intern_shallow(ptr.alloc_id, ref_mode, Some(referenced_ty)) {
281281
// No need to recurse, these are interned already and statics may have
282282
// cycles, so we don't want to recurse there
283283
Some(IsStaticOrFn) => {}
@@ -304,12 +304,18 @@ pub enum InternKind {
304304
ConstProp,
305305
}
306306

307+
/// Intern `ret` and everything it references.
308+
///
309+
/// This *cannot raise an interpreter error*. Doing so is left to validation, which
310+
/// trakcs where in the value we are and thus can show much better error messages.
311+
/// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
312+
/// are hard errors.
307313
pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
308314
ecx: &mut InterpCx<'mir, 'tcx, M>,
309315
intern_kind: InternKind,
310316
ret: MPlaceTy<'tcx>,
311317
ignore_interior_mut_in_const: bool,
312-
) -> InterpResult<'tcx>
318+
)
313319
where
314320
'tcx: 'mir,
315321
{
@@ -338,7 +344,7 @@ where
338344
ret.ptr.assert_ptr().alloc_id,
339345
base_intern_mode,
340346
Some(ret.layout.ty),
341-
)?;
347+
);
342348

343349
ref_tracking.track((ret, base_intern_mode), || ());
344350

@@ -422,13 +428,16 @@ where
422428
}
423429
}
424430
} else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
425-
// dangling pointer
426-
throw_ub_format!("encountered dangling pointer in final constant")
431+
// Codegen does not like dangling pointers, and generally `tcx` assumes that
432+
// all allocations referenced anywhere actually exist. So, make sure we error here.
433+
ecx.tcx.sess.span_err(
434+
ecx.tcx.span,
435+
"encountered dangling pointer in final constant",
436+
);
427437
} else if ecx.tcx.get_global_alloc(alloc_id).is_none() {
428-
// We have hit an `AllocId` that is neither in local or global memory and isn't marked
429-
// as dangling by local memory.
438+
// We have hit an `AllocId` that is neither in local or global memory and isn't
439+
// marked as dangling by local memory. That should be impossible.
430440
span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id);
431441
}
432442
}
433-
Ok(())
434443
}

src/librustc_mir/transform/const_prop.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,8 +702,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
702702
)) => l.is_bits() && r.is_bits(),
703703
interpret::Operand::Indirect(_) if mir_opt_level >= 2 => {
704704
let mplace = op.assert_mem_place(&self.ecx);
705-
intern_const_alloc_recursive(&mut self.ecx, InternKind::ConstProp, mplace, false)
706-
.expect("failed to intern alloc");
705+
intern_const_alloc_recursive(&mut self.ecx, InternKind::ConstProp, mplace, false);
707706
true
708707
}
709708
_ => false,

src/test/ui/consts/dangling-alloc-id-ice.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
// https://github.com/rust-lang/rust/issues/55223
2+
#![allow(const_err)]
23

34
union Foo<'a> {
45
y: &'a (),
56
long_live_the_unit: &'static (),
67
}
78

8-
const FOO: &() = { //~ ERROR any use of this value will cause an error
9+
const FOO: &() = { //~ ERROR it is undefined behavior to use this value
10+
//~^ ERROR encountered dangling pointer in final constant
911
let y = ();
1012
unsafe { Foo { y: &y }.long_live_the_unit }
1113
};
Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
1-
error: any use of this value will cause an error
2-
--> $DIR/dangling-alloc-id-ice.rs:8:1
1+
error: encountered dangling pointer in final constant
2+
--> $DIR/dangling-alloc-id-ice.rs:9:1
33
|
44
LL | / const FOO: &() = {
5+
LL | |
56
LL | | let y = ();
67
LL | | unsafe { Foo { y: &y }.long_live_the_unit }
78
LL | | };
8-
| |__^ encountered dangling pointer in final constant
9+
| |__^
10+
11+
error[E0080]: it is undefined behavior to use this value
12+
--> $DIR/dangling-alloc-id-ice.rs:9:1
13+
|
14+
LL | / const FOO: &() = {
15+
LL | |
16+
LL | | let y = ();
17+
LL | | unsafe { Foo { y: &y }.long_live_the_unit }
18+
LL | | };
19+
| |__^ type validation failed: encountered a dangling reference (use-after-free)
920
|
10-
= note: `#[deny(const_err)]` on by default
21+
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
1122

12-
error: aborting due to previous error
23+
error: aborting due to 2 previous errors
1324

25+
For more information about this error, try `rustc --explain E0080`.

src/test/ui/consts/dangling_raw_ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const FOO: *const u32 = { //~ ERROR any use of this value will cause an error
1+
const FOO: *const u32 = { //~ ERROR encountered dangling pointer in final constant
22
let x = 42;
33
&x
44
};
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
error: any use of this value will cause an error
1+
error: encountered dangling pointer in final constant
22
--> $DIR/dangling_raw_ptr.rs:1:1
33
|
44
LL | / const FOO: *const u32 = {
55
LL | | let x = 42;
66
LL | | &x
77
LL | | };
8-
| |__^ encountered dangling pointer in final constant
9-
|
10-
= note: `#[deny(const_err)]` on by default
8+
| |__^
119

1210
error: aborting due to previous error
1311

0 commit comments

Comments
 (0)