Skip to content

Commit 1ddbcc8

Browse files
authored
Rollup merge of rust-lang#61626 - oli-obk:const_eval_intrinsics, r=eddyb
Get rid of special const intrinsic query in favour of `const_eval` r? @eddyb
2 parents ef1ecbe + 612af94 commit 1ddbcc8

File tree

13 files changed

+184
-154
lines changed

13 files changed

+184
-154
lines changed

src/librustc/mir/interpret/error.rs

+9
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,15 @@ fn print_backtrace(backtrace: &mut Backtrace) {
215215
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
216216
}
217217

218+
impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
219+
fn from(err: ErrorHandled) -> Self {
220+
match err {
221+
ErrorHandled::Reported => err_inval!(ReferencedConstant),
222+
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
223+
}.into()
224+
}
225+
}
226+
218227
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
219228
fn from(kind: InterpError<'tcx>) -> Self {
220229
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {

src/librustc/query/mod.rs

-9
Original file line numberDiff line numberDiff line change
@@ -449,15 +449,6 @@ rustc_queries! {
449449
no_force
450450
desc { "extract field of const" }
451451
}
452-
453-
/// Produces an absolute path representation of the given type. See also the documentation
454-
/// on `std::any::type_name`.
455-
query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
456-
eval_always
457-
no_force
458-
desc { "get absolute path of type" }
459-
}
460-
461452
}
462453

463454
TypeChecking {

src/librustc_codegen_llvm/intrinsic.rs

+13-23
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc_codegen_ssa::glue;
1515
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
1616
use rustc::ty::{self, Ty};
1717
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
18+
use rustc::mir::interpret::GlobalId;
1819
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
1920
use rustc::hir;
2021
use syntax::ast::{self, FloatTy};
@@ -81,13 +82,14 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu
8182
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
8283
fn codegen_intrinsic_call(
8384
&mut self,
84-
callee_ty: Ty<'tcx>,
85+
instance: ty::Instance<'tcx>,
8586
fn_ty: &FnType<'tcx, Ty<'tcx>>,
8687
args: &[OperandRef<'tcx, &'ll Value>],
8788
llresult: &'ll Value,
8889
span: Span,
8990
) {
9091
let tcx = self.tcx;
92+
let callee_ty = instance.ty(tcx);
9193

9294
let (def_id, substs) = match callee_ty.sty {
9395
ty::FnDef(def_id, substs) => (def_id, substs),
@@ -133,10 +135,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
133135
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
134136
self.call(llfn, &[], None)
135137
}
136-
"size_of" => {
137-
let tp_ty = substs.type_at(0);
138-
self.const_usize(self.size_of(tp_ty).bytes())
139-
}
140138
"va_start" => {
141139
self.va_start(args[0].immediate())
142140
}
@@ -188,10 +186,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
188186
self.const_usize(self.size_of(tp_ty).bytes())
189187
}
190188
}
191-
"min_align_of" => {
192-
let tp_ty = substs.type_at(0);
193-
self.const_usize(self.align_of(tp_ty).bytes())
194-
}
195189
"min_align_of_val" => {
196190
let tp_ty = substs.type_at(0);
197191
if let OperandValue::Pair(_, meta) = args[0].val {
@@ -201,18 +195,19 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
201195
self.const_usize(self.align_of(tp_ty).bytes())
202196
}
203197
}
204-
"pref_align_of" => {
205-
let tp_ty = substs.type_at(0);
206-
self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
207-
}
198+
"size_of" |
199+
"pref_align_of" |
200+
"min_align_of" |
201+
"needs_drop" |
202+
"type_id" |
208203
"type_name" => {
209-
let tp_ty = substs.type_at(0);
210-
let ty_name = self.tcx.type_name(tp_ty);
204+
let gid = GlobalId {
205+
instance,
206+
promoted: None,
207+
};
208+
let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
211209
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
212210
}
213-
"type_id" => {
214-
self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
215-
}
216211
"init" => {
217212
let ty = substs.type_at(0);
218213
if !self.layout_of(ty).is_zst() {
@@ -235,11 +230,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
235230
"uninit" | "forget" => {
236231
return;
237232
}
238-
"needs_drop" => {
239-
let tp_ty = substs.type_at(0);
240-
241-
self.const_bool(self.type_needs_drop(tp_ty))
242-
}
243233
"offset" => {
244234
let ptr = args[0].immediate();
245235
let offset = args[1].immediate();

src/librustc_codegen_ssa/mir/block.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -666,8 +666,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
666666
}).collect();
667667

668668

669-
let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
670-
bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
669+
bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest,
671670
terminator.source_info.span);
672671

673672
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {

src/librustc_codegen_ssa/traits/intrinsic.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::BackendTypes;
22
use crate::mir::operand::OperandRef;
3-
use rustc::ty::Ty;
3+
use rustc::ty::{self, Ty};
44
use rustc_target::abi::call::FnType;
55
use syntax_pos::Span;
66

@@ -10,7 +10,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
1010
/// add them to librustc_codegen_llvm/context.rs
1111
fn codegen_intrinsic_call(
1212
&mut self,
13-
callee_ty: Ty<'tcx>,
13+
instance: ty::Instance<'tcx>,
1414
fn_ty: &FnType<'tcx, Ty<'tcx>>,
1515
args: &[OperandRef<'tcx, Self::Value>],
1616
llresult: Self::Value,

src/librustc_mir/const_eval.rs

+70-52
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc::ty::{self, Ty, TyCtxt, subst::Subst};
1515
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
1616
use rustc::traits::Reveal;
1717
use rustc_data_structures::fx::FxHashMap;
18+
use crate::interpret::eval_nullary_intrinsic;
1819

1920
use syntax::source_map::{Span, DUMMY_SP};
2021

@@ -612,6 +613,23 @@ pub fn const_eval_provider<'tcx>(
612613
other => return other,
613614
}
614615
}
616+
617+
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
618+
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
619+
if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
620+
let ty = key.value.instance.ty(tcx);
621+
let substs = match ty.sty {
622+
ty::FnDef(_, substs) => substs,
623+
_ => bug!("intrinsic with type {:?}", ty),
624+
};
625+
return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs)
626+
.map_err(|error| {
627+
let span = tcx.def_span(def_id);
628+
let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
629+
error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
630+
})
631+
}
632+
615633
tcx.const_eval_raw(key).and_then(|val| {
616634
validate_and_turn_into_const(tcx, val, key)
617635
})
@@ -680,63 +698,63 @@ pub fn const_eval_raw_provider<'tcx>(
680698
})
681699
}).map_err(|error| {
682700
let err = error_to_const_error(&ecx, error);
683-
// errors in statics are always emitted as fatal errors
684-
if tcx.is_static(def_id) {
685-
// Ensure that if the above error was either `TooGeneric` or `Reported`
686-
// an error must be reported.
701+
// errors in statics are always emitted as fatal errors
702+
if tcx.is_static(def_id) {
703+
// Ensure that if the above error was either `TooGeneric` or `Reported`
704+
// an error must be reported.
687705
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
688-
tcx.sess.delay_span_bug(
689-
err.span,
690-
&format!("static eval failure did not emit an error: {:#?}", v)
691-
);
692-
v
693-
} else if def_id.is_local() {
694-
// constant defined in this crate, we can figure out a lint level!
695-
match tcx.def_kind(def_id) {
696-
// constants never produce a hard error at the definition site. Anything else is
697-
// a backwards compatibility hazard (and will break old versions of winapi for sure)
698-
//
699-
// note that validation may still cause a hard error on this very same constant,
700-
// because any code that existed before validation could not have failed validation
701-
// thus preventing such a hard error from being a backwards compatibility hazard
702-
Some(DefKind::Const) | Some(DefKind::AssocConst) => {
703-
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
706+
tcx.sess.delay_span_bug(
707+
err.span,
708+
&format!("static eval failure did not emit an error: {:#?}", v)
709+
);
710+
v
711+
} else if def_id.is_local() {
712+
// constant defined in this crate, we can figure out a lint level!
713+
match tcx.def_kind(def_id) {
714+
// constants never produce a hard error at the definition site. Anything else is
715+
// a backwards compatibility hazard (and will break old versions of winapi for sure)
716+
//
717+
// note that validation may still cause a hard error on this very same constant,
718+
// because any code that existed before validation could not have failed validation
719+
// thus preventing such a hard error from being a backwards compatibility hazard
720+
Some(DefKind::Const) | Some(DefKind::AssocConst) => {
721+
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
722+
err.report_as_lint(
723+
tcx.at(tcx.def_span(def_id)),
724+
"any use of this value will cause an error",
725+
hir_id,
726+
Some(err.span),
727+
)
728+
},
729+
// promoting runtime code is only allowed to error if it references broken constants
730+
// any other kind of error will be reported to the user as a deny-by-default lint
731+
_ => if let Some(p) = cid.promoted {
732+
let span = tcx.promoted_mir(def_id)[p].span;
733+
if let err_inval!(ReferencedConstant) = err.error {
734+
err.report_as_error(
735+
tcx.at(span),
736+
"evaluation of constant expression failed",
737+
)
738+
} else {
704739
err.report_as_lint(
705-
tcx.at(tcx.def_span(def_id)),
706-
"any use of this value will cause an error",
707-
hir_id,
740+
tcx.at(span),
741+
"reaching this expression at runtime will panic or abort",
742+
tcx.hir().as_local_hir_id(def_id).unwrap(),
708743
Some(err.span),
709744
)
710-
},
711-
// promoting runtime code is only allowed to error if it references broken constants
712-
// any other kind of error will be reported to the user as a deny-by-default lint
713-
_ => if let Some(p) = cid.promoted {
714-
let span = tcx.promoted_mir(def_id)[p].span;
715-
if let err_inval!(ReferencedConstant) = err.error {
716-
err.report_as_error(
717-
tcx.at(span),
718-
"evaluation of constant expression failed",
719-
)
720-
} else {
721-
err.report_as_lint(
722-
tcx.at(span),
723-
"reaching this expression at runtime will panic or abort",
724-
tcx.hir().as_local_hir_id(def_id).unwrap(),
725-
Some(err.span),
726-
)
727-
}
728-
// anything else (array lengths, enum initializers, constant patterns) are reported
729-
// as hard errors
730-
} else {
731-
err.report_as_error(
745+
}
746+
// anything else (array lengths, enum initializers, constant patterns) are reported
747+
// as hard errors
748+
} else {
749+
err.report_as_error(
732750
ecx.tcx,
733-
"evaluation of constant value failed",
734-
)
735-
},
736-
}
737-
} else {
738-
// use of broken constant from other crate
739-
err.report_as_error(ecx.tcx, "could not evaluate constant")
751+
"evaluation of constant value failed",
752+
)
753+
},
740754
}
755+
} else {
756+
// use of broken constant from other crate
757+
err.report_as_error(ecx.tcx, "could not evaluate constant")
758+
}
741759
})
742760
}

src/librustc_mir/interpret/eval_context.rs

+1-9
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
1414
use rustc::ty::query::TyCtxtAt;
1515
use rustc_data_structures::indexed_vec::IndexVec;
1616
use rustc::mir::interpret::{
17-
ErrorHandled,
1817
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
1918
InterpResult, truncate, sign_extend,
2019
};
@@ -696,14 +695,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
696695
// Our result will later be validated anyway, and there seems no good reason
697696
// to have to fail early here. This is also more consistent with
698697
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
699-
let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
700-
match err {
701-
ErrorHandled::Reported =>
702-
err_inval!(ReferencedConstant),
703-
ErrorHandled::TooGeneric =>
704-
err_inval!(TooGeneric),
705-
}
706-
})?;
698+
let val = self.tcx.const_eval_raw(param_env.and(gid))?;
707699
self.raw_const_to_mplace(val)
708700
}
709701

0 commit comments

Comments
 (0)