use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::Discr;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
-use rustc_middle::ty::{TypeFoldable, TypeVisitor};
use rustc_session::config::SanitizerSet;
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_target::spec::abi;
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
-use smallvec::SmallVec;
-
mod type_of;
struct OnlySelfBounds(bool);
}
}
- if tcx.features().const_evaluatable_checked {
- let const_evaluatable = const_evaluatable_predicates_of(tcx, def_id, &result);
- if !const_evaluatable.is_empty() {
- result.predicates = tcx
- .arena
- .alloc_from_iter(result.predicates.iter().copied().chain(const_evaluatable));
- }
- }
-
debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
result
}
-pub fn const_evaluatable_predicates_of<'tcx>(
- tcx: TyCtxt<'tcx>,
- def_id: DefId,
- predicates: &ty::GenericPredicates<'tcx>,
-) -> Vec<(ty::Predicate<'tcx>, Span)> {
- #[derive(Default)]
- struct ConstCollector<'tcx> {
- ct: SmallVec<[(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>, Span); 4]>,
- curr_span: Span,
- }
-
- impl<'tcx> TypeVisitor<'tcx> for ConstCollector<'tcx> {
- fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> bool {
- if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
- self.ct.push((def, substs, self.curr_span));
- }
- false
- }
- }
-
- let mut collector = ConstCollector::default();
- for &(pred, span) in predicates.predicates.iter() {
- collector.curr_span = span;
- pred.visit_with(&mut collector);
- }
-
- match tcx.def_kind(def_id) {
- DefKind::Fn | DefKind::AssocFn => {
- tcx.fn_sig(def_id).visit_with(&mut collector);
- }
- _ => (),
- }
- debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.ct);
-
- // We only want unique const evaluatable predicates.
- collector.ct.sort();
- collector.ct.dedup();
- collector
- .ct
- .into_iter()
- .map(move |(def_id, subst, span)| {
- (ty::PredicateAtom::ConstEvaluatable(def_id, subst).to_predicate(tcx), span)
- })
- .collect()
-}
-
/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
/// `Self: Trait` predicates for traits.
}))
}
+ if tcx.features().const_evaluatable_checked {
+ predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
+ }
+
let mut predicates: Vec<_> = predicates.into_iter().collect();
// Subtle: before we store the predicates into the tcx, we
result
}
+fn const_evaluatable_predicates_of<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+) -> FxIndexSet<(ty::Predicate<'tcx>, Span)> {
+ struct ConstCollector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>,
+ }
+
+ impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
+ type Map = Map<'tcx>;
+
+ fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+ intravisit::NestedVisitorMap::None
+ }
+
+ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+ let def_id = self.tcx.hir().local_def_id(c.hir_id);
+ let ct = ty::Const::from_anon_const(self.tcx, def_id);
+ if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
+ let span = self.tcx.hir().span(c.hir_id);
+ self.preds.insert((
+ ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
+ span,
+ ));
+ }
+ }
+
+ // Look into `TyAlias`.
+ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
+ use ty::fold::{TypeFoldable, TypeVisitor};
+ struct TyAliasVisitor<'a, 'tcx> {
+ tcx: TyCtxt<'tcx>,
+ preds: &'a mut FxIndexSet<(ty::Predicate<'tcx>, Span)>,
+ span: Span,
+ }
+
+ impl<'a, 'tcx> TypeVisitor<'tcx> for TyAliasVisitor<'a, 'tcx> {
+ fn visit_const(&mut self, ct: &'tcx Const<'tcx>) -> bool {
+ if let ty::ConstKind::Unevaluated(def, substs, None) = ct.val {
+ self.preds.insert((
+ ty::PredicateAtom::ConstEvaluatable(def, substs).to_predicate(self.tcx),
+ self.span,
+ ));
+ }
+ false
+ }
+ }
+
+ if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind {
+ if let Res::Def(DefKind::TyAlias, def_id) = path.res {
+ let mut visitor =
+ TyAliasVisitor { tcx: self.tcx, preds: &mut self.preds, span: path.span };
+ self.tcx.type_of(def_id).visit_with(&mut visitor);
+ }
+ }
+
+ intravisit::walk_ty(self, ty)
+ }
+ }
+
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let node = tcx.hir().get(hir_id);
+
+ let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
+ if let Some(generics) = node.generics() {
+ warn!("const_evaluatable_predicates_of({:?}): visit_generics", def_id);
+ collector.visit_generics(generics);
+ }
+
+ if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) {
+ warn!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id);
+ collector.visit_fn_decl(fn_sig.decl);
+ }
+ warn!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds);
+
+ collector.preds
+}
+
fn projection_ty_from_predicates(
tcx: TyCtxt<'tcx>,
key: (
LL | let _ = const_evaluatable_lib::test1::<T>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
+ ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:10
|
LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
- | ----- required by this bound in `test1`
+ | ---------------------------- required by this bound in `test1`
|
= note: this may fail depending on what value the parameter takes
LL | let _ = const_evaluatable_lib::test1::<T>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
+ ::: $DIR/auxiliary/const_evaluatable_lib.rs:4:27
|
-LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
- | ----- required by this bound in `test1`
+LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
+ | ---------------------------- required by this bound in `test1`
|
= note: this may fail depending on what value the parameter takes
LL | let _ = const_evaluatable_lib::test1::<T>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
+ ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:10
|
LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
- | ----- required by this bound in `test1::{{constant}}#1`
+ | ---------------------------- required by this bound in `test1::{{constant}}#1`
|
= note: this may fail depending on what value the parameter takes
LL | let _ = const_evaluatable_lib::test1::<T>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
+ ::: $DIR/auxiliary/const_evaluatable_lib.rs:4:27
|
-LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
- | ----- required by this bound in `test1::{{constant}}#1`
+LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
+ | ---------------------------- required by this bound in `test1::{{constant}}#1`
|
= note: this may fail depending on what value the parameter takes