Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 4 pull requests #64012

Closed
wants to merge 18 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .mailmap
Original file line number Diff line number Diff line change
@@ -184,12 +184,19 @@ Neil Pankey <[email protected]> <[email protected]>
Nick Platt <[email protected]>
Nicole Mazzuca <[email protected]>
Nif Ward <[email protected]>
Oliver Schneider <[email protected]> oli-obk <[email protected]>
Oliver Schneider <[email protected]> Oliver 'ker' Schneider <[email protected]>
Oliver Schneider <[email protected]> Oliver Schneider <[email protected]>
Oliver Schneider <[email protected]> Oliver Schneider <[email protected]>
Oliver Schneider <[email protected]> Oliver Schneider <[email protected]>
Oliver Schneider <[email protected]> Oliver Schneider <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]> <[email protected]>
Oliver Scherer <[email protected]>
Ožbolt Menegatti <[email protected]> gareins <[email protected]>
Paul Faria <[email protected]> Paul Faria <[email protected]>
Peer Aramillo Irizar <[email protected]> parir <[email protected]>
2 changes: 1 addition & 1 deletion src/liballoc/collections/linked_list.rs
Original file line number Diff line number Diff line change
@@ -276,7 +276,7 @@ impl<T> LinkedList<T> {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> Self {
pub const fn new() -> Self {
LinkedList {
head: None,
tail: None,
9 changes: 9 additions & 0 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
@@ -215,6 +215,15 @@ fn print_backtrace(backtrace: &mut Backtrace) {
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
}

impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
fn from(err: ErrorHandled) -> Self {
match err {
ErrorHandled::Reported => err_inval!(ReferencedConstant),
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
}.into()
}
}

impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
fn from(kind: InterpError<'tcx>) -> Self {
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
9 changes: 0 additions & 9 deletions src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
@@ -463,15 +463,6 @@ rustc_queries! {
no_force
desc { "extract field of const" }
}

/// Produces an absolute path representation of the given type. See also the documentation
/// on `std::any::type_name`.
query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
eval_always
no_force
desc { "get absolute path of type" }
}

}

TypeChecking {
36 changes: 13 additions & 23 deletions src/librustc_codegen_llvm/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ use rustc_codegen_ssa::glue;
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
use rustc::ty::{self, Ty};
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
use rustc::mir::interpret::GlobalId;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc::hir;
use syntax::ast::{self, FloatTy};
@@ -81,13 +82,14 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
fn codegen_intrinsic_call(
&mut self,
callee_ty: Ty<'tcx>,
instance: ty::Instance<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, &'ll Value>],
llresult: &'ll Value,
span: Span,
) {
let tcx = self.tcx;
let callee_ty = instance.ty(tcx);

let (def_id, substs) = match callee_ty.sty {
ty::FnDef(def_id, substs) => (def_id, substs),
@@ -133,10 +135,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
self.call(llfn, &[], None)
}
"size_of" => {
let tp_ty = substs.type_at(0);
self.const_usize(self.size_of(tp_ty).bytes())
}
"va_start" => {
self.va_start(args[0].immediate())
}
@@ -188,10 +186,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
self.const_usize(self.size_of(tp_ty).bytes())
}
}
"min_align_of" => {
let tp_ty = substs.type_at(0);
self.const_usize(self.align_of(tp_ty).bytes())
}
"min_align_of_val" => {
let tp_ty = substs.type_at(0);
if let OperandValue::Pair(_, meta) = args[0].val {
@@ -201,18 +195,19 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
self.const_usize(self.align_of(tp_ty).bytes())
}
}
"pref_align_of" => {
let tp_ty = substs.type_at(0);
self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
}
"size_of" |
"pref_align_of" |
"min_align_of" |
"needs_drop" |
"type_id" |
"type_name" => {
let tp_ty = substs.type_at(0);
let ty_name = self.tcx.type_name(tp_ty);
let gid = GlobalId {
instance,
promoted: None,
};
let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
}
"type_id" => {
self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
}
"init" => {
let ty = substs.type_at(0);
if !self.layout_of(ty).is_zst() {
@@ -235,11 +230,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
"uninit" | "forget" => {
return;
}
"needs_drop" => {
let tp_ty = substs.type_at(0);

self.const_bool(self.type_needs_drop(tp_ty))
}
"offset" => {
let ptr = args[0].immediate();
let offset = args[1].immediate();
3 changes: 1 addition & 2 deletions src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
@@ -668,8 +668,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}).collect();


let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest,
terminator.source_info.span);

if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
4 changes: 2 additions & 2 deletions src/librustc_codegen_ssa/traits/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::BackendTypes;
use crate::mir::operand::OperandRef;
use rustc::ty::Ty;
use rustc::ty::{self, Ty};
use rustc_target::abi::call::FnType;
use syntax_pos::Span;

@@ -10,7 +10,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
/// add them to librustc_codegen_llvm/context.rs
fn codegen_intrinsic_call(
&mut self,
callee_ty: Ty<'tcx>,
instance: ty::Instance<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'tcx, Self::Value>],
llresult: Self::Value,
122 changes: 70 additions & 52 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ use rustc::ty::{self, Ty, TyCtxt, subst::Subst};
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
use rustc::traits::Reveal;
use rustc_data_structures::fx::FxHashMap;
use crate::interpret::eval_nullary_intrinsic;

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

@@ -604,6 +605,23 @@ pub fn const_eval_provider<'tcx>(
other => return other,
}
}

// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
let ty = key.value.instance.ty(tcx);
let substs = match ty.sty {
ty::FnDef(_, substs) => substs,
_ => bug!("intrinsic with type {:?}", ty),
};
return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs)
.map_err(|error| {
let span = tcx.def_span(def_id);
let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
})
}

tcx.const_eval_raw(key).and_then(|val| {
validate_and_turn_into_const(tcx, val, key)
})
@@ -666,63 +684,63 @@ pub fn const_eval_raw_provider<'tcx>(
})
}).map_err(|error| {
let err = error_to_const_error(&ecx, error);
// errors in statics are always emitted as fatal errors
if tcx.is_static(def_id) {
// Ensure that if the above error was either `TooGeneric` or `Reported`
// an error must be reported.
// errors in statics are always emitted as fatal errors
if tcx.is_static(def_id) {
// Ensure that if the above error was either `TooGeneric` or `Reported`
// an error must be reported.
let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
tcx.sess.delay_span_bug(
err.span,
&format!("static eval failure did not emit an error: {:#?}", v)
);
v
} else if def_id.is_local() {
// constant defined in this crate, we can figure out a lint level!
match tcx.def_kind(def_id) {
// constants never produce a hard error at the definition site. Anything else is
// a backwards compatibility hazard (and will break old versions of winapi for sure)
//
// note that validation may still cause a hard error on this very same constant,
// because any code that existed before validation could not have failed validation
// thus preventing such a hard error from being a backwards compatibility hazard
Some(DefKind::Const) | Some(DefKind::AssocConst) => {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
tcx.sess.delay_span_bug(
err.span,
&format!("static eval failure did not emit an error: {:#?}", v)
);
v
} else if def_id.is_local() {
// constant defined in this crate, we can figure out a lint level!
match tcx.def_kind(def_id) {
// constants never produce a hard error at the definition site. Anything else is
// a backwards compatibility hazard (and will break old versions of winapi for sure)
//
// note that validation may still cause a hard error on this very same constant,
// because any code that existed before validation could not have failed validation
// thus preventing such a hard error from being a backwards compatibility hazard
Some(DefKind::Const) | Some(DefKind::AssocConst) => {
let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
err.report_as_lint(
tcx.at(tcx.def_span(def_id)),
"any use of this value will cause an error",
hir_id,
Some(err.span),
)
},
// promoting runtime code is only allowed to error if it references broken constants
// any other kind of error will be reported to the user as a deny-by-default lint
_ => if let Some(p) = cid.promoted {
let span = tcx.promoted_mir(def_id)[p].span;
if let err_inval!(ReferencedConstant) = err.error {
err.report_as_error(
tcx.at(span),
"evaluation of constant expression failed",
)
} else {
err.report_as_lint(
tcx.at(tcx.def_span(def_id)),
"any use of this value will cause an error",
hir_id,
tcx.at(span),
"reaching this expression at runtime will panic or abort",
tcx.hir().as_local_hir_id(def_id).unwrap(),
Some(err.span),
)
},
// promoting runtime code is only allowed to error if it references broken constants
// any other kind of error will be reported to the user as a deny-by-default lint
_ => if let Some(p) = cid.promoted {
let span = tcx.promoted_mir(def_id)[p].span;
if let err_inval!(ReferencedConstant) = err.error {
err.report_as_error(
tcx.at(span),
"evaluation of constant expression failed",
)
} else {
err.report_as_lint(
tcx.at(span),
"reaching this expression at runtime will panic or abort",
tcx.hir().as_local_hir_id(def_id).unwrap(),
Some(err.span),
)
}
// anything else (array lengths, enum initializers, constant patterns) are reported
// as hard errors
} else {
err.report_as_error(
}
// anything else (array lengths, enum initializers, constant patterns) are reported
// as hard errors
} else {
err.report_as_error(
ecx.tcx,
"evaluation of constant value failed",
)
},
}
} else {
// use of broken constant from other crate
err.report_as_error(ecx.tcx, "could not evaluate constant")
"evaluation of constant value failed",
)
},
}
} else {
// use of broken constant from other crate
err.report_as_error(ecx.tcx, "could not evaluate constant")
}
})
}
10 changes: 1 addition & 9 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::query::TyCtxtAt;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::mir::interpret::{
ErrorHandled,
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
InterpResult, truncate, sign_extend,
};
@@ -669,14 +668,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Our result will later be validated anyway, and there seems no good reason
// to have to fail early here. This is also more consistent with
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
match err {
ErrorHandled::Reported =>
err_inval!(ReferencedConstant),
ErrorHandled::TooGeneric =>
err_inval!(TooGeneric),
}
})?;
let val = self.tcx.const_eval_raw(param_env.and(gid))?;
self.raw_const_to_mplace(val)
}

Loading