summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_const_eval/src/transform/check_consts
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_const_eval/src/transform/check_consts')
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs81
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs18
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs20
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs24
4 files changed, 61 insertions, 82 deletions
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 22a61774e..54213d55a 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -10,14 +10,11 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC
use rustc_middle::mir::*;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
-use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeVisitable};
+use rustc_middle::ty::{Binder, TraitRef, TypeVisitable};
use rustc_mir_dataflow::{self, Analysis};
use rustc_span::{sym, Span, Symbol};
-use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{
- self, ObligationCauseCode, SelectionContext, TraitEngine, TraitEngineExt,
-};
+use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
use std::mem;
use std::ops::Deref;
@@ -452,8 +449,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
| Rvalue::CopyForDeref(..)
| Rvalue::Repeat(..)
| Rvalue::Discriminant(..)
- | Rvalue::Len(_)
- | Rvalue::Aggregate(..) => {}
+ | Rvalue::Len(_) => {}
+
+ Rvalue::Aggregate(ref kind, ..) => {
+ if let AggregateKind::Generator(def_id, ..) = kind.as_ref() {
+ if let Some(generator_kind) = self.tcx.generator_kind(def_id.to_def_id()) {
+ if matches!(generator_kind, hir::GeneratorKind::Async(..)) {
+ self.check_op(ops::Generator(generator_kind));
+ }
+ }
+ }
+ }
Rvalue::Ref(_, kind @ BorrowKind::Mut { .. }, ref place)
| Rvalue::Ref(_, kind @ BorrowKind::Unique, ref place) => {
@@ -729,13 +735,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
let trait_ref = TraitRef::from_method(tcx, trait_id, substs);
- let poly_trait_pred = Binder::dummy(TraitPredicate {
- trait_ref,
- constness: ty::BoundConstness::ConstIfConst,
- polarity: ty::ImplPolarity::Positive,
- });
+ let poly_trait_pred =
+ Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst);
let obligation =
- Obligation::new(ObligationCause::dummy(), param_env, poly_trait_pred);
+ Obligation::new(tcx, ObligationCause::dummy(), param_env, poly_trait_pred);
let implsrc = {
let infcx = tcx.infer_ctxt().build();
@@ -747,37 +750,27 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// "non-const" check. This is required for correctness here.
{
let infcx = tcx.infer_ctxt().build();
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ let ocx = ObligationCtxt::new(&infcx);
+
let predicates = tcx.predicates_of(callee).instantiate(tcx, substs);
let hir_id = tcx
.hir()
.local_def_id_to_hir_id(self.body.source.def_id().expect_local());
- let cause = || {
- ObligationCause::new(
- terminator.source_info.span,
- hir_id,
- ObligationCauseCode::ItemObligation(callee),
- )
- };
- let normalized = infcx.partially_normalize_associated_types_in(
- cause(),
- param_env,
- predicates,
+ let cause = ObligationCause::new(
+ terminator.source_info.span,
+ hir_id,
+ ObligationCauseCode::ItemObligation(callee),
);
-
- for p in normalized.obligations {
- fulfill_cx.register_predicate_obligation(&infcx, p);
- }
- for obligation in traits::predicates_for_generics(
- |_, _| cause(),
+ let normalized_predicates = ocx.normalize(&cause, param_env, predicates);
+ ocx.register_obligations(traits::predicates_for_generics(
+ |_, _| cause.clone(),
self.param_env,
- normalized.value,
- ) {
- fulfill_cx.register_predicate_obligation(&infcx, obligation);
- }
- let errors = fulfill_cx.select_all_or_error(&infcx);
+ normalized_predicates,
+ ));
+
+ let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None);
}
}
@@ -828,11 +821,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
if !nonconst_call_permission {
let obligation = Obligation::new(
+ tcx,
ObligationCause::dummy_with_span(*fn_span),
param_env,
- tcx.mk_predicate(
- poly_trait_pred.map_bound(ty::PredicateKind::Trait),
- ),
+ poly_trait_pred,
);
// improve diagnostics by showing what failed. Our requirements are stricter this time
@@ -843,7 +835,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
obligation.clone(),
&obligation,
&e,
- false,
);
}
@@ -901,14 +892,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
return;
}
- // `async` blocks get lowered to `std::future::from_generator(/* a closure */)`.
- let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn();
- if is_async_block {
- let kind = hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block);
- self.check_op(ops::Generator(kind));
- return;
- }
-
if !tcx.is_const_fn_raw(callee) {
if !tcx.is_const_default_method(callee) {
// To get to here we must have already found a const impl for the
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index 25b420bed..655ec345e 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -62,7 +62,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
}
fn is_async(&self) -> bool {
- self.tcx.asyncness(self.def_id()) == hir::IsAsync::Async
+ self.tcx.asyncness(self.def_id()).is_async()
}
}
@@ -75,14 +75,14 @@ pub fn rustc_allow_const_fn_unstable(
attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate)
}
-// Returns `true` if the given `const fn` is "const-stable".
-//
-// Panics if the given `DefId` does not refer to a `const fn`.
-//
-// Const-stability is only relevant for `const fn` within a `staged_api` crate. Only "const-stable"
-// functions can be called in a const-context by users of the stable compiler. "const-stable"
-// functions are subject to more stringent restrictions than "const-unstable" functions: They
-// cannot use unstable features and can only call other "const-stable" functions.
+/// Returns `true` if the given `const fn` is "const-stable".
+///
+/// Panics if the given `DefId` does not refer to a `const fn`.
+///
+/// Const-stability is only relevant for `const fn` within a `staged_api` crate. Only "const-stable"
+/// functions can be called in a const-context by users of the stable compiler. "const-stable"
+/// functions are subject to more stringent restrictions than "const-unstable" functions: They
+/// cannot use unstable features and can only call other "const-stable" functions.
pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
// A default body in a `#[const_trait]` is not const-stable because const
// trait fns currently cannot be const-stable. We shouldn't
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index b28d70194..b19d270e6 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -1,7 +1,7 @@
//! Concrete error types for all operations which may be invalid in a certain const context.
use hir::def_id::LocalDefId;
-use hir::ConstContext;
+use hir::{ConstContext, LangItem};
use rustc_errors::{
error_code, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
};
@@ -13,10 +13,9 @@ use rustc_middle::mir;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{
- suggest_constraining_type_param, Adt, Closure, DefIdTree, FnDef, FnPtr, Param, TraitPredicate,
- Ty,
+ suggest_constraining_type_param, Adt, Closure, DefIdTree, FnDef, FnPtr, Param, Ty,
};
-use rustc_middle::ty::{Binder, BoundConstness, ImplPolarity, TraitRef};
+use rustc_middle::ty::{Binder, TraitRef};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{BytePos, Pos, Span, Symbol};
@@ -147,13 +146,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
}
Adt(..) => {
let obligation = Obligation::new(
+ tcx,
ObligationCause::dummy(),
param_env,
- Binder::dummy(TraitPredicate {
- trait_ref,
- constness: BoundConstness::NotConst,
- polarity: ImplPolarity::Positive,
- }),
+ Binder::dummy(trait_ref),
);
let infcx = tcx.infer_ctxt().build();
@@ -303,7 +299,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
err.span_note(deref_target, "deref defined here");
}
- diag_trait(&mut err, self_ty, tcx.lang_items().deref_trait().unwrap());
+ diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
err
}
_ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
@@ -380,7 +376,7 @@ impl<'tcx> NonConstOp<'tcx> for Generator {
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind());
+ let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
ccx.tcx.sess.create_feature_err(
UnallowedOpInConstContext { span, msg },
@@ -690,7 +686,7 @@ impl<'tcx> NonConstOp<'tcx> for ThreadLocalAccess {
}
}
-// Types that cannot appear in the signature or locals of a `const fn`.
+/// Types that cannot appear in the signature or locals of a `const fn`.
pub mod ty {
use super::*;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 335992342..8ca3fdf40 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -146,25 +146,19 @@ impl Qualif for NeedsNonConstDrop {
qualifs.needs_non_const_drop
}
+ #[instrument(level = "trace", skip(cx), ret)]
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
// Avoid selecting for simple cases, such as builtin types.
if ty::util::is_trivially_const_drop(ty) {
return false;
}
- let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None);
-
let obligation = Obligation::new(
- ObligationCause::dummy(),
+ cx.tcx,
+ ObligationCause::dummy_with_span(cx.body.span),
cx.param_env,
- ty::Binder::dummy(ty::TraitPredicate {
- trait_ref: ty::TraitRef {
- def_id: destruct,
- substs: cx.tcx.mk_substs_trait(ty, &[]),
- },
- constness: ty::BoundConstness::ConstIfConst,
- polarity: ty::ImplPolarity::Positive,
- }),
+ ty::Binder::dummy(cx.tcx.at(cx.body.span).mk_trait_ref(LangItem::Destruct, [ty]))
+ .with_constness(ty::BoundConstness::ConstIfConst),
);
let infcx = cx.tcx.infer_ctxt().build();
@@ -174,6 +168,8 @@ impl Qualif for NeedsNonConstDrop {
return true;
};
+ trace!(?impl_src);
+
if !matches!(
impl_src,
ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
@@ -348,7 +344,11 @@ where
// FIXME(valtrees): check whether const qualifs should behave the same
// way for type and mir constants.
let uneval = match constant.literal {
- ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None,
+ ConstantKind::Ty(ct)
+ if matches!(ct.kind(), ty::ConstKind::Param(_) | ty::ConstKind::Error(_)) =>
+ {
+ None
+ }
ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c),
ConstantKind::Unevaluated(uv, _) => Some(uv),
ConstantKind::Val(..) => None,