diff --git a/Cargo.lock b/Cargo.lock index 9d726b240da..4bf5a31b566 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4132,6 +4132,7 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", + "rustc_trait_selection", "rustc_typeck", "tracing", ] diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index ce83dc1de78..85e584d5435 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -13,4 +13,5 @@ rustc_typeck = { path = "../rustc_typeck" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_trait_selection = { path = "../rustc_trait_selection" } tracing = "0.1" diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 66206ca46c3..3fade2c4437 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -18,15 +18,17 @@ use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind}; use rustc_middle::bug; use rustc_middle::hir::map::Map; use rustc_middle::middle::privacy::{AccessLevel, AccessLevels}; +use rustc_middle::mir::abstract_const::Node as ACNode; use rustc_middle::span_bug; use rustc_middle::ty::fold::TypeVisitor; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::{self, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::subst::{InternalSubsts, Subst}; +use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::hygiene::Transparency; use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; +use rustc_trait_selection::traits::const_evaluatable::{self, AbstractConst}; use std::marker::PhantomData; use std::ops::ControlFlow; @@ -112,19 +114,35 @@ where ty.visit_with(self) } ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE, - ty::PredicateKind::ConstEvaluatable(..) + ty::PredicateKind::ConstEvaluatable(defs, substs) if self.def_id_visitor.tcx().features().const_evaluatable_checked => { - // FIXME(const_evaluatable_checked): If the constant used here depends on a - // private function we may have to do something here... - // - // For now, let's just pretend that everything is fine. + let tcx = self.def_id_visitor.tcx(); + if let Ok(Some(ct)) = AbstractConst::new(tcx, defs, substs) { + self.visit_abstract_const_expr(tcx, ct)?; + } ControlFlow::CONTINUE } _ => bug!("unexpected predicate: {:?}", predicate), } } + fn visit_abstract_const_expr( + &mut self, + tcx: TyCtxt<'tcx>, + ct: AbstractConst<'tcx>, + ) -> ControlFlow { + const_evaluatable::walk_abstract_const(tcx, ct, |node| match node { + ACNode::Leaf(leaf) => { + let leaf = leaf.subst(tcx, ct.substs); + self.visit_const(leaf) + } + ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => { + ControlFlow::CONTINUE + } + }) + } + fn visit_predicates( &mut self, predicates: ty::GenericPredicates<'tcx>, @@ -241,6 +259,15 @@ where ty.super_visit_with(self) } } + + fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow { + self.visit_ty(c.ty)?; + let tcx = self.def_id_visitor.tcx(); + if let Ok(Some(ct)) = AbstractConst::from_const(tcx, c) { + self.visit_abstract_const_expr(tcx, ct)?; + } + ControlFlow::CONTINUE + } } fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index dbc40a2eb96..f7c0bafff05 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -6,7 +6,7 @@ pub mod auto_trait; mod chalk_fulfill; pub mod codegen; mod coherence; -mod const_evaluatable; +pub mod const_evaluatable; mod engine; pub mod error_reporting; mod fulfill; diff --git a/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.rs b/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.rs new file mode 100644 index 00000000000..9f457fbd346 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.rs @@ -0,0 +1,31 @@ +#![crate_type = "lib"] +#![feature(const_generics, const_evaluatable_checked)] +#![allow(incomplete_features)] + +pub struct Const; + +pub trait Trait { + type AssocTy; + fn assoc_fn() -> Self::AssocTy; +} + +impl Trait for Const +//~^ WARN private type +//~| WARN this was previously +//~| WARN private type +//~| WARN this was previously + +where + Const<{ my_const_fn(U) }>: , +{ + type AssocTy = Const<{ my_const_fn(U) }>; + //~^ ERROR private type + fn assoc_fn() -> Self::AssocTy { + Const + } +} + +const fn my_const_fn(val: u8) -> u8 { + // body of this function doesn't matter + val +} diff --git a/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.stderr b/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.stderr new file mode 100644 index 00000000000..842c22c5c67 --- /dev/null +++ b/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.stderr @@ -0,0 +1,43 @@ +warning: private type `fn(u8) -> u8 {my_const_fn}` in public interface (error E0446) + --> $DIR/eval-privacy.rs:12:1 + | +LL | / impl Trait for Const +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ + | + = note: `#[warn(private_in_public)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +warning: private type `fn(u8) -> u8 {my_const_fn}` in public interface (error E0446) + --> $DIR/eval-privacy.rs:12:1 + | +LL | / impl Trait for Const +LL | | +LL | | +LL | | +... | +LL | | } +LL | | } + | |_^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/eval-privacy.rs:21:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + +error: aborting due to previous error; 2 warnings emitted + +For more information about this error, try `rustc --explain E0446`.